2 * Scheduler speed test for CUPS.
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2005 by Easy Software Products.
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
11 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * Include necessary headers...
18 #include <cups/string-private.h>
19 #include <cups/cups.h>
20 #include <cups/language.h>
21 #include <cups/debug-private.h>
22 #include <sys/types.h>
31 static int do_test(const char *server
, int port
,
32 http_encryption_t encryption
, int requests
,
33 const char *opstring
, int verbose
);
34 static void usage(void) __attribute__((noreturn
));
38 * 'main()' - Send multiple IPP requests and report on the average response
43 main(int argc
, /* I - Number of command-line arguments */
44 char *argv
[]) /* I - Command-line arguments */
46 int i
; /* Looping var */
47 char *server
, /* Server to use */
48 *ptr
; /* Pointer to port in server */
49 int port
; /* Port to use */
50 http_encryption_t encryption
; /* Encryption to use */
51 int requests
; /* Number of requests to send */
52 int children
; /* Number of children to fork */
53 int good_children
; /* Number of children that exited normally */
54 int pid
; /* Child PID */
55 int status
; /* Child status */
56 time_t start
, /* Start time */
58 double elapsed
; /* Elapsed time */
59 int verbose
; /* Verbosity */
60 const char *opstring
; /* Operation name */
64 * Parse command-line options...
69 server
= (char *)cupsServer();
71 encryption
= HTTP_ENCRYPT_IF_REQUESTED
;
75 for (i
= 1; i
< argc
; i
++)
76 if (argv
[i
][0] == '-')
78 for (ptr
= argv
[i
] + 1; *ptr
; ptr
++)
81 case 'E' : /* Enable encryption */
82 encryption
= HTTP_ENCRYPT_REQUIRED
;
85 case 'c' : /* Number of children */
90 children
= atoi(argv
[i
]);
93 case 'o' : /* Operation */
101 case 'r' : /* Number of requests */
106 requests
= atoi(argv
[i
]);
109 case 'v' : /* Verbose logging */
122 if (server
[0] != '/' && (ptr
= strrchr(server
, ':')) != NULL
)
130 * Then create child processes to act as clients...
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 " : "");
143 return (do_test(server
, port
, encryption
, requests
, opstring
, verbose
));
144 else if (children
== 1)
145 good_children
= do_test(server
, port
, encryption
, requests
, opstring
,
149 char options
[255], /* Command-line options for child */
150 reqstr
[255], /* Requests string for child */
151 serverstr
[255]; /* Server:port string for child */
154 snprintf(reqstr
, sizeof(reqstr
), "%d", requests
);
156 if (port
== 631 || server
[0] == '/')
157 strlcpy(serverstr
, server
, sizeof(serverstr
));
159 snprintf(serverstr
, sizeof(serverstr
), "%s:%d", server
, port
);
161 strlcpy(options
, "-cr", sizeof(options
));
163 if (encryption
== HTTP_ENCRYPT_REQUIRED
)
164 strlcat(options
, "E", sizeof(options
));
167 strlcat(options
, "v", sizeof(options
));
169 for (i
= 0; i
< children
; i
++)
173 if ((pid
= fork()) == 0)
180 execlp(argv
[0], argv
[0], options
, "0", reqstr
, "-o", opstring
,
181 serverstr
, (char *)NULL
);
183 execlp(argv
[0], argv
[0], options
, "0", reqstr
, serverstr
, (char *)NULL
);
189 printf("testspeed: Fork failed: %s\n", strerror(errno
));
193 printf("testspeed: Started child %d...\n", pid
);
197 * Wait for children to finish...
200 puts("testspeed: Waiting for children to finish...");
202 for (good_children
= 0;;)
206 if (pid
< 0 && errno
!= EINTR
)
209 printf("testspeed: Ended child %d (%d)...\n", pid
, status
/ 256);
217 * Compute the total run time...
220 if (good_children
> 0)
223 elapsed
= end
- start
;
224 i
= good_children
* requests
;
226 printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
227 good_children
, requests
, i
, elapsed
, elapsed
/ i
, i
/ elapsed
);
231 * Exit with no errors...
239 * 'do_test()' - Run a test on a specific host...
242 static int /* O - Exit status */
243 do_test(const char *server
, /* I - Server to use */
244 int port
, /* I - Port number to use */
245 http_encryption_t encryption
, /* I - Encryption to use */
246 int requests
, /* I - Number of requests to send */
247 const char *opstring
, /* I - Operation string */
248 int verbose
) /* I - Verbose output? */
250 int i
; /* Looping var */
251 http_t
*http
; /* Connection to server */
252 ipp_t
*request
; /* IPP Request */
253 struct timeval start
, /* Start time */
255 double reqtime
, /* Time for this request */
256 elapsed
; /* Elapsed time */
257 int op
; /* Current operation */
258 static ipp_op_t ops
[5] = /* Operations to test... */
269 * Connect to the server...
272 if ((http
= httpConnectEncrypt(server
, port
, encryption
)) == NULL
)
274 printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(),
280 * Do multiple requests...
283 for (elapsed
= 0.0, i
= 0; i
< requests
; i
++)
286 * Build a request which requires the following attributes:
289 * attributes-natural-language
291 * In addition, IPP_GET_JOBS needs a printer-uri attribute.
295 op
= ippOpValue(opstring
);
297 op
= ops
[i
% (int)(sizeof(ops
) / sizeof(ops
[0]))];
299 request
= ippNewRequest(op
);
301 gettimeofday(&start
, NULL
);
304 printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed
,
310 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
311 NULL
, "ipp://localhost/printers/");
314 ippDelete(cupsDoRequest(http
, request
, "/"));
318 ippAddString(request
, IPP_TAG_OPERATION
, IPP_TAG_URI
, "printer-uri",
319 NULL
, "ipp://localhost/printers/test");
320 ippDelete(cupsDoFileRequest(http
, request
, "/printers/test",
321 "../data/testprint.ps"));
325 gettimeofday(&end
, NULL
);
327 reqtime
= (end
.tv_sec
- start
.tv_sec
) +
328 0.000001 * (end
.tv_usec
- start
.tv_usec
);
331 switch (cupsLastError())
337 printf("succeeded: %s (%.6f)\n", cupsLastErrorString(), reqtime
);
344 printf("testspeed(%d): %s ", (int)getpid(),
345 ippOpString(ops
[i
& 3]));
347 printf("failed: %s\n", cupsLastErrorString());
355 printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
356 (int)getpid(), i
, elapsed
, elapsed
/ i
, i
/ elapsed
);
363 * 'usage()' - Show program usage...
369 puts("Usage: testspeed [-c children] [-h] [-o operation] [-r requests] [-v] "
370 "[-E] hostname[:port]");