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