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