]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/testspeed.c
Add (undocumented) -T option to print the current sandbox profile to stdout.
[thirdparty/cups.git] / scheduler / testspeed.c
CommitLineData
ef416fc2 1/*
23ef1cac 2 * "$Id$"
ef416fc2 3 *
7e86f2f6 4 * Scheduler speed test for CUPS.
ef416fc2 5 *
7e86f2f6
MS
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2005 by Easy Software Products.
ef416fc2 8 *
7e86f2f6
MS
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/".
ef416fc2 14 */
15
16/*
17 * Include necessary headers...
18 */
19
71e16022 20#include <cups/string-private.h>
ef416fc2 21#include <cups/cups.h>
22#include <cups/language.h>
71e16022 23#include <cups/debug-private.h>
75bd9771
MS
24#include <sys/types.h>
25#include <sys/time.h>
26#include <sys/wait.h>
ef416fc2 27
28
29/*
30 * Local functions...
31 */
32
dd1abb6b
MS
33static int do_test(const char *server, int port,
34 http_encryption_t encryption, int requests,
23ef1cac 35 const char *opstring, int verbose);
85dda01c 36static void usage(void) __attribute__((noreturn));
ef416fc2 37
38
39/*
40 * 'main()' - Send multiple IPP requests and report on the average response
41 * time.
42 */
43
44int
45main(int argc, /* I - Number of command-line arguments */
46 char *argv[]) /* I - Command-line arguments */
47{
48 int i; /* Looping var */
dd1abb6b
MS
49 char *server, /* Server to use */
50 *ptr; /* Pointer to port in server */
51 int port; /* Port to use */
ef416fc2 52 http_encryption_t encryption; /* Encryption to use */
53 int requests; /* Number of requests to send */
54 int children; /* Number of children to fork */
dd1abb6b 55 int good_children; /* Number of children that exited normally */
ef416fc2 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 */
23ef1cac 62 const char *opstring; /* Operation name */
ef416fc2 63
64
65 /*
66 * Parse command-line options...
67 */
68
69 requests = 100;
70 children = 5;
dd1abb6b
MS
71 server = (char *)cupsServer();
72 port = ippPort();
ef416fc2 73 encryption = HTTP_ENCRYPT_IF_REQUESTED;
74 verbose = 0;
23ef1cac 75 opstring = NULL;
ef416fc2 76
77 for (i = 1; i < argc; i ++)
dd1abb6b 78 if (argv[i][0] == '-')
ef416fc2 79 {
dd1abb6b
MS
80 for (ptr = argv[i] + 1; *ptr; ptr ++)
81 switch (*ptr)
82 {
23ef1cac
MS
83 case 'E' : /* Enable encryption */
84 encryption = HTTP_ENCRYPT_REQUIRED;
85 break;
86
dd1abb6b
MS
87 case 'c' : /* Number of children */
88 i ++;
89 if (i >= argc)
90 usage();
91
92 children = atoi(argv[i]);
93 break;
94
23ef1cac 95 case 'o' : /* Operation */
dd1abb6b
MS
96 i ++;
97 if (i >= argc)
98 usage();
99
23ef1cac 100 opstring = argv[i];
dd1abb6b
MS
101 break;
102
23ef1cac
MS
103 case 'r' : /* Number of requests */
104 i ++;
105 if (i >= argc)
106 usage();
107
108 requests = atoi(argv[i]);
dd1abb6b
MS
109 break;
110
111 case 'v' : /* Verbose logging */
112 verbose ++;
113 break;
114
115 default :
116 usage();
117 break;
118 }
ef416fc2 119 }
dd1abb6b 120 else
ef416fc2 121 {
dd1abb6b 122 server = argv[i];
ef416fc2 123
dd1abb6b
MS
124 if (server[0] != '/' && (ptr = strrchr(server, ':')) != NULL)
125 {
126 *ptr++ = '\0';
127 port = atoi(ptr);
128 }
ef416fc2 129 }
ef416fc2 130
131 /*
132 * Then create child processes to act as clients...
133 */
134
dd1abb6b
MS
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 }
ef416fc2 141
142 start = time(NULL);
143
dd1abb6b 144 if (children < 1)
23ef1cac 145 return (do_test(server, port, encryption, requests, opstring, verbose));
dd1abb6b 146 else if (children == 1)
23ef1cac
MS
147 good_children = do_test(server, port, encryption, requests, opstring,
148 verbose) ? 0 : 1;
ef416fc2 149 else
150 {
dd1abb6b
MS
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
ef416fc2 171 for (i = 0; i < children; i ++)
dd1abb6b
MS
172 {
173 fflush(stdout);
174
ef416fc2 175 if ((pid = fork()) == 0)
176 {
177 /*
178 * Child goes here...
179 */
180
23ef1cac
MS
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
dd1abb6b 187 exit(errno);
ef416fc2 188 }
189 else if (pid < 0)
190 {
dd1abb6b 191 printf("testspeed: Fork failed: %s\n", strerror(errno));
ef416fc2 192 break;
193 }
194 else
dd1abb6b
MS
195 printf("testspeed: Started child %d...\n", pid);
196 }
ef416fc2 197
198 /*
199 * Wait for children to finish...
200 */
201
dd1abb6b
MS
202 puts("testspeed: Waiting for children to finish...");
203
204 for (good_children = 0;;)
ef416fc2 205 {
206 pid = wait(&status);
207
208 if (pid < 0 && errno != EINTR)
209 break;
210
dd1abb6b
MS
211 printf("testspeed: Ended child %d (%d)...\n", pid, status / 256);
212
213 if (!status)
214 good_children ++;
ef416fc2 215 }
216 }
217
218 /*
219 * Compute the total run time...
220 */
221
dd1abb6b
MS
222 if (good_children > 0)
223 {
224 end = time(NULL);
225 elapsed = end - start;
226 i = good_children * requests;
ef416fc2 227
dd1abb6b
MS
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 }
ef416fc2 231
232 /*
233 * Exit with no errors...
234 */
235
91c84a35 236 return (0);
ef416fc2 237}
238
239
240/*
241 * 'do_test()' - Run a test on a specific host...
242 */
243
e1d6a774 244static int /* O - Exit status */
ef416fc2 245do_test(const char *server, /* I - Server to use */
dd1abb6b 246 int port, /* I - Port number to use */
ef416fc2 247 http_encryption_t encryption, /* I - Encryption to use */
248 int requests, /* I - Number of requests to send */
23ef1cac 249 const char *opstring, /* I - Operation string */
ef416fc2 250 int verbose) /* I - Verbose output? */
251{
252 int i; /* Looping var */
253 http_t *http; /* Connection to server */
dd1abb6b 254 ipp_t *request; /* IPP Request */
ef416fc2 255 struct timeval start, /* Start time */
256 end; /* End time */
dd1abb6b
MS
257 double reqtime, /* Time for this request */
258 elapsed; /* Elapsed time */
259 int op; /* Current operation */
23ef1cac 260 static ipp_op_t ops[5] = /* Operations to test... */
ef416fc2 261 {
262 IPP_PRINT_JOB,
23ef1cac 263 CUPS_GET_DEFAULT,
ef416fc2 264 CUPS_GET_PRINTERS,
265 CUPS_GET_CLASSES,
266 IPP_GET_JOBS
267 };
268
269
270 /*
271 * Connect to the server...
272 */
273
dd1abb6b 274 if ((http = httpConnectEncrypt(server, port, encryption)) == NULL)
ef416fc2 275 {
dd1abb6b
MS
276 printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(),
277 strerror(errno));
ef416fc2 278 return (1);
279 }
280
ef416fc2 281 /*
282 * Do multiple requests...
283 */
284
285 for (elapsed = 0.0, i = 0; i < requests; i ++)
286 {
ef416fc2 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
23ef1cac
MS
296 if (opstring)
297 op = ippOpValue(opstring);
298 else
7e86f2f6 299 op = ops[i % (int)(sizeof(ops) / sizeof(ops[0]))];
23ef1cac 300
dd1abb6b 301 request = ippNewRequest(op);
ef416fc2 302
303 gettimeofday(&start, NULL);
304
dd1abb6b
MS
305 if (verbose)
306 printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed,
307 ippOpString(op));
308
309 switch (op)
ef416fc2 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 :
dd1abb6b 316 ippDelete(cupsDoRequest(http, request, "/"));
ef416fc2 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");
dd1abb6b
MS
322 ippDelete(cupsDoFileRequest(http, request, "/printers/test",
323 "../data/testprint.ps"));
ef416fc2 324 break;
325 }
326
327 gettimeofday(&end, NULL);
328
dd1abb6b
MS
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;
ef416fc2 343
dd1abb6b
MS
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 }
ef416fc2 353 }
354
ef416fc2 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
e1d6a774 368static void
ef416fc2 369usage(void)
370{
23ef1cac
MS
371 puts("Usage: testspeed [-c children] [-h] [-o operation] [-r requests] [-v] "
372 "[-E] hostname[:port]");
ef416fc2 373 exit(0);
374}
375
376
377
378/*
23ef1cac 379 * End of "$Id$".
ef416fc2 380 */