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