xref: /onnv-gate/usr/src/cmd/perl/contrib/Sun/Solaris/Exacct/t/randtest.c (revision 12388:1bc8d55b0dfd)
1 /*
2  * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3  *
4  * This program is part of a stress test for ::Exacct and libexacct.
5  * See README for details.
6  */
7 
8 /* Turn largefile support on. */
9 #define	_FILE_OFFSET_BITS 64
10 
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <strings.h>
14 #include <signal.h>
15 #include <errno.h>
16 #include <fcntl.h>
17 #include <exacct.h>
18 #include <exacct_impl.h>
19 
20 static char *ea_errstr[] = {
21 	"EXR_OK",
22 	"EXR_SYSCALL_FAIL",
23 	"EXR_CORRUPT_FILE",
24 	"EXR_EOF",
25 	"EXR_NO_CREATOR",
26 	"EXR_INVALID_BUF",
27 	"EXR_NOTSUPP",
28 	"EXR_UNKN_VERSION",
29 	"EXR_INVALID_OBJ",
30 };
31 
32 #define	LOGSZ 100
33 #define	LINESZ 81
34 static char log[LOGSZ][LINESZ];
35 static int log_op, log_pos;
36 
type_str(ea_object_type_t type)37 static char *type_str(ea_object_type_t type)
38 {
39 	switch (type & EXT_TYPE_MASK) {
40 	case EXT_NONE:
41 		return ("NONE");
42 	case EXT_UINT8:
43 		return ("UINT8");
44 	case EXT_UINT16:
45 		return ("UINT16");
46 	case EXT_UINT32:
47 		return ("UINT32");
48 	case EXT_UINT64:
49 		return ("UINT64");
50 	case EXT_DOUBLE:
51 		return ("DOUBLE");
52 	case EXT_STRING:
53 		return ("STRING");
54 	case EXT_EXACCT_OBJECT:
55 		return ("OBJECT");
56 	case EXT_RAW:
57 		return ("RAW");
58 	case EXT_GROUP:
59 		return ("GROUP");
60 	default:
61 		return ("INVALID");
62 	}
63 }
64 
logmsg(const char * msg,char dir,ea_file_t * f,ea_object_t * obj)65 static void logmsg(const char *msg, char dir, ea_file_t *f, ea_object_t *obj)
66 {
67 	ea_file_impl_t *fi;
68 	off_t pos;
69 	char buf[LINESZ];
70 	char posbuf[10];
71 
72 	fi = (ea_file_impl_t *)f;
73 	pos = ftello(fi->ef_fp);
74 	log_op++;
75 	if (fi->ef_ndeep < 0) {
76 		(void) strlcpy(posbuf, "0/0", sizeof (posbuf));
77 	} else {
78 		(void) snprintf(posbuf, sizeof (posbuf), "%d/%d",
79 		    fi->ef_depth[fi->ef_ndeep].efd_obj + 1,
80 		    fi->ef_depth[fi->ef_ndeep].efd_nobjs);
81 	}
82 	(void) snprintf(log[log_pos], LINESZ,
83 	    "%-6d %c off=0x%-5llx depth=%-2d pos=%-7s adv=0x%-3llx %s",
84 	    log_op, dir, pos, fi->ef_ndeep, posbuf, fi->ef_advance, msg);
85 	if (obj != NULL) {
86 		if ((obj->eo_type & EXT_TYPE_MASK) == EXT_GROUP) {
87 			(void) snprintf(buf, LINESZ, " %s #%d len=%d",
88 			    type_str(obj->eo_catalog),
89 			    obj->eo_catalog & EXD_DATA_MASK,
90 			    obj->eo_group.eg_nobjs);
91 		} else {
92 			(void) snprintf(buf, LINESZ, " %s #%d",
93 			    type_str(obj->eo_catalog),
94 			    obj->eo_catalog & EXD_DATA_MASK);
95 		}
96 		(void) strlcat(log[log_pos], buf, LINESZ);
97 	}
98 	log_pos = (log_pos + 1) % LOGSZ;
99 }
100 
die(ea_file_t * f,const char * msg)101 static void die(ea_file_t *f, const char *msg)
102 {
103 	int i, l;
104 	char buf[LINESZ];
105 
106 	bzero(buf, sizeof (buf));
107 	if (ea_error() == EXR_SYSCALL_FAIL) {
108 		(void) strlcat(buf, strerror(errno), sizeof (buf));
109 	}
110 	(void) printf("\nError at offset 0x%lx: %s: %s %s\n",
111 	    ftell(((ea_file_impl_t *)f)->ef_fp), msg,
112 	    ea_errstr[ea_error()], buf);
113 	(void) printf("Last %d operations:\n", LOGSZ);
114 	for (i = LOGSZ, l = log_pos; i > 0; i--, l = (l + 1) % LOGSZ) {
115 		if (log[l][0] != '\0') {
116 			(void) printf("%s\n", log[l]);
117 		}
118 	}
119 	exit(1);
120 }
121 
122 /* ARGSUSED */
stop(int sig)123 static void stop(int sig)
124 {
125 	exit(2);
126 }
127 
128 static int
do_reads(ea_file_t * f,char dir,int sz)129 do_reads(ea_file_t *f, char dir, int sz)
130 {
131 	ea_object_t	obj;
132 	unsigned char	act;
133 
134 	bzero(&obj, sizeof (obj));
135 	while (sz--) {
136 
137 		act = 0x01 << (lrand48() & 0x01);
138 
139 		/* If reading backwards */
140 		if (dir == 'B') {
141 			logmsg("> ea_previous_object", dir, f, NULL);
142 			if (ea_previous_object(f, &obj) == EO_ERROR) {
143 				if (ea_error() == EXR_EOF) {
144 					logmsg("! SOF", dir, f, NULL);
145 					return ('F');
146 				} else {
147 					die(f, "ea_previous_object");
148 				}
149 			}
150 			logmsg("< ea_previous_object", dir, f, NULL);
151 		}
152 
153 		/* Do a ea_next_object 50% of the time */
154 		if (act & 0x01) {
155 			logmsg("> ea_next_object", dir, f, NULL);
156 			if (ea_next_object(f, &obj) == EO_ERROR) {
157 				if (ea_error() == EXR_EOF) {
158 					logmsg("! EOF", dir, f, NULL);
159 					return (dir == 'F' ? 'B' : 'F');
160 				} else {
161 					die(f, "ea_next_object");
162 				}
163 			}
164 			logmsg("< ea_next_object", dir, f, NULL);
165 		}
166 
167 		/* Do a ea_get_object 50% of the time */
168 		if (act & 0x02) {
169 			logmsg("> ea_get_object", dir, f, NULL);
170 			if (ea_get_object(f, &obj) == EO_ERROR) {
171 				if (ea_error() == EXR_EOF) {
172 					logmsg("! EOF", dir, f, NULL);
173 					return (dir == 'F' ? 'B' : 'F');
174 				} else {
175 					die(f, "ea_get_object");
176 				}
177 			}
178 			logmsg("< ea_get_object", dir, f, &obj);
179 			(void) ea_free_item(&obj, EUP_ALLOC);
180 		}
181 
182 		/* If reading backwards */
183 		if (dir == 'B') {
184 			logmsg("> ea_previous_object", dir, f, NULL);
185 			if (ea_previous_object(f, &obj) == EO_ERROR) {
186 				if (ea_error() == EXR_EOF) {
187 					logmsg("! SOF", dir, f, NULL);
188 					return ('F');
189 				} else {
190 					die(f, "ea_get_object");
191 				}
192 			}
193 			logmsg("< ea_previous_object", dir, f, NULL);
194 		}
195 	}
196 	return (' ');
197 }
198 
199 int
main(int argc,char ** argv)200 main(int argc, char **argv)
201 {
202 	int		iters, maxsz, sz;
203 	char		dir;
204 	ea_file_t	f;
205 
206 	(void) signal(SIGINT, stop);
207 	(void) signal(SIGTERM, stop);
208 	(void) signal(SIGHUP, stop);
209 
210 	if (argc != 4) {
211 		(void) fprintf(stderr,
212 		    "Usage: randtest <iters> <maxsz> <file>\n");
213 		return (2);
214 	}
215 	iters = atoi(argv[1]);
216 	maxsz = atoi(argv[2]);
217 	bzero(log, sizeof (log));
218 	log_pos = log_op = 0;
219 
220 	if (ea_open(&f, argv[3], NULL, EO_HEAD, O_RDONLY, 0) == -1) {
221 		perror("open failed");
222 		return (1);
223 	}
224 	srand48((long)(gethrtime() & ~0L));
225 	dir = 'F';
226 	while (iters--) {
227 		if (dir == ' ') {
228 			dir = (lrand48() % 2) ? 'F' : 'B';
229 		}
230 		sz = (lrand48() % maxsz) + 1;
231 		dir = do_reads(&f, dir, sz);
232 	}
233 	(void) ea_close(&f);
234 	return (0);
235 }
236