]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
b19ccc9e | 2 | * "$Id: testspeed.c 7727 2008-07-14 18:02:21Z mike $" |
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, | |
42 | int verbose); | |
e1d6a774 | 43 | static void usage(void); |
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 */ | |
69 | ||
70 | ||
71 | /* | |
72 | * Parse command-line options... | |
73 | */ | |
74 | ||
75 | requests = 100; | |
76 | children = 5; | |
dd1abb6b MS |
77 | server = (char *)cupsServer(); |
78 | port = ippPort(); | |
ef416fc2 | 79 | encryption = HTTP_ENCRYPT_IF_REQUESTED; |
80 | verbose = 0; | |
81 | ||
82 | for (i = 1; i < argc; i ++) | |
dd1abb6b | 83 | if (argv[i][0] == '-') |
ef416fc2 | 84 | { |
dd1abb6b MS |
85 | for (ptr = argv[i] + 1; *ptr; ptr ++) |
86 | switch (*ptr) | |
87 | { | |
88 | case 'c' : /* Number of children */ | |
89 | i ++; | |
90 | if (i >= argc) | |
91 | usage(); | |
92 | ||
93 | children = atoi(argv[i]); | |
94 | break; | |
95 | ||
96 | case 'r' : /* Number of requests */ | |
97 | i ++; | |
98 | if (i >= argc) | |
99 | usage(); | |
100 | ||
101 | requests = atoi(argv[i]); | |
102 | break; | |
103 | ||
104 | case 'E' : /* Enable encryption */ | |
105 | encryption = HTTP_ENCRYPT_REQUIRED; | |
106 | break; | |
107 | ||
108 | case 'v' : /* Verbose logging */ | |
109 | verbose ++; | |
110 | break; | |
111 | ||
112 | default : | |
113 | usage(); | |
114 | break; | |
115 | } | |
ef416fc2 | 116 | } |
dd1abb6b | 117 | else |
ef416fc2 | 118 | { |
dd1abb6b | 119 | server = argv[i]; |
ef416fc2 | 120 | |
dd1abb6b MS |
121 | if (server[0] != '/' && (ptr = strrchr(server, ':')) != NULL) |
122 | { | |
123 | *ptr++ = '\0'; | |
124 | port = atoi(ptr); | |
125 | } | |
ef416fc2 | 126 | } |
ef416fc2 | 127 | |
128 | /* | |
129 | * Then create child processes to act as clients... | |
130 | */ | |
131 | ||
dd1abb6b MS |
132 | if (children > 0) |
133 | { | |
134 | printf("testspeed: Simulating %d clients with %d requests to %s with " | |
135 | "%sencryption...\n", children, requests, server, | |
136 | encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no " : ""); | |
137 | } | |
ef416fc2 | 138 | |
139 | start = time(NULL); | |
140 | ||
dd1abb6b MS |
141 | if (children < 1) |
142 | return (do_test(server, port, encryption, requests, verbose)); | |
143 | else if (children == 1) | |
144 | good_children = do_test(server, port, encryption, requests, verbose) ? 0 : 1; | |
ef416fc2 | 145 | else |
146 | { | |
dd1abb6b MS |
147 | char options[255], /* Command-line options for child */ |
148 | reqstr[255], /* Requests string for child */ | |
149 | serverstr[255]; /* Server:port string for child */ | |
150 | ||
151 | ||
152 | snprintf(reqstr, sizeof(reqstr), "%d", requests); | |
153 | ||
154 | if (port == 631 || server[0] == '/') | |
155 | strlcpy(serverstr, server, sizeof(serverstr)); | |
156 | else | |
157 | snprintf(serverstr, sizeof(serverstr), "%s:%d", server, port); | |
158 | ||
159 | strlcpy(options, "-cr", sizeof(options)); | |
160 | ||
161 | if (encryption == HTTP_ENCRYPT_REQUIRED) | |
162 | strlcat(options, "E", sizeof(options)); | |
163 | ||
164 | if (verbose) | |
165 | strlcat(options, "v", sizeof(options)); | |
166 | ||
ef416fc2 | 167 | for (i = 0; i < children; i ++) |
dd1abb6b MS |
168 | { |
169 | fflush(stdout); | |
170 | ||
ef416fc2 | 171 | if ((pid = fork()) == 0) |
172 | { | |
173 | /* | |
174 | * Child goes here... | |
175 | */ | |
176 | ||
dd1abb6b MS |
177 | execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL); |
178 | exit(errno); | |
ef416fc2 | 179 | } |
180 | else if (pid < 0) | |
181 | { | |
dd1abb6b | 182 | printf("testspeed: Fork failed: %s\n", strerror(errno)); |
ef416fc2 | 183 | break; |
184 | } | |
185 | else | |
dd1abb6b MS |
186 | printf("testspeed: Started child %d...\n", pid); |
187 | } | |
ef416fc2 | 188 | |
189 | /* | |
190 | * Wait for children to finish... | |
191 | */ | |
192 | ||
dd1abb6b MS |
193 | puts("testspeed: Waiting for children to finish..."); |
194 | ||
195 | for (good_children = 0;;) | |
ef416fc2 | 196 | { |
197 | pid = wait(&status); | |
198 | ||
199 | if (pid < 0 && errno != EINTR) | |
200 | break; | |
201 | ||
dd1abb6b MS |
202 | printf("testspeed: Ended child %d (%d)...\n", pid, status / 256); |
203 | ||
204 | if (!status) | |
205 | good_children ++; | |
ef416fc2 | 206 | } |
207 | } | |
208 | ||
209 | /* | |
210 | * Compute the total run time... | |
211 | */ | |
212 | ||
dd1abb6b MS |
213 | if (good_children > 0) |
214 | { | |
215 | end = time(NULL); | |
216 | elapsed = end - start; | |
217 | i = good_children * requests; | |
ef416fc2 | 218 | |
dd1abb6b MS |
219 | printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n", |
220 | good_children, requests, i, elapsed, elapsed / i, i / elapsed); | |
221 | } | |
ef416fc2 | 222 | |
223 | /* | |
224 | * Exit with no errors... | |
225 | */ | |
226 | ||
91c84a35 | 227 | return (0); |
ef416fc2 | 228 | } |
229 | ||
230 | ||
231 | /* | |
232 | * 'do_test()' - Run a test on a specific host... | |
233 | */ | |
234 | ||
e1d6a774 | 235 | static int /* O - Exit status */ |
ef416fc2 | 236 | do_test(const char *server, /* I - Server to use */ |
dd1abb6b | 237 | int port, /* I - Port number to use */ |
ef416fc2 | 238 | http_encryption_t encryption, /* I - Encryption to use */ |
239 | int requests, /* I - Number of requests to send */ | |
240 | int verbose) /* I - Verbose output? */ | |
241 | { | |
242 | int i; /* Looping var */ | |
243 | http_t *http; /* Connection to server */ | |
dd1abb6b | 244 | ipp_t *request; /* IPP Request */ |
ef416fc2 | 245 | struct timeval start, /* Start time */ |
246 | end; /* End time */ | |
dd1abb6b MS |
247 | double reqtime, /* Time for this request */ |
248 | elapsed; /* Elapsed time */ | |
249 | int op; /* Current operation */ | |
ef416fc2 | 250 | static ipp_op_t ops[4] = /* Operations to test... */ |
251 | { | |
252 | IPP_PRINT_JOB, | |
253 | CUPS_GET_PRINTERS, | |
254 | CUPS_GET_CLASSES, | |
255 | IPP_GET_JOBS | |
256 | }; | |
257 | ||
258 | ||
259 | /* | |
260 | * Connect to the server... | |
261 | */ | |
262 | ||
dd1abb6b | 263 | if ((http = httpConnectEncrypt(server, port, encryption)) == NULL) |
ef416fc2 | 264 | { |
dd1abb6b MS |
265 | printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(), |
266 | strerror(errno)); | |
ef416fc2 | 267 | return (1); |
268 | } | |
269 | ||
ef416fc2 | 270 | /* |
271 | * Do multiple requests... | |
272 | */ | |
273 | ||
274 | for (elapsed = 0.0, i = 0; i < requests; i ++) | |
275 | { | |
ef416fc2 | 276 | /* |
277 | * Build a request which requires the following attributes: | |
278 | * | |
279 | * attributes-charset | |
280 | * attributes-natural-language | |
281 | * | |
282 | * In addition, IPP_GET_JOBS needs a printer-uri attribute. | |
283 | */ | |
284 | ||
dd1abb6b MS |
285 | op = ops[i & 3]; |
286 | request = ippNewRequest(op); | |
ef416fc2 | 287 | |
288 | gettimeofday(&start, NULL); | |
289 | ||
dd1abb6b MS |
290 | if (verbose) |
291 | printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed, | |
292 | ippOpString(op)); | |
293 | ||
294 | switch (op) | |
ef416fc2 | 295 | { |
296 | case IPP_GET_JOBS : | |
297 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", | |
298 | NULL, "ipp://localhost/printers/"); | |
299 | ||
300 | default : | |
dd1abb6b | 301 | ippDelete(cupsDoRequest(http, request, "/")); |
ef416fc2 | 302 | break; |
303 | ||
304 | case IPP_PRINT_JOB : | |
305 | ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", | |
306 | NULL, "ipp://localhost/printers/test"); | |
dd1abb6b MS |
307 | ippDelete(cupsDoFileRequest(http, request, "/printers/test", |
308 | "../data/testprint.ps")); | |
ef416fc2 | 309 | break; |
310 | } | |
311 | ||
312 | gettimeofday(&end, NULL); | |
313 | ||
dd1abb6b MS |
314 | reqtime = (end.tv_sec - start.tv_sec) + |
315 | 0.000001 * (end.tv_usec - start.tv_usec); | |
316 | elapsed += reqtime; | |
317 | ||
318 | switch (cupsLastError()) | |
319 | { | |
320 | case IPP_OK : | |
321 | case IPP_NOT_FOUND : | |
322 | if (verbose) | |
323 | { | |
324 | printf("succeeded: %s (%.6f)\n", cupsLastErrorString(), reqtime); | |
325 | fflush(stdout); | |
326 | } | |
327 | break; | |
ef416fc2 | 328 | |
dd1abb6b MS |
329 | default : |
330 | if (!verbose) | |
331 | printf("testspeed(%d): %s ", (int)getpid(), | |
332 | ippOpString(ops[i & 3])); | |
333 | ||
334 | printf("failed: %s\n", cupsLastErrorString()); | |
335 | httpClose(http); | |
336 | return (1); | |
337 | } | |
ef416fc2 | 338 | } |
339 | ||
ef416fc2 | 340 | httpClose(http); |
341 | ||
342 | printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n", | |
343 | (int)getpid(), i, elapsed, elapsed / i, i / elapsed); | |
344 | ||
345 | return (0); | |
346 | } | |
347 | ||
348 | ||
349 | /* | |
350 | * 'usage()' - Show program usage... | |
351 | */ | |
352 | ||
e1d6a774 | 353 | static void |
ef416fc2 | 354 | usage(void) |
355 | { | |
dd1abb6b MS |
356 | puts("Usage: testspeed [-c children] [-h] [-r requests] [-v] [-E] " |
357 | "hostname[:port]"); | |
ef416fc2 | 358 | exit(0); |
359 | } | |
360 | ||
361 | ||
362 | ||
363 | /* | |
b19ccc9e | 364 | * End of "$Id: testspeed.c 7727 2008-07-14 18:02:21Z mike $". |
ef416fc2 | 365 | */ |