de7cc73f906fe8d1bacef8d96423c236e0ff7953
[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 void
71 async_BulkProc(data)
72      char *data;
73 {
74     struct async_work *work = (struct async_work *)data;
75     struct rx_call *call;
76     struct clock startTime, endTime;
77     long length;
78     long error;
79     long msec;
80     int i;
81
82     for (i = 0; i < work->count; i++) {
83         call = rx_NewCall(work->conn);
84         clock_NewTime();
85         clock_GetTime(&startTime);
86         error =
87             ((work->store ? StoreFile : FetchFile) (call, work->verbose,
88                                                     work->local, work->remote,
89                                                     &length));
90         error = rx_EndCall(call, error);
91
92         clock_NewTime();
93         clock_GetTime(&endTime);
94         msec = clock_ElapsedTime(&startTime, &endTime);
95         if (work->verbose && !error)
96             printf("%s: %s %s, %d bytes in %d msec, %d bps\n", work->host,
97                    work->store ? "stored" : "fetched",
98                    work->store ? work->local : work->remote, length, msec,
99                    length * 1000 / msec);
100         else if (error)
101             printf("%s: %s of %s failed: error %d\n", work->host,
102                    work->store ? "store" : "fetch",
103                    work->store ? work->local : work->remote, error);
104     }
105     async_nProcs--;
106     osi_Wakeup(&async_nProcs);
107 }
108
109 async_BulkTest(host, conn, store, count, verbose, file)
110      char *host;
111      struct rx_connection *conn;
112      int store;
113      int count;
114      int verbose;
115      char *file;
116 {
117     char tempfile[256];
118     char *name;
119     PROCESS pid;
120     struct async_work *work =
121         (struct async_work *)malloc(sizeof(struct async_work));
122     work->host = host;
123     work->conn = conn;
124     work->store = store;
125     work->count = count;
126     work->verbose = verbose;
127     name = strrchr(file, '/');
128     if (!name)
129         name = file;
130     else
131         name++;
132 /*   sprintf(tempfile, "/usr/tmp/%s.%s", myHostName, name);*/
133     sprintf(tempfile, "/usr/tmp/%s", name);
134     work->local = strdup(store ? file : tempfile);
135     work->remote = strdup(store ? tempfile : file);
136     async_nProcs += 1;
137     LWP_CreateProcess(async_BulkProc, 3000, RX_PROCESS_PRIORITY, (void *)work,
138                       "bulk", &pid);
139 }
140
141 long
142 FetchFile(call, verbose, localFile, remoteFile, length_ptr)
143      struct rx_call *call;
144      int verbose;
145      char *localFile, *remoteFile;
146      long *length_ptr;
147 {
148     int fd = -1, error = 0;
149     struct stat status;
150
151     if (StartBULK_FetchFile(call, verbose, remoteFile))
152         return BULK_ERROR;
153     fd = open(localFile, O_CREAT | O_TRUNC | O_WRONLY, 0666);
154     if (fd < 0 || fstat(fd, &status) < 0) {
155         fprintf("Could not create %s\n", localFile);
156         error = BULK_ERROR;
157     } else if (bulk_ReceiveFile(fd, call, &status))
158         error = BULK_ERROR;
159     *length_ptr = status.st_size;
160     if (fd >= 0)
161         close(fd);
162     /*  If there were any output parameters, then it would be necessary to call EndBULKFetchFile(call, &out1,...) here to pick them up */
163     return error;
164 }
165
166 long
167 StoreFile(call, verbose, localFile, remoteFile, length_ptr)
168      struct rx_call *call;
169      int verbose;
170      char *localFile, *remoteFile;
171      long *length_ptr;
172 {
173     int fd = -1, error = 0;
174     struct stat status;
175
176     fd = open(localFile, O_RDONLY, 0);
177     if (fd < 0 || fstat(fd, &status) < 0) {
178         fprintf("Could not open %s\n", localFile);
179         return BULK_ERROR;
180     }
181     error = StartBULK_StoreFile(call, verbose, remoteFile);
182     if (!error)
183         error = bulk_SendFile(fd, call, &status);
184     /*  If there were any output parameters, then it would be necessary to call EndBULKStoreFile(call, &out1,...) here to pick them up */
185     close(fd);
186     *length_ptr = status.st_size;
187     return error;
188 }
189
190 main(argc, argv)
191      char **argv;
192 {
193     int store = 0;
194     int count = 1;
195     int verbose = 0;
196     char *hostname = NULL;
197     u_long host;
198     struct rx_securityClass *null_securityObject;
199     struct rx_connection *conn = (struct rx_connection *)0;
200     gethostname(myHostName, sizeof(myHostName));
201     signal(SIGINT, InterruptSignal);
202     rx_Init(0);
203
204     null_securityObject = rxnull_NewClientSecurityObject();
205     argc--;
206     argv++;
207     while (argc) {
208         while (**argv == '-') {
209             if (strcmp(*argv, "-h") == 0) {
210                 hostname = *++argv;
211                 argc--;
212                 host = GetIpAddress(hostname);
213                 conn =
214                     rx_NewConnection(host, BULK_SERVER_PORT, BULK_SERVICE_ID,
215                                      null_securityObject, BULK_NULL);
216             } else if (strcmp(*argv, "-f") == 0)
217                 store = 0;
218             else if (strcmp(*argv, "-s") == 0)
219                 store = 1;
220             else if (strcmp(*argv, "-v") == 0)
221                 verbose = 1;
222             else if (strcmp(*argv, "-c") == 0)
223                 (count = atoi(*++argv)), argc--;
224             else {
225                 fprintf(stderr, "Unknown option %s\n", *argv);
226                 exit(1);
227             }
228             argc--;
229             argv++;
230         }
231         if (argc < 1) {
232             fprintf(stderr, "local + remote file names expected\n");
233             exit(1);
234         }
235         if (conn == (struct rx_connection *)0) {
236             fprintf(stderr, "No host specified\n");
237             exit(1);
238         }
239         async_BulkTest(hostname, conn, store, count, verbose, argv[0]);
240         argv++;
241         argc--;
242     }
243     while (async_nProcs)
244         osi_Sleep(&async_nProcs);
245     if (verbose)
246         fprintf(stderr, "All transfers done\n");
247     rx_PrintStats(stdout);
248     /* Allow Rx to idle down any calls; it's a good idea, but not essential, to call this routine */
249     rx_Finalize();
250 }