87129d0490fe1c5dc9032e6f458fa0b3528b3473
[openafs.git] / src / rx / bulktest / bulk_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
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/file.h>
19 #include <netdb.h>
20 #include <netinet/in.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include <rx/rx.h>
24 #include <rx/rx_null.h>
25 #include "bulk.h"
26
27 char myHostName[256];
28
29 InterruptSignal()
30 {
31     rx_PrintStats(stdout);
32     exit(0);
33 }
34
35
36 /* Bogus procedure to get internet address of host */
37 static u_long
38 GetIpAddress(hostname)
39      char *hostname;
40 {
41     struct hostent *hostent;
42     u_long host;
43     hostent = gethostbyname(hostname);
44     if (!hostent) {
45         printf("host %s not found", hostname);
46         exit(1);
47     }
48     if (hostent->h_length != sizeof(u_long)) {
49         printf("host address is disagreeable length (%d)", hostent->h_length);
50         exit(1);
51     }
52     memcpy((char *)&host, hostent->h_addr, sizeof(host));
53     return host;
54 }
55
56 long FetchFile(), StoreFile();
57
58 struct async_work {
59     char *host;
60     struct rx_connection *conn;
61     int store;
62     int count;
63     int verbose;
64     char *local;
65     char *remote;
66 };
67
68 int async_nProcs = 0;
69
70 char *
71 allocString(s)
72      char *s;
73 {
74     char *new = (char *)malloc(strlen(s) + 1);
75     strcpy(new, s);
76     return new;
77 }
78
79 void
80 async_BulkProc(data)
81      char *data;
82 {
83     struct async_work *work = (struct async_work *)data;
84     struct rx_call *call;
85     struct clock startTime, endTime;
86     long length;
87     long error;
88     long msec;
89     int i;
90
91     for (i = 0; i < work->count; i++) {
92         call = rx_NewCall(work->conn);
93         clock_NewTime();
94         clock_GetTime(&startTime);
95         error =
96             ((work->store ? StoreFile : FetchFile) (call, work->verbose,
97                                                     work->local, work->remote,
98                                                     &length));
99         error = rx_EndCall(call, error);
100
101         clock_NewTime();
102         clock_GetTime(&endTime);
103         msec = clock_ElapsedTime(&startTime, &endTime);
104         if (work->verbose && !error)
105             printf("%s: %s %s, %d bytes in %d msec, %d bps\n", work->host,
106                    work->store ? "stored" : "fetched",
107                    work->store ? work->local : work->remote, length, msec,
108                    length * 1000 / msec);
109         else if (error)
110             printf("%s: %s of %s failed: error %d\n", work->host,
111                    work->store ? "store" : "fetch",
112                    work->store ? work->local : work->remote, error);
113     }
114     async_nProcs--;
115     osi_Wakeup(&async_nProcs);
116 }
117
118 async_BulkTest(host, conn, store, count, verbose, file)
119      char *host;
120      struct rx_connection *conn;
121      int store;
122      int count;
123      int verbose;
124      char *file;
125 {
126     char tempfile[256];
127     char *name;
128     PROCESS pid;
129     struct async_work *work =
130         (struct async_work *)malloc(sizeof(struct async_work));
131     work->host = host;
132     work->conn = conn;
133     work->store = store;
134     work->count = count;
135     work->verbose = verbose;
136     name = strrchr(file, '/');
137     if (!name)
138         name = file;
139     else
140         name++;
141 /*   sprintf(tempfile, "/usr/tmp/%s.%s", myHostName, name);*/
142     sprintf(tempfile, "/usr/tmp/%s", name);
143     work->local = allocString(store ? file : tempfile);
144     work->remote = allocString(store ? tempfile : file);
145     async_nProcs += 1;
146     LWP_CreateProcess(async_BulkProc, 3000, RX_PROCESS_PRIORITY, (void *)work,
147                       "bulk", &pid);
148 }
149
150 long
151 FetchFile(call, verbose, localFile, remoteFile, length_ptr)
152      struct rx_call *call;
153      int verbose;
154      char *localFile, *remoteFile;
155      long *length_ptr;
156 {
157     int fd = -1, error = 0;
158     struct stat status;
159
160     if (StartBULK_FetchFile(call, verbose, remoteFile))
161         return BULK_ERROR;
162     fd = open(localFile, O_CREAT | O_TRUNC | O_WRONLY, 0666);
163     if (fd < 0 || fstat(fd, &status) < 0) {
164         fprintf("Could not create %s\n", localFile);
165         error = BULK_ERROR;
166     } else if (bulk_ReceiveFile(fd, call, &status))
167         error = BULK_ERROR;
168     *length_ptr = status.st_size;
169     if (fd >= 0)
170         close(fd);
171     /*  If there were any output parameters, then it would be necessary to call EndBULKFetchFile(call, &out1,...) here to pick them up */
172     return error;
173 }
174
175 long
176 StoreFile(call, verbose, localFile, remoteFile, length_ptr)
177      struct rx_call *call;
178      int verbose;
179      char *localFile, *remoteFile;
180      long *length_ptr;
181 {
182     int fd = -1, error = 0;
183     struct stat status;
184
185     fd = open(localFile, O_RDONLY, 0);
186     if (fd < 0 || fstat(fd, &status) < 0) {
187         fprintf("Could not open %s\n", localFile);
188         return BULK_ERROR;
189     }
190     error = StartBULK_StoreFile(call, verbose, remoteFile);
191     if (!error)
192         error = bulk_SendFile(fd, call, &status);
193     /*  If there were any output parameters, then it would be necessary to call EndBULKStoreFile(call, &out1,...) here to pick them up */
194     close(fd);
195     *length_ptr = status.st_size;
196     return error;
197 }
198
199 main(argc, argv)
200      char **argv;
201 {
202     int store = 0;
203     int count = 1;
204     int verbose = 0;
205     char *hostname = NULL;
206     u_long host;
207     struct rx_securityClass *null_securityObject;
208     struct rx_connection *conn = (struct rx_connection *)0;
209     gethostname(myHostName, sizeof(myHostName));
210     signal(SIGINT, InterruptSignal);
211     rx_Init(0);
212
213     null_securityObject = rxnull_NewClientSecurityObject();
214     argc--;
215     argv++;
216     while (argc) {
217         while (**argv == '-') {
218             if (strcmp(*argv, "-h") == 0) {
219                 hostname = *++argv;
220                 argc--;
221                 host = GetIpAddress(hostname);
222                 conn =
223                     rx_NewConnection(host, BULK_SERVER_PORT, BULK_SERVICE_ID,
224                                      null_securityObject, BULK_NULL);
225             } else if (strcmp(*argv, "-f") == 0)
226                 store = 0;
227             else if (strcmp(*argv, "-s") == 0)
228                 store = 1;
229             else if (strcmp(*argv, "-v") == 0)
230                 verbose = 1;
231             else if (strcmp(*argv, "-c") == 0)
232                 (count = atoi(*++argv)), argc--;
233             else {
234                 fprintf(stderr, "Unknown option %s\n", *argv);
235                 exit(1);
236             }
237             argc--;
238             argv++;
239         }
240         if (argc < 1) {
241             fprintf(stderr, "local + remote file names expected\n");
242             exit(1);
243         }
244         if (conn == (struct rx_connection *)0) {
245             fprintf(stderr, "No host specified\n");
246             exit(1);
247         }
248         async_BulkTest(hostname, conn, store, count, verbose, argv[0]);
249         argv++;
250         argc--;
251     }
252     while (async_nProcs)
253         osi_Sleep(&async_nProcs);
254     if (verbose)
255         fprintf(stderr, "All transfers done\n");
256     rx_PrintStats(stdout);
257     /* Allow Rx to idle down any calls; it's a good idea, but not essential, to call this routine */
258     rx_Finalize();
259 }