no-copy-libafs-builds-20021015
[openafs.git] / src / rx / test / testclient.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 /* Client test program */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 RCSID("$Header$");
16
17 #include <sys/types.h>
18 #include <stdio.h>
19 #ifdef AFS_NT40_ENV
20 #include <io.h>
21 #include <winsock2.h>
22 #include <fcntl.h>
23 #include <stdlib.h>
24 #else
25 #include <netinet/in.h>
26 #include <netdb.h>
27 #include <sys/file.h>
28 #endif
29 #include <sys/stat.h>
30 #include <signal.h>
31 #include "rx_clock.h"
32 #include "rx.h"
33 #include "rx_globals.h"
34 #include "rx_null.h"
35 #include <errno.h>
36 #include <afs/afsutil.h>
37
38 #ifndef osi_Alloc
39 #define osi_Alloc(n) (char *) malloc(n)
40 #endif
41
42 int timeReadvs = 0;
43 int print = 1, eventlog = 0, rxlog = 0;
44 int fillPackets;
45 int burst; struct clock burstTime;
46 struct clock retryTime;
47 extern int rx_initSendWindow, rx_initReceiveWindow;
48 extern int rxi_nSendFrags, rxi_nRecvFrags;
49 extern rx_intentionallyDroppedPacketsPer100;
50 extern int (*rxi_syscallp)();
51 FILE *debugFile;
52 int timeout;
53 struct clock waitTime, computeTime;
54
55 void OpenFD();
56
57 void intSignal(int ignore) {
58     Quit("Interrupted");
59 }
60
61 void quitSignal(int ignore) {
62     static int quitCount = 0;
63     if (++quitCount > 1) Quit("rx_ctest: second quit signal, aborting");
64     rx_debugFile = debugFile = fopen("rx_ctest.db", "w");
65     if (debugFile) rx_PrintStats(debugFile);
66 }
67
68 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV)
69 int test_syscall(a3, a4, a5)
70 afs_uint32 a3, a4;
71 void * a5;
72 {
73   afs_uint32 rcode;
74   void (*old)(int);
75         
76   old = signal(SIGSYS, SIG_IGN);        
77   rcode = syscall (31 /* AFS_SYSCALL */, 28 /* AFSCALL_CALL */, a3, a4, a5);
78   signal(SIGSYS, old);  
79
80 return rcode;
81 }
82 #endif
83
84 main(argc, argv)
85 char **argv;
86 {
87     char *hostname;
88     struct hostent *hostent;
89     afs_uint32 host;
90     int logstdout = 0;
91     struct rx_connection *conn;
92     struct rx_call *call;
93     int err = 0;
94     int nCalls = 1, nBytes = 1;
95     int bufferSize = 2000;
96     char *buffer;
97     char *sendFile = 0;
98     int setFD = 0;
99
100 #if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV)
101     setlinebuf(stdout);
102     rxi_syscallp = test_syscall;
103 #endif
104
105
106     argv++; argc--;
107     while (argc && **argv == '-') {
108         if (strcmp(*argv, "-silent") == 0) print = 0;
109         else if (strcmp(*argv, "-nc") == 0) nCalls = atoi(*++argv), argc--;
110         else if (strcmp(*argv, "-nb") == 0) nBytes = atoi(*++argv), argc--;
111         else if (strcmp(*argv, "-npb") == 0) rx_nPackets = atoi(*++argv), argc--;
112         else if (!strcmp(*argv, "-nsf")) 
113              rxi_nSendFrags =  atoi(*++argv), argc--;
114         else if (!strcmp(*argv, "-nrf")) 
115              rxi_nRecvFrags =  atoi(*++argv), argc--;
116         else if (strcmp(*argv, "-twind") == 0) 
117              rx_initSendWindow = atoi(*++argv), argc--;
118         else if (strcmp(*argv, "-rwind") == 0) 
119              rx_initReceiveWindow = atoi(*++argv), argc--;
120         else if (strcmp(*argv, "-rxlog") == 0) rxlog = 1;
121         else if (strcmp(*argv, "-logstdout") == 0) logstdout = 1;
122         else if (strcmp(*argv, "-eventlog") == 0) eventlog = 1;
123         else if (strcmp(*argv, "-drop") == 0) rx_intentionallyDroppedPacketsPer100 = atoi(*++argv), argc--;
124         else if (strcmp(*argv, "-burst") == 0) {
125             burst = atoi(*++argv), argc--;
126             burstTime.sec = atoi(*++argv), argc--;
127             burstTime.usec = atoi(*++argv), argc--;
128         }
129         else if (strcmp(*argv, "-retry") == 0) {
130             retryTime.sec = atoi(*++argv), argc--;
131             retryTime.usec = atoi(*++argv), argc--;
132         }
133         else if (strcmp(*argv, "-timeout") == 0) timeout = atoi(*++argv), argc--;
134         else if (strcmp(*argv, "-fill") == 0) fillPackets++;
135         else if (strcmp(*argv, "-file") == 0) sendFile = *++argv, argc--;
136         else if (strcmp(*argv, "-timereadvs") == 0) timeReadvs = 1;
137         else if (strcmp(*argv, "-wait") == 0) {
138             /* Wait time between calls--to test lastack code */
139             waitTime.sec = atoi(*++argv), argc--;
140             waitTime.usec = atoi(*++argv), argc--;
141         }
142         else if (strcmp(*argv, "-compute") == 0) {
143             /* Simulated "compute" time for each call--to test acknowledgement protocol.  This is simulated by doing an iomgr_select:  imperfect, admittedly. */
144             computeTime.sec = atoi(*++argv), argc--;
145             computeTime.usec = atoi(*++argv), argc--;
146         }
147         else if (strcmp(*argv, "-fd") == 0) {
148             /* Open at least this many fd's. */
149             setFD = atoi(*++argv), argc--;
150         }
151         else {err = 1;break;}
152         argv++, argc--;
153     }
154     if (err || argc != 1) 
155         Quit("usage: rx_ctest [-silent] [-rxlog] [-eventlog] [-nc NCALLS] [-np NPACKETS] hostname");
156     hostname = *argv++, argc--;
157
158     if (rxlog || eventlog) {
159         if (logstdout) debugFile = stdout;
160         else debugFile = fopen("rx_ctest.db", "w");
161         if (debugFile == NULL) Quit("Couldn't open rx_ctest.db");
162         if (rxlog) rx_debugFile = debugFile;
163         if (eventlog) rxevent_debugFile = debugFile;
164     }
165
166     signal(SIGINT, intSignal);/*Changed to sigquit since dbx is broken right now */
167 #ifndef AFS_NT40_ENV
168     signal(SIGQUIT, quitSignal);
169 #endif
170
171 #ifdef AFS_NT40_ENV
172     if (afs_winsockInit()<0) {
173         printf("Can't initialize winsock.\n");
174         exit(1);
175     }
176 #endif
177
178     hostent = gethostbyname(hostname);
179     if (!hostent) Abort("host %s not found", hostname);
180     if (hostent->h_length != 4)
181         Abort("host address is disagreeable length (%d)", hostent->h_length);
182     memcpy((char *)&host, hostent->h_addr, sizeof(host));
183     if (setFD>0)
184         OpenFD(setFD);
185     if (rx_Init(0) != 0) {
186         printf("RX failed to initialize, exiting.\n");
187         exit(2);
188     }
189     if (setFD>0) {
190         printf("rx_socket=%d\n", rx_socket);
191     }
192
193     printf("Using %d packet buffers\n", rx_nPackets);
194
195     conn = rx_NewConnection(host, htons(2500), 3, rxnull_NewClientSecurityObject(), 0);
196
197     if (!conn) Abort("unable to make a new connection");
198     
199     /* Set initial parameters.  This is (currently) not the approved interface */
200     if (burst) conn->peer->burstSize = conn->peer->burst = burst;
201     if (!clock_IsZero(&burstTime)) conn->peer->burstWait = burstTime;
202     if (!clock_IsZero(&retryTime)) conn->peer->timeout = retryTime;
203
204     if (sendFile) SendFile(sendFile, conn);
205     else {
206         buffer = (char *) osi_Alloc(bufferSize);
207         while (nCalls--) {
208             struct clock startTime;
209             struct timeval t;
210             int nbytes;
211             int nSent;
212             int bytesSent = 0;
213             int bytesRead = 0;
214             call = rx_NewCall(conn);
215             if (!call) Abort("unable to make a new call");
216
217             clock_GetTime(&startTime);
218             for (bytesSent = 0; bytesSent < nBytes; bytesSent += nSent) {
219                 int tryCount;
220                 tryCount = (bufferSize > nBytes - bytesSent)? nBytes - bytesSent: bufferSize;
221                 nSent = rx_Write(call, buffer, tryCount);
222                 if (nSent == 0) break;
223
224             }
225             for (bytesRead = 0; nbytes = rx_Read(call, buffer, bufferSize); bytesRead += nbytes) {};
226             if (print) printf("Received %d characters in response\n", bytesRead);
227             err = rx_EndCall(call, 0);
228             if (err) printf("Error %d returned from rpc call\n", err);
229             else {
230                 struct clock totalTime;
231                 float elapsedTime;
232                 clock_GetTime(&totalTime);
233                 clock_Sub(&totalTime, &startTime);
234                 elapsedTime = clock_Float(&totalTime);
235                 fprintf(stderr, "Sent %d bytes in %0.3f seconds:  %0.0f bytes per second\n",
236                         bytesSent, elapsedTime, bytesSent/elapsedTime);
237             }
238             if (!clock_IsZero(&computeTime)) {
239                 t.tv_sec = computeTime.sec;
240                 t.tv_usec = computeTime.usec;
241                 if (select(0, 0, 0, 0, &t) != 0) Quit("Select didn't return 0");
242             }
243             if (!clock_IsZero(&waitTime)) {
244                 struct timeval t;
245                 t.tv_sec = waitTime.sec;
246                 t.tv_usec = waitTime.usec;
247 #ifdef AFS_PTHREAD_ENV
248                 select(0,0,0,0, &t);
249 #else
250                 IOMGR_Sleep(t.tv_sec);
251 #endif
252             }
253         }
254         if (debugFile) rx_PrintPeerStats(debugFile, rx_PeerOf(conn));
255         rx_PrintPeerStats(stdout, rx_PeerOf(conn));
256     }
257     Quit("testclient: done!\n");
258 }
259
260 SendFile(file, conn)
261 char *file;
262 struct rx_connection *conn;
263 {
264     struct rx_call *call;
265     int fd;
266     struct stat status;
267     int blockSize, bytesLeft;
268     char *buf;
269     int nbytes;
270     int err;
271     struct clock startTime;
272     int receivedStore = 0;
273     struct clock totalReadvDelay;
274     int nReadvs;
275     int code;
276 #ifdef  AFS_AIX_ENV
277 #include <sys/statfs.h>
278     struct statfs tstatfs;
279 #endif
280
281     if (timeReadvs) {
282         nReadvs = 0;
283         clock_Zero(&totalReadvDelay);
284     }
285     fd = open(file, O_RDONLY, 0);
286     if (fd < 0) Abort("Couldn't open %s\n", file);
287     fstat(fd, &status);
288 #ifdef AFS_NT40_ENV
289     blockSize = 1024;
290 #else
291 #ifdef  AFS_AIX_ENV
292 /* Unfortunately in AIX valuable fields such as st_blksize are gone from the stat structure!! */
293     fstatfs(fd, &tstatfs);
294     blockSize = tstatfs.f_bsize;
295 #else
296     blockSize = status.st_blksize;
297 #endif
298 #endif
299     buf = (char *) osi_Alloc(blockSize);
300     bytesLeft = status.st_size;
301     clock_GetTime(&startTime);
302     call = rx_NewCall(conn);
303     while (bytesLeft) {
304         if (!receivedStore && rx_GetRemoteStatus(call) == 79) {
305             receivedStore = 1;
306             fprintf(stderr, "Remote status indicates file accepted (\"received store\")\n");
307         }
308         nbytes = (bytesLeft > blockSize? blockSize: bytesLeft);
309         errno = 0;
310         code = read(fd, buf, nbytes);
311         if (code != nbytes) {
312             Abort("Only read %d bytes of %d, errno=%d\n", code, nbytes, errno);
313         }
314         code = rx_Write(call, buf, nbytes);
315         if (code != nbytes) {
316             Abort("Only wrote %d bytes of %d\n", code, nbytes);
317         }
318         bytesLeft -= nbytes;
319     }
320     while ((nbytes = rx_Read(call, buf, sizeof(buf))) > 0) {
321         char *p = buf;
322         while (nbytes--) {putchar(*p); *p++;}
323     }
324     if ((err = rx_EndCall(call, 0)) != 0) {
325         fprintf(stderr, "rx_Endcall returned error %d\n", err);
326     } else {
327         struct clock totalTime;
328         float elapsedTime;
329         clock_GetTime(&totalTime);
330         clock_Sub(&totalTime, &startTime);
331         elapsedTime = totalTime.sec + totalTime.usec/1e6;
332         fprintf(stderr, "Sent %d bytes in %0.3f seconds:  %0.0f bytes per second\n",
333                 status.st_size, elapsedTime, status.st_size/elapsedTime);
334         if (timeReadvs) {
335             float delay = clock_Float(&totalReadvDelay) / nReadvs;
336             fprintf(stderr, "%d readvs, average delay of %0.4f seconds\n", nReadvs, delay);
337         }
338     }
339     close(fd);
340 }
341     
342 Abort(msg,a,b,c,d,e) {
343     printf((char *) msg, a, b, c, d, e);
344     printf("\n");
345     if (debugFile) {
346         rx_PrintStats(debugFile);
347         fflush(debugFile);
348     }
349     afs_abort();
350     exit(1);
351 }
352
353 Quit(msg, a,b,c,d,e) {
354     printf((char *) msg, a,b,c,d,e);
355     printf("\n");
356     if (debugFile) {
357         rx_PrintStats(debugFile);
358         fflush(debugFile);
359     }
360     rx_PrintStats(stdout);
361     exit(0);
362 }
363
364 /* OpenFD
365  *
366  * Open file descriptors until file descriptor n or higher is returned.
367  */
368 #include <sys/stat.h>
369 void OpenFD(n)
370 int n;
371 {
372     int i;
373     struct stat sbuf;
374     int fd, lfd;
375
376     lfd = -1;
377     for (i=0; i<n; i++) {
378         if (fstat(i, &sbuf) == 0)
379             continue;
380         if ((fd = open("/dev/null", 0, 0)) < 0) {
381             if (lfd >=0) {
382                 close(lfd);
383                 return;
384             }
385         }
386         else {
387             if (fd >= n) {
388                 close(fd);
389                 return;
390             }
391             else {
392                 lfd = fd;
393             }
394         }
395     }
396 }