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