xref: /freebsd/tools/test/stress2/lib/options.c (revision dd41de95a84d979615a2ef11df6850622bf6184e)
1 /*-
2  * Copyright (c) 2008 Peter Holm <pho@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <sysexits.h>
32 #include <string.h>
33 #include <time.h>
34 #include <err.h>
35 
36 #include "stress.h"
37 
38 static opt_t opt;
39 opt_t *op;
40 
41 static char path[64];
42 
43 static void
44 usage(const char *where)
45 {
46 	const char *help;
47 
48 	if (where != NULL)
49 		printf("Error in \"%s\"\n", where);
50 	fprintf(stderr, "Usage: %s [-t | -l | -i | -d | -h | -k | -v]\n", getprogname());
51 	help =  " t <number><s|m|h|d> : time to run test\n"
52 		" l <pct>             : load factor 0 - 100%\n"
53 		" i <number>          : max # of parallel incarnations\n"
54 		" d <path>            : working directory\n"
55 		" h                   : hog resources\n"
56 		" k                   : terminate with SIGHUP + SIGKILL\n"
57 		" n                   : no startup delay\n"
58 		" v                   : verbose\n";
59 	printf("%s", help);
60 	exit(EX_USAGE);
61 }
62 
63 static int
64 time2sec(const char *string)
65 {
66 	int r, s = 0;
67 	char modifier;
68 	r = sscanf(string, "%d%c", &s, &modifier);
69 	if (r == 2)
70 		switch(modifier) {
71 		case 's': break;
72 		case 'm': s = s * 60; break;
73 		case 'h': s = s * 60 * 60; break;
74 		case 'd': s = s * 60 * 60 * 24; break;
75 		default:
76 			usage("-t");
77 		}
78 	else
79 		usage("-t");
80 	return (s);
81 }
82 
83 static char *gete(const char *name)
84 {
85 	char *cp;
86 	char help[128];
87 
88 	snprintf(help, sizeof(help), "%s%s", getprogname(), name);
89 	cp = getenv(help);
90 	if (cp == NULL)
91 		cp = getenv(name);
92 	return (cp);
93 }
94 
95 static void
96 environment(void)
97 {
98 	char *cp;
99 
100 	if ((cp = gete("INCARNATIONS")) != NULL) {
101 		if (sscanf(cp, "%d", &op->incarnations) != 1)
102 			usage("INCARNATIONS");
103 	}
104 	if ((cp = gete("LOAD")) != NULL) {
105 		if (sscanf(cp, "%d", &op->load) != 1)
106 			usage("LOAD");
107 	}
108 	if ((cp = gete("RUNTIME")) != NULL) {
109 		op->run_time = time2sec(cp);
110 	}
111 	if ((cp = gete("RUNDIR")) != NULL) {
112 		op->wd = cp;
113 	}
114 	if ((cp = gete("CTRLDIR")) != NULL) {
115 		op->cd = cp;
116 	}
117 	if ((cp = gete("HOG")) != NULL) {
118 		op->hog = 1;
119 	}
120 	if ((cp = gete("KILL")) != NULL) {
121 		op->kill = 1;
122 	}
123 	if ((cp = gete("NODELAY")) != NULL) {
124 		op->nodelay = 1;
125 	}
126 	if ((cp = gete("VERBOSE")) != NULL) {
127 		if (sscanf(cp, "%d", &op->verbose) != 1)
128 			usage("VERBOSE");
129 	}
130 	if ((cp = gete("KBLOCKS")) != NULL) {
131 		if (sscanf(cp, "%jd", &op->kblocks) != 1)
132 			usage("KBLOCKS");
133 	}
134 	if ((cp = gete("INODES")) != NULL) {
135 		if (sscanf(cp, "%jd", &op->inodes) != 1)
136 			usage("INODES");
137 	}
138 }
139 
140 void
141 options(int argc, char **argv)
142 {
143 	int ch;
144 
145 	op = &opt;
146 
147 	op->run_time	= 60;
148 	op->load	= 100;
149 	op->wd		= strdup("/tmp/stressX");
150 	op->cd		= strdup("/tmp/stressX.control");
151 	op->incarnations	= 1;
152 	op->hog		= 0;
153 	op->kill	= 0;
154 	op->nodelay	= 0;
155 	op->verbose	= 0;
156 	op->kblocks	= 0;
157 	op->inodes	= 0;
158 
159 	environment();
160 
161 	while ((ch = getopt(argc, argv, "t:l:i:d:hknv")) != -1)
162 		switch(ch) {
163 		case 't':	/* run time */
164 			op->run_time = time2sec(optarg);
165 			break;
166 		case 'l':	/* load factor in pct */
167 			if (sscanf(optarg, "%d", &op->load) != 1)
168 				usage("-l");
169 			break;
170 		case 'i':	/* max incarnations */
171 			if (sscanf(optarg, "%d", &op->incarnations) != 1)
172 				usage("-i");
173 			break;
174 		case 'd':	/* working directory */
175 			op->wd = strdup(optarg);
176 			break;
177 		case 'h':	/* hog flag */
178 			op->hog += 1;
179 			break;
180 		case 'k':	/* kill flag */
181 			op->kill = 1;
182 			break;
183 		case 'n':	/* no delay flag */
184 			op->nodelay = 1;
185 			break;
186 		case 'v':	/* verbose flag */
187 			op->verbose += 1;
188 			break;
189 		default:
190 			usage(NULL);
191 		}
192 	op->argc = argc -= optind;
193 	op->argv = argv += optind;
194 
195 	if (op->incarnations < 1)
196 		op->incarnations = 1;
197 	if (op->hog == 0)
198 		op->incarnations = random_int(1, op->incarnations);
199 	if (op->run_time < 15)
200 		op->run_time = 15;
201 	if (op->load < 0 || op->load > 100)
202 		op->load = 100;
203 }
204 
205 void
206 show_status(void)
207 {
208 	char buf[80], pgname[9];
209 	int days;
210 	time_t t;
211 
212 	if (op->verbose > 0) {
213 		strncpy(pgname, getprogname(), sizeof(pgname));
214 		pgname[8] = 0;
215 		t = op->run_time;
216 		days = t / (60 * 60 * 24);
217 		t = t % (60 * 60 * 24);
218 		strftime(buf, sizeof(buf), "%T", gmtime(&t));
219 		printf("%8s: run time %2d+%s, incarnations %3d, load %3d, "
220 			"verbose %d\n",
221 			pgname, days, buf, op->incarnations, op->load,
222 			op->verbose);
223 		fflush(stdout);
224 	}
225 }
226 
227 void
228 rmval(void)
229 {
230 	if (snprintf(path, sizeof(path), "%s/%s.conf", op->cd,
231 	    getprogname()) < 0)
232 		err(1, "snprintf path");
233 	(void) unlink(path);
234 }
235 
236 void
237 putval(unsigned long v)
238 {
239 	char buf[64];
240 
241 	rmval();
242 	snprintf(buf, sizeof(buf), "%lu", v);
243 	if (symlink(buf, path) < 0)
244 		err(1, "symlink(%s, %s)", path, buf);
245 }
246 
247 unsigned long
248 getval(void)
249 {
250 	int i, n;
251 	unsigned long val;
252 	char buf[64];
253 
254 	if ((n = readlink(path, buf, sizeof(buf) -1)) < 0) {
255 		for (i = 0; i < 60; i++) {
256 			sleep(1);
257 			if ((n = readlink(path, buf, sizeof(buf) -1)) > 0)
258 				break;
259 		}
260 		if (n < 0)
261 			err(1, "readlink(%s). %s:%d", path, __FILE__,
262 			    __LINE__);
263 	}
264 	buf[n] = '\0';
265 	if (sscanf(buf, "%ld", &val) != 1)
266 		err(1, "sscanf(%s)", buf);
267 	return val;
268 }
269