/* * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * * This program is part of a stress test for ::Exacct and libexacct. * See README for details. */ /* Turn largefile support on. */ #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include static char *ea_errstr[] = { "EXR_OK", "EXR_SYSCALL_FAIL", "EXR_CORRUPT_FILE", "EXR_EOF", "EXR_NO_CREATOR", "EXR_INVALID_BUF", "EXR_NOTSUPP", "EXR_UNKN_VERSION", "EXR_INVALID_OBJ", }; #define LOGSZ 100 #define LINESZ 81 static char log[LOGSZ][LINESZ]; static int log_op, log_pos; static char *type_str(ea_object_type_t type) { switch (type & EXT_TYPE_MASK) { case EXT_NONE: return ("NONE"); case EXT_UINT8: return ("UINT8"); case EXT_UINT16: return ("UINT16"); case EXT_UINT32: return ("UINT32"); case EXT_UINT64: return ("UINT64"); case EXT_DOUBLE: return ("DOUBLE"); case EXT_STRING: return ("STRING"); case EXT_EXACCT_OBJECT: return ("OBJECT"); case EXT_RAW: return ("RAW"); case EXT_GROUP: return ("GROUP"); default: return ("INVALID"); } } static void logmsg(const char *msg, char dir, ea_file_t *f, ea_object_t *obj) { ea_file_impl_t *fi; off_t pos; char buf[LINESZ]; char posbuf[10]; fi = (ea_file_impl_t *)f; pos = ftello(fi->ef_fp); log_op++; if (fi->ef_ndeep < 0) { (void) strlcpy(posbuf, "0/0", sizeof (posbuf)); } else { (void) snprintf(posbuf, sizeof (posbuf), "%d/%d", fi->ef_depth[fi->ef_ndeep].efd_obj + 1, fi->ef_depth[fi->ef_ndeep].efd_nobjs); } (void) snprintf(log[log_pos], LINESZ, "%-6d %c off=0x%-5llx depth=%-2d pos=%-7s adv=0x%-3llx %s", log_op, dir, pos, fi->ef_ndeep, posbuf, fi->ef_advance, msg); if (obj != NULL) { if ((obj->eo_type & EXT_TYPE_MASK) == EXT_GROUP) { (void) snprintf(buf, LINESZ, " %s #%d len=%d", type_str(obj->eo_catalog), obj->eo_catalog & EXD_DATA_MASK, obj->eo_group.eg_nobjs); } else { (void) snprintf(buf, LINESZ, " %s #%d", type_str(obj->eo_catalog), obj->eo_catalog & EXD_DATA_MASK); } (void) strlcat(log[log_pos], buf, LINESZ); } log_pos = (log_pos + 1) % LOGSZ; } static void die(ea_file_t *f, const char *msg) { int i, l; char buf[LINESZ]; bzero(buf, sizeof (buf)); if (ea_error() == EXR_SYSCALL_FAIL) { (void) strlcat(buf, strerror(errno), sizeof (buf)); } (void) printf("\nError at offset 0x%lx: %s: %s %s\n", ftell(((ea_file_impl_t *)f)->ef_fp), msg, ea_errstr[ea_error()], buf); (void) printf("Last %d operations:\n", LOGSZ); for (i = LOGSZ, l = log_pos; i > 0; i--, l = (l + 1) % LOGSZ) { if (log[l][0] != '\0') { (void) printf("%s\n", log[l]); } } exit(1); } /* ARGSUSED */ static void stop(int sig) { exit(2); } static int do_reads(ea_file_t *f, char dir, int sz) { ea_object_t obj; unsigned char act; bzero(&obj, sizeof (obj)); while (sz--) { act = 0x01 << (lrand48() & 0x01); /* If reading backwards */ if (dir == 'B') { logmsg("> ea_previous_object", dir, f, NULL); if (ea_previous_object(f, &obj) == EO_ERROR) { if (ea_error() == EXR_EOF) { logmsg("! SOF", dir, f, NULL); return ('F'); } else { die(f, "ea_previous_object"); } } logmsg("< ea_previous_object", dir, f, NULL); } /* Do a ea_next_object 50% of the time */ if (act & 0x01) { logmsg("> ea_next_object", dir, f, NULL); if (ea_next_object(f, &obj) == EO_ERROR) { if (ea_error() == EXR_EOF) { logmsg("! EOF", dir, f, NULL); return (dir == 'F' ? 'B' : 'F'); } else { die(f, "ea_next_object"); } } logmsg("< ea_next_object", dir, f, NULL); } /* Do a ea_get_object 50% of the time */ if (act & 0x02) { logmsg("> ea_get_object", dir, f, NULL); if (ea_get_object(f, &obj) == EO_ERROR) { if (ea_error() == EXR_EOF) { logmsg("! EOF", dir, f, NULL); return (dir == 'F' ? 'B' : 'F'); } else { die(f, "ea_get_object"); } } logmsg("< ea_get_object", dir, f, &obj); (void) ea_free_item(&obj, EUP_ALLOC); } /* If reading backwards */ if (dir == 'B') { logmsg("> ea_previous_object", dir, f, NULL); if (ea_previous_object(f, &obj) == EO_ERROR) { if (ea_error() == EXR_EOF) { logmsg("! SOF", dir, f, NULL); return ('F'); } else { die(f, "ea_get_object"); } } logmsg("< ea_previous_object", dir, f, NULL); } } return (' '); } int main(int argc, char **argv) { int iters, maxsz, sz; char dir; ea_file_t f; (void) signal(SIGINT, stop); (void) signal(SIGTERM, stop); (void) signal(SIGHUP, stop); if (argc != 4) { (void) fprintf(stderr, "Usage: randtest \n"); return (2); } iters = atoi(argv[1]); maxsz = atoi(argv[2]); bzero(log, sizeof (log)); log_pos = log_op = 0; if (ea_open(&f, argv[3], NULL, EO_HEAD, O_RDONLY, 0) == -1) { perror("open failed"); return (1); } srand48((long)(gethrtime() & ~0L)); dir = 'F'; while (iters--) { if (dir == ' ') { dir = (lrand48() % 2) ? 'F' : 'B'; } sz = (lrand48() % maxsz) + 1; dir = do_reads(&f, dir, sz); } (void) ea_close(&f); return (0); }