]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/testspeed.c
Merge changes from CUPS 1.4svn-r7961.
[thirdparty/cups.git] / scheduler / testspeed.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: testspeed.c 7727 2008-07-14 18:02:21Z mike $"
ef416fc2 3 *
4 * Scheduler speed test for the Common UNIX Printing System (CUPS).
5 *
dd1abb6b 6 * Copyright 2007-2008 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
75bd9771 27#include <cups/string.h>
ef416fc2 28#include <cups/cups.h>
29#include <cups/language.h>
30#include <cups/debug.h>
75bd9771
MS
31#include <sys/types.h>
32#include <sys/time.h>
33#include <sys/wait.h>
ef416fc2 34#include <errno.h>
35
36
37/*
38 * Local functions...
39 */
40
dd1abb6b
MS
41static int do_test(const char *server, int port,
42 http_encryption_t encryption, int requests,
43 int verbose);
e1d6a774 44static void usage(void);
ef416fc2 45
46
47/*
48 * 'main()' - Send multiple IPP requests and report on the average response
49 * time.
50 */
51
52int
53main(int argc, /* I - Number of command-line arguments */
54 char *argv[]) /* I - Command-line arguments */
55{
56 int i; /* Looping var */
dd1abb6b
MS
57 char *server, /* Server to use */
58 *ptr; /* Pointer to port in server */
59 int port; /* Port to use */
ef416fc2 60 http_encryption_t encryption; /* Encryption to use */
61 int requests; /* Number of requests to send */
62 int children; /* Number of children to fork */
dd1abb6b 63 int good_children; /* Number of children that exited normally */
ef416fc2 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;
dd1abb6b
MS
78 server = (char *)cupsServer();
79 port = ippPort();
ef416fc2 80 encryption = HTTP_ENCRYPT_IF_REQUESTED;
81 verbose = 0;
82
83 for (i = 1; i < argc; i ++)
dd1abb6b 84 if (argv[i][0] == '-')
ef416fc2 85 {
dd1abb6b
MS
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 }
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
MS
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;
ef416fc2 146 else
147 {
dd1abb6b
MS
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
ef416fc2 168 for (i = 0; i < children; i ++)
dd1abb6b
MS
169 {
170 fflush(stdout);
171
ef416fc2 172 if ((pid = fork()) == 0)
173 {
174 /*
175 * Child goes here...
176 */
177
dd1abb6b
MS
178 execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL);
179 exit(errno);
ef416fc2 180 }
181 else if (pid < 0)
182 {
dd1abb6b 183 printf("testspeed: Fork failed: %s\n", strerror(errno));
ef416fc2 184 break;
185 }
186 else
dd1abb6b
MS
187 printf("testspeed: Started child %d...\n", pid);
188 }
ef416fc2 189
190 /*
191 * Wait for children to finish...
192 */
193
dd1abb6b
MS
194 puts("testspeed: Waiting for children to finish...");
195
196 for (good_children = 0;;)
ef416fc2 197 {
198 pid = wait(&status);
199
200 if (pid < 0 && errno != EINTR)
201 break;
202
dd1abb6b
MS
203 printf("testspeed: Ended child %d (%d)...\n", pid, status / 256);
204
205 if (!status)
206 good_children ++;
ef416fc2 207 }
208 }
209
210 /*
211 * Compute the total run time...
212 */
213
dd1abb6b
MS
214 if (good_children > 0)
215 {
216 end = time(NULL);
217 elapsed = end - start;
218 i = good_children * requests;
ef416fc2 219
dd1abb6b
MS
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 }
ef416fc2 223
224 /*
225 * Exit with no errors...
226 */
227
91c84a35 228 return (0);
ef416fc2 229}
230
231
232/*
233 * 'do_test()' - Run a test on a specific host...
234 */
235
e1d6a774 236static int /* O - Exit status */
ef416fc2 237do_test(const char *server, /* I - Server to use */
dd1abb6b 238 int port, /* I - Port number to use */
ef416fc2 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 */
dd1abb6b 245 ipp_t *request; /* IPP Request */
ef416fc2 246 struct timeval start, /* Start time */
247 end; /* End time */
dd1abb6b
MS
248 double reqtime, /* Time for this request */
249 elapsed; /* Elapsed time */
250 int op; /* Current operation */
ef416fc2 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
dd1abb6b 264 if ((http = httpConnectEncrypt(server, port, encryption)) == NULL)
ef416fc2 265 {
dd1abb6b
MS
266 printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(),
267 strerror(errno));
ef416fc2 268 return (1);
269 }
270
ef416fc2 271 /*
272 * Do multiple requests...
273 */
274
275 for (elapsed = 0.0, i = 0; i < requests; i ++)
276 {
ef416fc2 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
dd1abb6b
MS
286 op = ops[i & 3];
287 request = ippNewRequest(op);
ef416fc2 288
289 gettimeofday(&start, NULL);
290
dd1abb6b
MS
291 if (verbose)
292 printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed,
293 ippOpString(op));
294
295 switch (op)
ef416fc2 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 :
dd1abb6b 302 ippDelete(cupsDoRequest(http, request, "/"));
ef416fc2 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");
dd1abb6b
MS
308 ippDelete(cupsDoFileRequest(http, request, "/printers/test",
309 "../data/testprint.ps"));
ef416fc2 310 break;
311 }
312
313 gettimeofday(&end, NULL);
314
dd1abb6b
MS
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;
ef416fc2 329
dd1abb6b
MS
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 }
ef416fc2 339 }
340
ef416fc2 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
e1d6a774 354static void
ef416fc2 355usage(void)
356{
dd1abb6b
MS
357 puts("Usage: testspeed [-c children] [-h] [-r requests] [-v] [-E] "
358 "hostname[:port]");
ef416fc2 359 exit(0);
360}
361
362
363
364/*
b19ccc9e 365 * End of "$Id: testspeed.c 7727 2008-07-14 18:02:21Z mike $".
ef416fc2 366 */