]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
61515785 | 2 | * "$Id: testspeed.c 10995 2013-05-29 11:51:03Z msweet $" |
ef416fc2 | 3 | * |
71e16022 | 4 | * Scheduler speed test for CUPS. |
ef416fc2 | 5 | * |
71e16022 | 6 | * Copyright 2007-2010 by Apple Inc. |
ef416fc2 | 7 | * Copyright 1997-2005 by Easy Software Products. |
8 | * | |
9 | * These coded instructions, statements, and computer programs are the | |
bc44d920 | 10 | * property of Apple Inc. and are protected by Federal copyright |
11 | * law. Distribution and use rights are outlined in the file "LICENSE.txt" | |
12 | * which should have been included with this file. If this file is | |
13 | * file is missing or damaged, see the license at "http://www.cups.org/". | |
ef416fc2 | 14 | * |
15 | * Contents: | |
16 | * | |
e1d6a774 | 17 | * main() - Send multiple IPP requests and report on the average response |
18 | * time. | |
19 | * do_test() - Run a test on a specific host... | |
20 | * usage() - Show program usage... | |
ef416fc2 | 21 | */ |
22 | ||
23 | /* | |
24 | * Include necessary headers... | |
25 | */ | |
26 | ||
71e16022 | 27 | #include <cups/string-private.h> |
ef416fc2 | 28 | #include <cups/cups.h> |
29 | #include <cups/language.h> | |
71e16022 | 30 | #include <cups/debug-private.h> |
75bd9771 MS |
31 | #include <sys/types.h> |
32 | #include <sys/time.h> | |
33 | #include <sys/wait.h> | |
ef416fc2 | 34 | |
35 | ||
36 | /* | |
37 | * Local functions... | |
38 | */ | |
39 | ||
dd1abb6b MS |
40 | static int do_test(const char *server, int port, |
41 | http_encryption_t encryption, int requests, | |
23ef1cac | 42 | const char *opstring, int verbose); |
85dda01c | 43 | static void usage(void) __attribute__((noreturn)); |
ef416fc2 | 44 | |
45 | ||
46 | /* | |
47 | * 'main()' - Send multiple IPP requests and report on the average response | |
48 | * time. | |
49 | */ | |
50 | ||
51 | int | |
52 | main(int argc, /* I - Number of command-line arguments */ | |
53 | char *argv[]) /* I - Command-line arguments */ | |
54 | { | |
55 | int i; /* Looping var */ | |
dd1abb6b MS |
56 | char *server, /* Server to use */ |
57 | *ptr; /* Pointer to port in server */ | |
58 | int port; /* Port to use */ | |
ef416fc2 | 59 | http_encryption_t encryption; /* Encryption to use */ |
60 | int requests; /* Number of requests to send */ | |
61 | int children; /* Number of children to fork */ | |
dd1abb6b | 62 | int good_children; /* Number of children that exited normally */ |
ef416fc2 | 63 | int pid; /* Child PID */ |
64 | int status; /* Child status */ | |
65 | time_t start, /* Start time */ | |
66 | end; /* End time */ | |
67 | double elapsed; /* Elapsed time */ | |
68 | int verbose; /* Verbosity */ | |
23ef1cac | 69 | const char *opstring; /* Operation name */ |
ef416fc2 | 70 | |
71 | ||
72 | /* | |
73 | * Parse command-line options... | |
74 | */ | |
75 | ||
76 | requests = 100; | |
77 | children = 5; | |
dd1abb6b MS |
78 | server = (char *)cupsServer(); |
79 | port = ippPort(); | |
ef416fc2 | 80 | encryption = HTTP_ENCRYPT_IF_REQUESTED; |
81 | verbose = 0; | |
23ef1cac | 82 | opstring = NULL; |
ef416fc2 | 83 | |
84 | for (i = 1; i < argc; i ++) | |
dd1abb6b | 85 | if (argv[i][0] == '-') |
ef416fc2 | 86 | { |
dd1abb6b MS |
87 | for (ptr = argv[i] + 1; *ptr; ptr ++) |
88 | switch (*ptr) | |
89 | { | |
23ef1cac MS |
90 | case 'E' : /* Enable encryption */ |
91 | encryption = HTTP_ENCRYPT_REQUIRED; | |
92 | break; | |
93 | ||
dd1abb6b MS |
94 | case 'c' : /* Number of children */ |
95 | i ++; | |
96 | if (i >= argc) | |
97 | usage(); | |
98 | ||
99 | children = atoi(argv[i]); | |
100 | break; | |
101 | ||
23ef1cac | 102 | case 'o' : /* Operation */ |
dd1abb6b MS |
103 | i ++; |
104 | if (i >= argc) | |
105 | usage(); | |
106 | ||
23ef1cac | 107 | opstring = argv[i]; |
dd1abb6b MS |
108 | break; |
109 | ||
23ef1cac MS |
110 | case 'r' : /* Number of requests */ |
111 | i ++; | |
112 | if (i >= argc) | |
113 | usage(); | |
114 | ||
115 | requests = atoi(argv[i]); | |
dd1abb6b MS |
116 | break; |
117 | ||
118 | case 'v' : /* Verbose logging */ | |
119 | verbose ++; | |
120 | break; | |
121 | ||
122 | default : | |
123 | usage(); | |
124 | break; | |
125 | } | |
ef416fc2 | 126 | } |
dd1abb6b | 127 | else |
ef416fc2 | 128 | { |
dd1abb6b | 129 | server = argv[i]; |
ef416fc2 | 130 | |
dd1abb6b MS |
131 | if (server[0] != '/' && (ptr = strrchr(server, ':')) != NULL) |
132 | { | |
133 | *ptr++ = '\0'; | |
134 | port = atoi(ptr); | |
135 | } | |
ef416fc2 | 136 | } |
ef416fc2 | 137 | |
138 | /* | |
139 | * Then create child processes to act as clients... | |
140 | */ | |
141 | ||
dd1abb6b MS |
142 | if (children > 0) |
143 | { | |
144 | printf("testspeed: Simulating %d clients with %d requests to %s with " | |
145 | "%sencryption...\n", children, requests, server, | |
146 | encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no " : ""); | |
147 | } | |
ef416fc2 | 148 | |
149 | start = time(NULL); | |
150 | ||
dd1abb6b | 151 | if (children < 1) |
23ef1cac | 152 | return (do_test(server, port, encryption, requests, opstring, verbose)); |
dd1abb6b | 153 | else if (children == 1) |
23ef1cac MS |
154 | good_children = do_test(server, port, encryption, requests, opstring, |
155 | verbose) ? 0 : 1; | |
ef416fc2 | 156 | else |
157 | { | |
dd1abb6b MS |
158 | char options[255], /* Command-line options for child */ |
159 | reqstr[255], /* Requests string for child */ | |
160 | serverstr[255]; /* Server:port string for child */ | |
161 | ||
162 | ||
163 | snprintf(reqstr, sizeof(reqstr), "%d", requests); | |
164 | ||
165 | if (port == 631 || server[0] == '/') | |
166 | strlcpy(serverstr, server, sizeof(serverstr)); | |
167 | else | |
168 | snprintf(serverstr, sizeof(serverstr), "%s:%d", server, port); | |
169 | ||
170 | strlcpy(options, "-cr", sizeof(options)); | |
171 | ||
172 | if (encryption == HTTP_ENCRYPT_REQUIRED) | |
173 | strlcat(options, "E", sizeof(options)); | |
174 | ||
175 | if (verbose) | |
176 | strlcat(options, "v", sizeof(options)); | |
177 | ||
ef416fc2 | 178 | for (i = 0; i < children; i ++) |
dd1abb6b MS |
179 | { |
180 | fflush(stdout); | |
181 | ||
ef416fc2 | 182 | if ((pid = fork()) == 0) |
183 | { | |
184 | /* | |
185 | * Child goes here... | |
186 | */ | |
187 | ||
23ef1cac MS |
188 | if (opstring) |
189 | execlp(argv[0], argv[0], options, "0", reqstr, "-o", opstring, | |
190 | serverstr, (char *)NULL); | |
191 | else | |
192 | execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL); | |
193 | ||
dd1abb6b | 194 | exit(errno); |
ef416fc2 | 195 | } |
196 | else if (pid < 0) | |
197 | { | |
dd1abb6b | 198 | printf("testspeed: Fork failed: %s\n", strerror(errno)); |
ef416fc2 | 199 | break; |
200 | } | |
201 | else | |
dd1abb6b MS |
202 | printf("testspeed: Started child %d...\n", pid); |
203 | } | |
ef416fc2 | 204 | |
205 | /* | |
206 | * Wait for children to finish... | |
207 | */ | |
208 | ||
dd1abb6b MS |
209 | puts("testspeed: Waiting for children to finish..."); |
210 | ||
211 | for (good_children = 0;;) | |
ef416fc2 | 212 | { |
213 | pid = wait(&status); | |
214 | ||
215 | if (pid < 0 && errno != EINTR) | |
216 | break; | |
217 | ||
dd1abb6b MS |
218 | printf("testspeed: Ended child %d (%d)...\n", pid, status / 256); |
219 | ||
220 | if (!status) | |
221 | good_children ++; | |
ef416fc2 | 222 | } |
223 | } | |
224 | ||
225 | /* | |
226 | * Compute the total run time... | |
227 | */ | |
228 | ||
dd1abb6b MS |
229 | if (good_children > 0) |
230 | { | |
231 | end = time(NULL); | |
232 | elapsed = end - start; | |
233 | i = good_children * requests; | |
ef416fc2 | 234 | |
dd1abb6b MS |
235 | printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n", |
236 | good_children, requests, i, elapsed, elapsed / i, i / elapsed); | |
237 | } | |
ef416fc2 | 238 | |
239 | /* | |
240 | * Exit with no errors... | |
241 | */ | |
242 | ||
91c84a35 | 243 | return (0); |
ef416fc2 | 244 | } |
245 | ||
246 | ||
247 | /* | |
248 | * 'do_test()' - Run a test on a specific host... | |
249 | */ | |
250 | ||
e1d6a774 | 251 | static int /* O - Exit status */ |
ef416fc2 | 252 | do_test(const char *server, /* I - Server to use */ |
dd1abb6b | 253 | int port, /* I - Port number to use */ |
ef416fc2 | 254 | http_encryption_t encryption, /* I - Encryption to use */ |
255 | int requests, /* I - Number of requests to send */ | |
23ef1cac | 256 | const char *opstring, /* I - Operation string */ |
ef416fc2 | 257 | int verbose) /* I - Verbose output? */ |
258 | { | |
259 | int i; /* Looping var */ | |
260 | http_t *http; /* Connection to server */ | |
dd1abb6b | 261 | ipp_t *request; /* IPP Request */ |
ef416fc2 | 262 | struct timeval start, /* Start time */ |
263 | end; /* End time */ | |
dd1abb6b MS |
264 | double reqtime, /* Time for this request */ |
265 | elapsed; /* Elapsed time */ | |
266 | int op; /* Current operation */ | |
23ef1cac | 267 | static ipp_op_t ops[5] = /* Operations to test... */ |
ef416fc2 | 268 | { |
269 | IPP_PRINT_JOB, | |
23ef1cac | 270 | CUPS_GET_DEFAULT, |
ef416fc2 | 271 | CUPS_GET_PRINTERS, |
272 | CUPS_GET_CLASSES, | |
273 | IPP_GET_JOBS | |
274 | }; | |
275 | ||
276 | ||
277 | /* | |
278 | * Connect to the server... | |
279 | */ | |
280 | ||
dd1abb6b | 281 | if ((http = httpConnectEncrypt(server, port, encryption)) == NULL) |
ef416fc2 | 282 | { |
dd1abb6b MS |
283 | printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(), |
284 | strerror(errno)); | |
ef416fc2 | 285 | return (1); |
286 | } | |
287 | ||
ef416fc2 | 288 | /* |
289 | * Do multiple requests... | |
290 | */ | |
291 | ||
292 | for (elapsed = 0.0, i = 0; i < requests; i ++) | |
293 | { | |
ef416fc2 | 294 | /* |
295 | * Build a request which requires the following attributes: | |
296 | * | |
297 | * attributes-charset | |
298 | * attributes-natural-language | |
299 | * | |
300 | * In addition, IPP_GET_JOBS needs a printer-uri attribute. | |
301 | */ | |
302 | ||
23ef1cac MS |
303 | if (opstring) |
304 | op = ippOpValue(opstring); | |
305 | else | |
306 | op = ops[i % (sizeof(ops) / sizeof(ops[0]))]; | |
307 | ||
dd1abb6b | 308 | request = ippNewRequest(op); |
ef416fc2 | 309 | |
310 | gettimeofday(&start, NULL); | |
311 | ||
dd1abb6b MS |
312 | if (verbose) |
313 | printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed, | |
314 | ippOpString(op)); | |
315 | ||
316 | switch (op) | |
ef416fc2 | 317 | { |
318 | case IPP_GET_JOBS : | |
319 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", | |
320 | NULL, "ipp://localhost/printers/"); | |
321 | ||
322 | default : | |
dd1abb6b | 323 | ippDelete(cupsDoRequest(http, request, "/")); |
ef416fc2 | 324 | break; |
325 | ||
326 | case IPP_PRINT_JOB : | |
327 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", | |
328 | NULL, "ipp://localhost/printers/test"); | |
dd1abb6b MS |
329 | ippDelete(cupsDoFileRequest(http, request, "/printers/test", |
330 | "../data/testprint.ps")); | |
ef416fc2 | 331 | break; |
332 | } | |
333 | ||
334 | gettimeofday(&end, NULL); | |
335 | ||
dd1abb6b MS |
336 | reqtime = (end.tv_sec - start.tv_sec) + |
337 | 0.000001 * (end.tv_usec - start.tv_usec); | |
338 | elapsed += reqtime; | |
339 | ||
340 | switch (cupsLastError()) | |
341 | { | |
342 | case IPP_OK : | |
343 | case IPP_NOT_FOUND : | |
344 | if (verbose) | |
345 | { | |
346 | printf("succeeded: %s (%.6f)\n", cupsLastErrorString(), reqtime); | |
347 | fflush(stdout); | |
348 | } | |
349 | break; | |
ef416fc2 | 350 | |
dd1abb6b MS |
351 | default : |
352 | if (!verbose) | |
353 | printf("testspeed(%d): %s ", (int)getpid(), | |
354 | ippOpString(ops[i & 3])); | |
355 | ||
356 | printf("failed: %s\n", cupsLastErrorString()); | |
357 | httpClose(http); | |
358 | return (1); | |
359 | } | |
ef416fc2 | 360 | } |
361 | ||
ef416fc2 | 362 | httpClose(http); |
363 | ||
364 | printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n", | |
365 | (int)getpid(), i, elapsed, elapsed / i, i / elapsed); | |
366 | ||
367 | return (0); | |
368 | } | |
369 | ||
370 | ||
371 | /* | |
372 | * 'usage()' - Show program usage... | |
373 | */ | |
374 | ||
e1d6a774 | 375 | static void |
ef416fc2 | 376 | usage(void) |
377 | { | |
23ef1cac MS |
378 | puts("Usage: testspeed [-c children] [-h] [-o operation] [-r requests] [-v] " |
379 | "[-E] hostname[:port]"); | |
ef416fc2 | 380 | exit(0); |
381 | } | |
382 | ||
383 | ||
384 | ||
385 | /* | |
61515785 | 386 | * End of "$Id: testspeed.c 10995 2013-05-29 11:51:03Z msweet $". |
ef416fc2 | 387 | */ |