include-afsconfig-before-param-h-20010712
[openafs.git] / src / rx / multi.example / sample_client.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* Sample program using multi_Rx, to execute calls in parallel to multiple hosts */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 RCSID("$Header$");
16
17 #include <sys/types.h>
18 #include <netdb.h>
19 #include <netinet/in.h>
20 #include <stdio.h>
21 #include "sample.h"
22 #include "rx/rx_clock.h"
23
24 /* Bogus procedure to get internet address of host */
25 static u_long GetIpAddress(hostname)
26     char *hostname;
27 {
28     struct hostent *hostent;
29     u_long host;
30     hostent = gethostbyname(hostname);
31     if (!hostent) {printf("host %s not found", hostname);exit(1);}
32     if (hostent->h_length != sizeof(u_long)) {
33         printf("host address is disagreeable length (%d)", hostent->h_length);
34         exit(1);
35     }
36     bcopy(hostent->h_addr, (char *)&host, sizeof(host));
37     return host;
38 }
39
40 main(argc, argv)
41     char **argv;
42 {
43     struct rx_securityClass *null_securityObject;
44     register int i, nHosts = 0;
45     struct {
46         u_long ipaddr;
47         char *name;
48     } host[50];
49     int arg[50];
50     struct rx_connection *conns[50];
51     int nSuccesses = 0;
52     register int trials=1;
53     register int verbose=0;
54     register int abort=0;
55     int msec;
56     struct clock startTime, endTime;
57     int result;
58     argc--; argv++;
59     while (**argv == '-') {
60         if (strcmp(*argv, "-verbose") == 0) verbose = 1;
61         else if (strcmp(*argv, "-count") == 0) trials = atoi(*++argv), argc--;
62         else if (strcmp(*argv, "-abort") == 0) abort = 1;
63         else {
64             fprintf("Unknown option %s\n", *argv);
65             exit(1);
66         }
67         argc--; argv++;
68     }
69     while (argc--) {
70         host[nHosts].name = *argv;
71         host[nHosts].ipaddr = GetIpAddress(*argv);
72         arg[nHosts] = 10000*(nHosts+1); /* a bogus argument to show how an input argument to the multi call can be indexed by multi_i */
73         nHosts++;
74         argv++;
75     }
76
77     rx_Init(0);
78     null_securityObject = rxnull_NewClientSecurityObject();
79     for (i=0; i<nHosts; i++) {
80         conns[i] = rx_NewConnection(host[i].ipaddr, SAMPLE_SERVER_PORT, SAMPLE_SERVICE_ID, null_securityObject, SAMPLE_NULL);
81     }
82
83     clock_NewTime();
84     clock_GetTime(&startTime);
85     for (i=0;i<trials;i++) {
86         multi_Rx(conns, nHosts) {
87             /* Note that multi_i is available both for arguments (result could also be indexed by multi_i, if you want to keep the results apart, and after the call completes) and in the code which follows the completion of each multi_TEST_Add.  At completion, multi_i will be set to the connection index of the call which completed, and multi_error will be set to the error code returned by that call. */
88             if (verbose) printf("%s:  About to add %d to %d\n", host[multi_i].name, arg[multi_i], i*10, &result);
89             multi_TEST_Add(verbose, arg[multi_i], i*10, &result);
90             if (verbose) printf("%s: error %d, %d + %d is %d\n", host[multi_i].name, multi_error, arg[multi_i], i*10, result);
91             if (abort && multi_error) multi_Abort;
92             if (multi_error == 0) nSuccesses++;
93             else if (!verbose) printf("%s: error %d\n", host[multi_i].name, multi_error);
94         } multi_End;
95     }
96     clock_NewTime();
97     clock_GetTime(&endTime);
98     msec = clock_ElapsedTime(&startTime, &endTime);
99     printf("nSuccesses=%d in %d msec; %d msec per iteration for %d iterations over %d hosts\n", nSuccesses, msec, msec/trials, trials, nHosts);
100
101     /* Allow Rx to idle down any calls; it's a good idea, but not essential, to call this routine */
102     rx_Finalize();
103 }