xref: /onnv-gate/usr/src/cmd/perl/contrib/Sun/Solaris/Exacct/t/randtest.c (revision 12388:1bc8d55b0dfd)
10Sstevel@tonic-gate /*
2*12388SJohn.Sonnenschein@Sun.COM  * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * This program is part of a stress test for ::Exacct and libexacct.
50Sstevel@tonic-gate  * See README for details.
60Sstevel@tonic-gate  */
70Sstevel@tonic-gate 
80Sstevel@tonic-gate /* Turn largefile support on. */
90Sstevel@tonic-gate #define	_FILE_OFFSET_BITS 64
100Sstevel@tonic-gate 
110Sstevel@tonic-gate #include <stdlib.h>
120Sstevel@tonic-gate #include <stdio.h>
130Sstevel@tonic-gate #include <strings.h>
140Sstevel@tonic-gate #include <signal.h>
150Sstevel@tonic-gate #include <errno.h>
160Sstevel@tonic-gate #include <fcntl.h>
170Sstevel@tonic-gate #include <exacct.h>
180Sstevel@tonic-gate #include <exacct_impl.h>
190Sstevel@tonic-gate 
200Sstevel@tonic-gate static char *ea_errstr[] = {
210Sstevel@tonic-gate 	"EXR_OK",
220Sstevel@tonic-gate 	"EXR_SYSCALL_FAIL",
230Sstevel@tonic-gate 	"EXR_CORRUPT_FILE",
240Sstevel@tonic-gate 	"EXR_EOF",
250Sstevel@tonic-gate 	"EXR_NO_CREATOR",
260Sstevel@tonic-gate 	"EXR_INVALID_BUF",
270Sstevel@tonic-gate 	"EXR_NOTSUPP",
280Sstevel@tonic-gate 	"EXR_UNKN_VERSION",
290Sstevel@tonic-gate 	"EXR_INVALID_OBJ",
300Sstevel@tonic-gate };
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #define	LOGSZ 100
330Sstevel@tonic-gate #define	LINESZ 81
340Sstevel@tonic-gate static char log[LOGSZ][LINESZ];
350Sstevel@tonic-gate static int log_op, log_pos;
360Sstevel@tonic-gate 
type_str(ea_object_type_t type)370Sstevel@tonic-gate static char *type_str(ea_object_type_t type)
380Sstevel@tonic-gate {
390Sstevel@tonic-gate 	switch (type & EXT_TYPE_MASK) {
400Sstevel@tonic-gate 	case EXT_NONE:
410Sstevel@tonic-gate 		return ("NONE");
420Sstevel@tonic-gate 	case EXT_UINT8:
430Sstevel@tonic-gate 		return ("UINT8");
440Sstevel@tonic-gate 	case EXT_UINT16:
450Sstevel@tonic-gate 		return ("UINT16");
460Sstevel@tonic-gate 	case EXT_UINT32:
470Sstevel@tonic-gate 		return ("UINT32");
480Sstevel@tonic-gate 	case EXT_UINT64:
490Sstevel@tonic-gate 		return ("UINT64");
500Sstevel@tonic-gate 	case EXT_DOUBLE:
510Sstevel@tonic-gate 		return ("DOUBLE");
520Sstevel@tonic-gate 	case EXT_STRING:
530Sstevel@tonic-gate 		return ("STRING");
540Sstevel@tonic-gate 	case EXT_EXACCT_OBJECT:
550Sstevel@tonic-gate 		return ("OBJECT");
560Sstevel@tonic-gate 	case EXT_RAW:
570Sstevel@tonic-gate 		return ("RAW");
580Sstevel@tonic-gate 	case EXT_GROUP:
590Sstevel@tonic-gate 		return ("GROUP");
600Sstevel@tonic-gate 	default:
610Sstevel@tonic-gate 		return ("INVALID");
620Sstevel@tonic-gate 	}
630Sstevel@tonic-gate }
640Sstevel@tonic-gate 
logmsg(const char * msg,char dir,ea_file_t * f,ea_object_t * obj)650Sstevel@tonic-gate static void logmsg(const char *msg, char dir, ea_file_t *f, ea_object_t *obj)
660Sstevel@tonic-gate {
670Sstevel@tonic-gate 	ea_file_impl_t *fi;
680Sstevel@tonic-gate 	off_t pos;
690Sstevel@tonic-gate 	char buf[LINESZ];
700Sstevel@tonic-gate 	char posbuf[10];
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	fi = (ea_file_impl_t *)f;
730Sstevel@tonic-gate 	pos = ftello(fi->ef_fp);
740Sstevel@tonic-gate 	log_op++;
750Sstevel@tonic-gate 	if (fi->ef_ndeep < 0) {
760Sstevel@tonic-gate 		(void) strlcpy(posbuf, "0/0", sizeof (posbuf));
770Sstevel@tonic-gate 	} else {
780Sstevel@tonic-gate 		(void) snprintf(posbuf, sizeof (posbuf), "%d/%d",
790Sstevel@tonic-gate 		    fi->ef_depth[fi->ef_ndeep].efd_obj + 1,
800Sstevel@tonic-gate 		    fi->ef_depth[fi->ef_ndeep].efd_nobjs);
810Sstevel@tonic-gate 	}
820Sstevel@tonic-gate 	(void) snprintf(log[log_pos], LINESZ,
830Sstevel@tonic-gate 	    "%-6d %c off=0x%-5llx depth=%-2d pos=%-7s adv=0x%-3llx %s",
840Sstevel@tonic-gate 	    log_op, dir, pos, fi->ef_ndeep, posbuf, fi->ef_advance, msg);
850Sstevel@tonic-gate 	if (obj != NULL) {
860Sstevel@tonic-gate 		if ((obj->eo_type & EXT_TYPE_MASK) == EXT_GROUP) {
870Sstevel@tonic-gate 			(void) snprintf(buf, LINESZ, " %s #%d len=%d",
880Sstevel@tonic-gate 			    type_str(obj->eo_catalog),
890Sstevel@tonic-gate 			    obj->eo_catalog & EXD_DATA_MASK,
900Sstevel@tonic-gate 			    obj->eo_group.eg_nobjs);
910Sstevel@tonic-gate 		} else {
920Sstevel@tonic-gate 			(void) snprintf(buf, LINESZ, " %s #%d",
930Sstevel@tonic-gate 			    type_str(obj->eo_catalog),
940Sstevel@tonic-gate 			    obj->eo_catalog & EXD_DATA_MASK);
950Sstevel@tonic-gate 		}
960Sstevel@tonic-gate 		(void) strlcat(log[log_pos], buf, LINESZ);
970Sstevel@tonic-gate 	}
980Sstevel@tonic-gate 	log_pos = (log_pos + 1) % LOGSZ;
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate 
die(ea_file_t * f,const char * msg)1010Sstevel@tonic-gate static void die(ea_file_t *f, const char *msg)
1020Sstevel@tonic-gate {
1030Sstevel@tonic-gate 	int i, l;
1040Sstevel@tonic-gate 	char buf[LINESZ];
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	bzero(buf, sizeof (buf));
1070Sstevel@tonic-gate 	if (ea_error() == EXR_SYSCALL_FAIL) {
1080Sstevel@tonic-gate 		(void) strlcat(buf, strerror(errno), sizeof (buf));
1090Sstevel@tonic-gate 	}
1100Sstevel@tonic-gate 	(void) printf("\nError at offset 0x%lx: %s: %s %s\n",
1110Sstevel@tonic-gate 	    ftell(((ea_file_impl_t *)f)->ef_fp), msg,
1120Sstevel@tonic-gate 	    ea_errstr[ea_error()], buf);
1130Sstevel@tonic-gate 	(void) printf("Last %d operations:\n", LOGSZ);
1140Sstevel@tonic-gate 	for (i = LOGSZ, l = log_pos; i > 0; i--, l = (l + 1) % LOGSZ) {
1150Sstevel@tonic-gate 		if (log[l][0] != '\0') {
1160Sstevel@tonic-gate 			(void) printf("%s\n", log[l]);
1170Sstevel@tonic-gate 		}
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 	exit(1);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate /* ARGSUSED */
stop(int sig)1230Sstevel@tonic-gate static void stop(int sig)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate 	exit(2);
1260Sstevel@tonic-gate }
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate static int
do_reads(ea_file_t * f,char dir,int sz)1290Sstevel@tonic-gate do_reads(ea_file_t *f, char dir, int sz)
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate 	ea_object_t	obj;
1320Sstevel@tonic-gate 	unsigned char	act;
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	bzero(&obj, sizeof (obj));
1350Sstevel@tonic-gate 	while (sz--) {
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 		act = 0x01 << (lrand48() & 0x01);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 		/* If reading backwards */
1400Sstevel@tonic-gate 		if (dir == 'B') {
1410Sstevel@tonic-gate 			logmsg("> ea_previous_object", dir, f, NULL);
1420Sstevel@tonic-gate 			if (ea_previous_object(f, &obj) == EO_ERROR) {
1430Sstevel@tonic-gate 				if (ea_error() == EXR_EOF) {
1440Sstevel@tonic-gate 					logmsg("! SOF", dir, f, NULL);
1450Sstevel@tonic-gate 					return ('F');
1460Sstevel@tonic-gate 				} else {
1470Sstevel@tonic-gate 					die(f, "ea_previous_object");
1480Sstevel@tonic-gate 				}
1490Sstevel@tonic-gate 			}
1500Sstevel@tonic-gate 			logmsg("< ea_previous_object", dir, f, NULL);
1510Sstevel@tonic-gate 		}
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 		/* Do a ea_next_object 50% of the time */
1540Sstevel@tonic-gate 		if (act & 0x01) {
1550Sstevel@tonic-gate 			logmsg("> ea_next_object", dir, f, NULL);
1560Sstevel@tonic-gate 			if (ea_next_object(f, &obj) == EO_ERROR) {
1570Sstevel@tonic-gate 				if (ea_error() == EXR_EOF) {
1580Sstevel@tonic-gate 					logmsg("! EOF", dir, f, NULL);
1590Sstevel@tonic-gate 					return (dir == 'F' ? 'B' : 'F');
1600Sstevel@tonic-gate 				} else {
1610Sstevel@tonic-gate 					die(f, "ea_next_object");
1620Sstevel@tonic-gate 				}
1630Sstevel@tonic-gate 			}
1640Sstevel@tonic-gate 			logmsg("< ea_next_object", dir, f, NULL);
1650Sstevel@tonic-gate 		}
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 		/* Do a ea_get_object 50% of the time */
1680Sstevel@tonic-gate 		if (act & 0x02) {
1690Sstevel@tonic-gate 			logmsg("> ea_get_object", dir, f, NULL);
1700Sstevel@tonic-gate 			if (ea_get_object(f, &obj) == EO_ERROR) {
1710Sstevel@tonic-gate 				if (ea_error() == EXR_EOF) {
1720Sstevel@tonic-gate 					logmsg("! EOF", dir, f, NULL);
1730Sstevel@tonic-gate 					return (dir == 'F' ? 'B' : 'F');
1740Sstevel@tonic-gate 				} else {
1750Sstevel@tonic-gate 					die(f, "ea_get_object");
1760Sstevel@tonic-gate 				}
1770Sstevel@tonic-gate 			}
1780Sstevel@tonic-gate 			logmsg("< ea_get_object", dir, f, &obj);
1790Sstevel@tonic-gate 			(void) ea_free_item(&obj, EUP_ALLOC);
1800Sstevel@tonic-gate 		}
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 		/* If reading backwards */
1830Sstevel@tonic-gate 		if (dir == 'B') {
1840Sstevel@tonic-gate 			logmsg("> ea_previous_object", dir, f, NULL);
1850Sstevel@tonic-gate 			if (ea_previous_object(f, &obj) == EO_ERROR) {
1860Sstevel@tonic-gate 				if (ea_error() == EXR_EOF) {
1870Sstevel@tonic-gate 					logmsg("! SOF", dir, f, NULL);
1880Sstevel@tonic-gate 					return ('F');
1890Sstevel@tonic-gate 				} else {
1900Sstevel@tonic-gate 					die(f, "ea_get_object");
1910Sstevel@tonic-gate 				}
1920Sstevel@tonic-gate 			}
1930Sstevel@tonic-gate 			logmsg("< ea_previous_object", dir, f, NULL);
1940Sstevel@tonic-gate 		}
1950Sstevel@tonic-gate 	}
1960Sstevel@tonic-gate 	return (' ');
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate int
main(int argc,char ** argv)2000Sstevel@tonic-gate main(int argc, char **argv)
2010Sstevel@tonic-gate {
2020Sstevel@tonic-gate 	int		iters, maxsz, sz;
2030Sstevel@tonic-gate 	char		dir;
2040Sstevel@tonic-gate 	ea_file_t	f;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	(void) signal(SIGINT, stop);
2070Sstevel@tonic-gate 	(void) signal(SIGTERM, stop);
2080Sstevel@tonic-gate 	(void) signal(SIGHUP, stop);
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	if (argc != 4) {
2110Sstevel@tonic-gate 		(void) fprintf(stderr,
2120Sstevel@tonic-gate 		    "Usage: randtest <iters> <maxsz> <file>\n");
2130Sstevel@tonic-gate 		return (2);
2140Sstevel@tonic-gate 	}
2150Sstevel@tonic-gate 	iters = atoi(argv[1]);
2160Sstevel@tonic-gate 	maxsz = atoi(argv[2]);
2170Sstevel@tonic-gate 	bzero(log, sizeof (log));
2180Sstevel@tonic-gate 	log_pos = log_op = 0;
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	if (ea_open(&f, argv[3], NULL, EO_HEAD, O_RDONLY, 0) == -1) {
2210Sstevel@tonic-gate 		perror("open failed");
2220Sstevel@tonic-gate 		return (1);
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 	srand48((long)(gethrtime() & ~0L));
2250Sstevel@tonic-gate 	dir = 'F';
2260Sstevel@tonic-gate 	while (iters--) {
2270Sstevel@tonic-gate 		if (dir == ' ') {
2280Sstevel@tonic-gate 			dir = (lrand48() % 2) ? 'F' : 'B';
2290Sstevel@tonic-gate 		}
2300Sstevel@tonic-gate 		sz = (lrand48() % maxsz) + 1;
2310Sstevel@tonic-gate 		dir = do_reads(&f, dir, sz);
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 	(void) ea_close(&f);
2340Sstevel@tonic-gate 	return (0);
2350Sstevel@tonic-gate }
236