]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * "$Id: testspeed.c 7727 2008-07-14 18:02:21Z mike $" | |
3 | * | |
4 | * Scheduler speed test for the Common UNIX Printing System (CUPS). | |
5 | * | |
6 | * Copyright 2007-2008 by Apple Inc. | |
7 | * Copyright 1997-2005 by Easy Software Products. | |
8 | * | |
9 | * These coded instructions, statements, and computer programs are the | |
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/". | |
14 | * | |
15 | * Contents: | |
16 | * | |
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... | |
21 | */ | |
22 | ||
23 | /* | |
24 | * Include necessary headers... | |
25 | */ | |
26 | ||
27 | #include <cups/string.h> | |
28 | #include <cups/cups.h> | |
29 | #include <cups/language.h> | |
30 | #include <cups/debug.h> | |
31 | #include <sys/types.h> | |
32 | #include <sys/time.h> | |
33 | #include <sys/wait.h> | |
34 | #include <errno.h> | |
35 | ||
36 | ||
37 | /* | |
38 | * Local functions... | |
39 | */ | |
40 | ||
41 | static int do_test(const char *server, int port, | |
42 | http_encryption_t encryption, int requests, | |
43 | int verbose); | |
44 | static void usage(void); | |
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 */ | |
57 | char *server, /* Server to use */ | |
58 | *ptr; /* Pointer to port in server */ | |
59 | int port; /* Port to use */ | |
60 | http_encryption_t encryption; /* Encryption to use */ | |
61 | int requests; /* Number of requests to send */ | |
62 | int children; /* Number of children to fork */ | |
63 | int good_children; /* Number of children that exited normally */ | |
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; | |
78 | server = (char *)cupsServer(); | |
79 | port = ippPort(); | |
80 | encryption = HTTP_ENCRYPT_IF_REQUESTED; | |
81 | verbose = 0; | |
82 | ||
83 | for (i = 1; i < argc; i ++) | |
84 | if (argv[i][0] == '-') | |
85 | { | |
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 | } | |
117 | } | |
118 | else | |
119 | { | |
120 | server = argv[i]; | |
121 | ||
122 | if (server[0] != '/' && (ptr = strrchr(server, ':')) != NULL) | |
123 | { | |
124 | *ptr++ = '\0'; | |
125 | port = atoi(ptr); | |
126 | } | |
127 | } | |
128 | ||
129 | /* | |
130 | * Then create child processes to act as clients... | |
131 | */ | |
132 | ||
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 | } | |
139 | ||
140 | start = time(NULL); | |
141 | ||
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; | |
146 | else | |
147 | { | |
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 | ||
168 | for (i = 0; i < children; i ++) | |
169 | { | |
170 | fflush(stdout); | |
171 | ||
172 | if ((pid = fork()) == 0) | |
173 | { | |
174 | /* | |
175 | * Child goes here... | |
176 | */ | |
177 | ||
178 | execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL); | |
179 | exit(errno); | |
180 | } | |
181 | else if (pid < 0) | |
182 | { | |
183 | printf("testspeed: Fork failed: %s\n", strerror(errno)); | |
184 | break; | |
185 | } | |
186 | else | |
187 | printf("testspeed: Started child %d...\n", pid); | |
188 | } | |
189 | ||
190 | /* | |
191 | * Wait for children to finish... | |
192 | */ | |
193 | ||
194 | puts("testspeed: Waiting for children to finish..."); | |
195 | ||
196 | for (good_children = 0;;) | |
197 | { | |
198 | pid = wait(&status); | |
199 | ||
200 | if (pid < 0 && errno != EINTR) | |
201 | break; | |
202 | ||
203 | printf("testspeed: Ended child %d (%d)...\n", pid, status / 256); | |
204 | ||
205 | if (!status) | |
206 | good_children ++; | |
207 | } | |
208 | } | |
209 | ||
210 | /* | |
211 | * Compute the total run time... | |
212 | */ | |
213 | ||
214 | if (good_children > 0) | |
215 | { | |
216 | end = time(NULL); | |
217 | elapsed = end - start; | |
218 | i = good_children * requests; | |
219 | ||
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 | } | |
223 | ||
224 | /* | |
225 | * Exit with no errors... | |
226 | */ | |
227 | ||
228 | return (0); | |
229 | } | |
230 | ||
231 | ||
232 | /* | |
233 | * 'do_test()' - Run a test on a specific host... | |
234 | */ | |
235 | ||
236 | static int /* O - Exit status */ | |
237 | do_test(const char *server, /* I - Server to use */ | |
238 | int port, /* I - Port number to use */ | |
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 */ | |
245 | ipp_t *request; /* IPP Request */ | |
246 | struct timeval start, /* Start time */ | |
247 | end; /* End time */ | |
248 | double reqtime, /* Time for this request */ | |
249 | elapsed; /* Elapsed time */ | |
250 | int op; /* Current operation */ | |
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 | ||
264 | if ((http = httpConnectEncrypt(server, port, encryption)) == NULL) | |
265 | { | |
266 | printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(), | |
267 | strerror(errno)); | |
268 | return (1); | |
269 | } | |
270 | ||
271 | /* | |
272 | * Do multiple requests... | |
273 | */ | |
274 | ||
275 | for (elapsed = 0.0, i = 0; i < requests; i ++) | |
276 | { | |
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 | ||
286 | op = ops[i & 3]; | |
287 | request = ippNewRequest(op); | |
288 | ||
289 | gettimeofday(&start, NULL); | |
290 | ||
291 | if (verbose) | |
292 | printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed, | |
293 | ippOpString(op)); | |
294 | ||
295 | switch (op) | |
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 : | |
302 | ippDelete(cupsDoRequest(http, request, "/")); | |
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"); | |
308 | ippDelete(cupsDoFileRequest(http, request, "/printers/test", | |
309 | "../data/testprint.ps")); | |
310 | break; | |
311 | } | |
312 | ||
313 | gettimeofday(&end, NULL); | |
314 | ||
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; | |
329 | ||
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 | } | |
339 | } | |
340 | ||
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 | ||
354 | static void | |
355 | usage(void) | |
356 | { | |
357 | puts("Usage: testspeed [-c children] [-h] [-r requests] [-v] [-E] " | |
358 | "hostname[:port]"); | |
359 | exit(0); | |
360 | } | |
361 | ||
362 | ||
363 | ||
364 | /* | |
365 | * End of "$Id: testspeed.c 7727 2008-07-14 18:02:21Z mike $". | |
366 | */ |