Bring in FreeBSD's stress2 stress testing suite.
[dragonfly.git] / test / stress / stress2 / lib / options.c
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 opt_t opt;
39 opt_t *op;
40
41 static char path[64];
42
43 static void
44 usage(char *where)
45 {
46         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(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(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, "%d", &op->kblocks) != 1)
132                         usage("KBLOCKS");
133         }
134         if ((cp = gete("INODES")) != NULL) {
135                 if (sscanf(cp, "%d", &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          = "/tmp/stressX";
150         op->cd          = "/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];
209         int days;
210         time_t t;
211
212         if (op->verbose > 0) {
213                 t = op->run_time;
214                 days = t / (60 * 60 * 24);
215                 t = t % (60 * 60 * 24);
216                 strftime(buf, sizeof(buf), "%T", gmtime(&t));
217                 printf("%8s: run time %2d+%s, incarnations %3d, load %3d, verbose %d\n",
218                         getprogname(), days, buf, op->incarnations, op->load,
219                         op->verbose);
220         }
221 }
222
223 void
224 rmval(void)
225 {
226         if (snprintf(path, sizeof(path), "%s/%s.conf", op->cd, getprogname()) < 0)
227                 err(1, "snprintf path");
228         (void) unlink(path);
229 }
230
231 void
232 putval(unsigned long v)
233 {
234         char buf[64];
235
236         rmval();
237         snprintf(buf, sizeof(buf), "%lu", v);
238         if (symlink(buf, path) < 0)
239                 err(1, "symlink(%s, %s)", path, buf);
240 }
241
242 unsigned long
243 getval(void)
244 {
245         int i, n;
246         unsigned long val;
247         char buf[64];
248
249         if ((n = readlink(path, buf, sizeof(buf) -1)) < 0) {
250                 for (i = 0; i < 60; i++) {
251                         sleep(1);
252                         if ((n = readlink(path, buf, sizeof(buf) -1)) > 0)
253                                 break;
254                 }
255                 if (n < 0)
256                         err(1, "readlink(%s). %s:%d", path, __FILE__, __LINE__);
257         }
258         buf[n] = '\0';
259         if (sscanf(buf, "%ld", &val) != 1)
260                 err(1, "sscanf(%s)", buf);
261         return val;
262 }