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