e80b652df112611e253007567826c942ec6afcd9
[openafs.git] / src / libadmin / test / 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 /*
11  * This file implements the client related funtions for afscp
12  */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17 RCSID
18     ("$Header$");
19
20 #include "client.h"
21 #include <afs/cellconfig.h>
22 #include <afs/bosint.h>
23 #include <rx/rxstat.h>
24 #include <afs/afsint.h>
25 #define FSINT_COMMON_XG
26 #include <afs/afscbint.h>
27 #include <afs/kauth.h>
28 #include <afs/kautils.h>
29 #include <afs/ptint.h>
30 #include <afs/ptserver.h>
31 #include <afs/vldbint.h>
32 #include <afs/volint.h>
33 #include <afs/volser.h>
34 #include <ubik.h>
35 #include <ubik_int.h>
36 #ifdef AFS_NT40_ENV
37 #include <winsock2.h>
38 #include <pthread.h>
39 #endif
40
41 /*
42  * This structure stores the client and server function lists.
43  * This is kept separate from the actual interface definitions
44  * since an rpc interface can be offered by several servers
45  * (e.g. ubik and rxstat)
46  *
47  * The purpose of these functions is to allow a mapping from interfaceId
48  * to text representations of server process names and function names.
49  */
50
51 typedef struct {
52     const char **functionList;
53     size_t functionListLen;
54 } interface_function_list_t, *interface_function_list_p;
55
56 #ifdef AFS_NT40_ENV
57
58 /*
59  * On NT, you cannot define an array of character pointers in a dll
60  * and then access this array outside the dll via a global initialization
61  * because the msvc compiler will complain that the initializer is not
62  * a constant (i.e. C2099: initializer is not a constant).  This is because
63  * the dllimport and dllexport c language extensions cause references
64  * to the character array to go through another level of indirection -
65  * and this indirection is unknown at compilation time.
66  *
67  * To get around this problem I hand initialize this array on NT only
68  */
69
70 static interface_function_list_t afs_server;
71 static interface_function_list_t afscb_server;
72 static interface_function_list_t bos_server;
73 static interface_function_list_t kauth_kaa_server;
74 static interface_function_list_t kauth_kam_server;
75 static interface_function_list_t kauth_kat_server;
76 static interface_function_list_t pts_server;
77 static interface_function_list_t rxstat_server;
78 static interface_function_list_t ubik_disk_server;
79 static interface_function_list_t ubik_vote_server;
80 static interface_function_list_t vl_server;
81 static interface_function_list_t vol_server;
82 static pthread_once_t pthread_func_list_once = PTHREAD_ONCE_INIT;
83 static int pthread_func_list_done;
84
85 static void
86 cr_list(void)
87 {
88     afs_server.functionList = RXAFS_function_names;
89     afs_server.functionListLen = RXAFS_NO_OF_STAT_FUNCS;
90     afscb_server.functionList = RXAFSCB_function_names;
91     afscb_server.functionListLen = RXAFSCB_NO_OF_STAT_FUNCS;
92     bos_server.functionList = BOZO_function_names;
93     bos_server.functionListLen = BOZO_NO_OF_STAT_FUNCS;
94     kauth_kaa_server.functionList = KAA_function_names;
95     kauth_kaa_server.functionListLen = KAA_NO_OF_STAT_FUNCS;
96     kauth_kam_server.functionList = KAM_function_names;
97     kauth_kam_server.functionListLen = KAM_NO_OF_STAT_FUNCS;
98     kauth_kat_server.functionList = KAT_function_names;
99     kauth_kat_server.functionListLen = KAT_NO_OF_STAT_FUNCS;
100     pts_server.functionList = PR_function_names;
101     pts_server.functionListLen = PR_NO_OF_STAT_FUNCS;
102     rxstat_server.functionList = RXSTATS_function_names;
103     rxstat_server.functionListLen = RXSTATS_NO_OF_STAT_FUNCS;
104     ubik_disk_server.functionList = DISK_function_names;
105     ubik_disk_server.functionListLen = DISK_NO_OF_STAT_FUNCS;
106     ubik_vote_server.functionList = VOTE_function_names;
107     ubik_vote_server.functionListLen = VOTE_NO_OF_STAT_FUNCS;
108     vl_server.functionList = VL_function_names;
109     vl_server.functionListLen = VL_NO_OF_STAT_FUNCS;
110     vol_server.functionList = AFSVolfunction_names;
111     vol_server.functionListLen = AFSVolNO_OF_STAT_FUNCS;
112     pthread_func_list_done = 1;
113 }
114
115 #else
116
117 static interface_function_list_t afs_server = {
118     RXAFS_function_names,
119     RXAFS_NO_OF_STAT_FUNCS
120 };
121
122 static interface_function_list_t afscb_server = {
123     RXAFSCB_function_names,
124     RXAFSCB_NO_OF_STAT_FUNCS
125 };
126
127 static interface_function_list_t bos_server = {
128     BOZO_function_names,
129     BOZO_NO_OF_STAT_FUNCS
130 };
131
132 static interface_function_list_t kauth_kaa_server = {
133     KAA_function_names,
134     KAA_NO_OF_STAT_FUNCS
135 };
136
137 static interface_function_list_t kauth_kam_server = {
138     KAM_function_names,
139     KAM_NO_OF_STAT_FUNCS
140 };
141
142 static interface_function_list_t kauth_kat_server = {
143     KAT_function_names,
144     KAT_NO_OF_STAT_FUNCS
145 };
146
147 static interface_function_list_t pts_server = {
148     PR_function_names,
149     PR_NO_OF_STAT_FUNCS
150 };
151
152 static interface_function_list_t rxstat_server = {
153     RXSTATS_function_names,
154     RXSTATS_NO_OF_STAT_FUNCS
155 };
156
157 static interface_function_list_t ubik_disk_server = {
158     DISK_function_names,
159     DISK_NO_OF_STAT_FUNCS,
160 };
161
162 static interface_function_list_t ubik_vote_server = {
163     VOTE_function_names,
164     VOTE_NO_OF_STAT_FUNCS,
165 };
166
167 static interface_function_list_t vl_server = {
168     VL_function_names,
169     VL_NO_OF_STAT_FUNCS
170 };
171
172 static interface_function_list_t vol_server = {
173     AFSVolfunction_names,
174     AFSVolNO_OF_STAT_FUNCS
175 };
176
177 #endif /* AFS_NT40_ENV */
178
179 static interface_function_list_t unknown_server = {
180     0,
181     0
182 };
183
184 typedef struct {
185     afs_uint32 interfaceId;
186     const char *interfaceName;
187     interface_function_list_p functionList;
188 } interface_t, *interface_p;
189
190 interface_t int_list[] = {
191     {RXAFS_STATINDEX,
192      "file server",
193      &afs_server},
194
195     {RXSTATS_STATINDEX,
196      "rx stats",
197      &rxstat_server},
198
199     {RXAFSCB_STATINDEX,
200      "cache manager",
201      &afscb_server},
202
203     {PR_STATINDEX,
204      "pts server",
205      &pts_server},
206
207     {DISK_STATINDEX,
208      "ubik disk server",
209      &ubik_disk_server},
210
211     {VOTE_STATINDEX,
212      "ubik vote server",
213      &ubik_vote_server},
214
215     {VL_STATINDEX,
216      "vldb server",
217      &vl_server},
218
219     {AFSVolSTATINDEX,
220      "vol server",
221      &vol_server},
222
223     {BOZO_STATINDEX,
224      "bos server",
225      &bos_server},
226
227     {KAA_STATINDEX,
228      "kas kaa server",
229      &kauth_kaa_server},
230
231     {KAM_STATINDEX,
232      "kas kam server",
233      &kauth_kam_server},
234
235     {KAT_STATINDEX,
236      "kas kat server",
237      &kauth_kat_server},
238
239     /*
240      * Note the code below assumes that the following entry is the last entry
241      * in this array
242      */
243
244     {0, "unknown", &unknown_server}
245 };
246
247 /*
248  * Utility functions
249  */
250
251 int
252 DoClientLocalCellGet(struct cmd_syndesc *as, char *arock)
253 {
254     afs_status_t st = 0;
255     char cellName[MAXCELLCHARS];
256
257     if (!afsclient_LocalCellGet(cellName, &st)) {
258         ERR_ST_EXT("afsclient_LocalCellGet", st);
259     }
260
261     printf("This machine belongs to cell: %s\n", cellName);
262
263     return 0;
264 }
265
266 int
267 DoClientMountPointCreate(struct cmd_syndesc *as, char *arock)
268 {
269     typedef enum { DIRECTORY, VOLUME, READWRITE,
270         CHECK
271     } DoClientMountPointCreate_parm_t;
272     afs_status_t st = 0;
273     const char *directory;
274     const char *volume;
275     vol_type_t vol_type = READ_ONLY;
276     vol_check_t vol_check = DONT_CHECK_VOLUME;
277
278     if (as->parms[DIRECTORY].items) {
279         directory = as->parms[DIRECTORY].items->data;
280     }
281
282     if (as->parms[VOLUME].items) {
283         volume = as->parms[VOLUME].items->data;
284     }
285
286     if (as->parms[READWRITE].items) {
287         vol_type = READ_WRITE;
288     }
289
290     if (as->parms[CHECK].items) {
291         vol_check = CHECK_VOLUME;
292     }
293
294     if (!afsclient_MountPointCreate
295         (cellHandle, directory, volume, vol_type, vol_check, &st)) {
296         ERR_ST_EXT("afsclient_MountPointCreate", st);
297     }
298
299     return 0;
300 }
301
302 static void
303 Print_afs_serverEntry_p(afs_serverEntry_p serv, const char *prefix)
304 {
305     int i = 0;
306
307     printf("%sInformation for server %s\n", prefix, serv->serverName);
308     if (serv->serverType & DATABASE_SERVER) {
309         printf("%s\tIt is a database server\n", prefix);
310     }
311     if (serv->serverType & FILE_SERVER) {
312         printf("%s\tIt is a file server\n", prefix);
313     }
314     printf("%s\tServer addresses:%s\n", prefix, serv->serverName);
315     while (serv->serverAddress[i] != 0) {
316         printf("\t\t%s%x\n", prefix, serv->serverAddress[i++]);
317     }
318 }
319
320 int
321 DoClientAFSServerGet(struct cmd_syndesc *as, char *arock)
322 {
323     typedef enum { SERVER } DoClientAFSServerGet_parm_t;
324     afs_status_t st = 0;
325     const char *server;
326     afs_serverEntry_t entry;
327
328     if (as->parms[SERVER].items) {
329         server = as->parms[SERVER].items->data;
330     }
331
332     if (!afsclient_AFSServerGet(cellHandle, server, &entry, &st)) {
333         ERR_ST_EXT("afsclient_AFSServerGet", st);
334     }
335
336     Print_afs_serverEntry_p(&entry, "");
337
338     return 0;
339 }
340
341 int
342 DoClientAFSServerList(struct cmd_syndesc *as, char *arock)
343 {
344     afs_status_t st = 0;
345     afs_serverEntry_t entry;
346     void *iter = NULL;
347
348     if (!afsclient_AFSServerGetBegin(cellHandle, &iter, &st)) {
349         ERR_ST_EXT("afsclient_AFSServerGetBegin", st);
350     }
351
352     while (afsclient_AFSServerGetNext(iter, &entry, &st)) {
353         Print_afs_serverEntry_p(&entry, "");
354     }
355
356     if (st != ADMITERATORDONE) {
357         ERR_ST_EXT("afsclient_AFSServerGetNext", st);
358     }
359
360     if (!afsclient_AFSServerGetDone(iter, &st)) {
361         ERR_ST_EXT("afsclient_AFSServerGetDone", st);
362     }
363
364
365     return 0;
366 }
367
368 static void
369 Print_afs_RPCStatsState_p(afs_RPCStatsState_p state, const char *prefix)
370 {
371     printf("%sThe rpc stats state is: ", prefix);
372     switch (*state) {
373     case AFS_RPC_STATS_DISABLED:
374         printf("disabled\n");
375         break;
376     case AFS_RPC_STATS_ENABLED:
377         printf("enabled\n");
378         break;
379     }
380 }
381
382 typedef struct {
383     const char *tag;
384     afs_stat_source_t value;
385 } afs_type_map_t, *afs_type_map_p;
386
387 static afs_type_map_t map[] = {
388     {"bosserver", AFS_BOSSERVER},
389     {"fileserver", AFS_FILESERVER},
390     {"kaserver", AFS_KASERVER},
391     {"ptserver", AFS_PTSERVER},
392     {"volserver", AFS_VOLSERVER},
393     {"vlserver", AFS_VLSERVER},
394     {"client", AFS_CLIENT},
395     {0, 0}
396 };
397
398 static int
399 GetStatPortFromString(const char *type, int *port)
400 {
401     char *end;
402     long tport;
403
404     errno = 0;
405     tport = strtol(type, &end, 0);
406     if (tport == 0 || end == type || *end != '\0') {
407         return 0;
408     }
409
410     *port = (int)tport;
411     return 1;
412 }
413
414 static int
415 GetStatSourceFromString(const char *type, afs_stat_source_t * src, int *port)
416 {
417     int i;
418     size_t type_len = strlen(type);
419
420     for (i = 0; (map[i].tag) && strncasecmp(type, map[i].tag, type_len); i++);
421
422     if (map[i].tag == 0) {
423         /*
424          * Try to convert string to port number
425          */
426         if (GetStatPortFromString(type, port)) {
427             return 0;
428         }
429
430         fprintf(stderr,
431                 "couldn't convert server to type, try one of the "
432                 "following:\n");
433         for (i = 0; map[i].tag; i++) {
434             fprintf(stderr, "%s ", map[i].tag);
435         }
436
437         ERR_EXT("");
438     } else {
439         *src = map[i].value;
440         return 1;
441     }
442 }
443
444 typedef enum {
445     AFS_PEER_STATS,
446     AFS_PROCESS_STATS
447 } afs_stat_type_t, *afs_stat_type_p;
448
449 static afs_stat_type_t
450 GetStatTypeFromString(const char *type)
451 {
452     afs_stat_type_t rc;
453
454     if (!strcmp(type, "peer")) {
455         rc = AFS_PEER_STATS;
456     } else if (!strcmp(type, "process")) {
457         rc = AFS_PROCESS_STATS;
458     } else {
459         ERR_EXT("stat_type must be process or peer");
460     }
461
462     return rc;
463 }
464
465 int
466 DoClientRPCStatsStateGet(struct cmd_syndesc *as, char *arock)
467 {
468     typedef enum { SERVER, PROCESS,
469         STAT_TYPE
470     } DoClientRPCStatsStateGet_parm_t;
471     afs_status_t st = 0;
472     struct rx_connection *conn;
473     int servAddr = 0;
474     afs_stat_source_t type;
475     int srvrPort;
476     int typeIsValid;
477     afs_stat_type_t which;
478     afs_RPCStatsState_t state;
479
480     if (as->parms[PROCESS].items) {
481         typeIsValid =
482             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
483                                     &srvrPort);
484     }
485
486     if (as->parms[STAT_TYPE].items) {
487         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
488     }
489
490     if (as->parms[SERVER].items) {
491         if (typeIsValid) {
492             if (!afsclient_RPCStatOpen
493                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
494                  &st)) {
495                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
496             }
497         } else {
498             if (!afsclient_RPCStatOpenPort
499                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
500                  &st)) {
501                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
502             }
503         }
504     }
505
506     if (which == AFS_PEER_STATS) {
507         if (!util_RPCStatsStateGet
508             (conn, RXSTATS_QueryPeerRPCStats, &state, &st)) {
509             ERR_ST_EXT("util_RPCStatsStateGet", st);
510         }
511     } else {
512         if (!util_RPCStatsStateGet
513             (conn, RXSTATS_QueryProcessRPCStats, &state, &st)) {
514             ERR_ST_EXT("util_RPCStatsStateGet", st);
515         }
516     }
517
518     Print_afs_RPCStatsState_p(&state, "");
519
520     afsclient_RPCStatClose(conn, 0);
521
522     return 0;
523 }
524
525 int
526 DoClientRPCStatsStateEnable(struct cmd_syndesc *as, char *arock)
527 {
528     typedef enum { SERVER, PROCESS, STAT_TYPE } DoClientRPCStatsEnable_parm_t;
529     afs_status_t st = 0;
530     struct rx_connection *conn;
531     int servAddr = 0;
532     afs_stat_source_t type;
533     int srvrPort;
534     int typeIsValid;
535     afs_stat_type_t which;
536
537     if (as->parms[PROCESS].items) {
538         typeIsValid =
539             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
540                                     &srvrPort);
541     }
542
543     if (as->parms[STAT_TYPE].items) {
544         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
545     }
546
547     if (as->parms[SERVER].items) {
548         if (typeIsValid) {
549             if (!afsclient_RPCStatOpen
550                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
551                  &st)) {
552                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
553             }
554         } else {
555             if (!afsclient_RPCStatOpenPort
556                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
557                  &st)) {
558                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
559             }
560         }
561     }
562
563     if (which == AFS_PEER_STATS) {
564         if (!util_RPCStatsStateEnable(conn, RXSTATS_EnablePeerRPCStats, &st)) {
565             ERR_ST_EXT("util_RPCStatsStateEnable", st);
566         }
567     } else {
568         if (!util_RPCStatsStateEnable
569             (conn, RXSTATS_EnableProcessRPCStats, &st)) {
570             ERR_ST_EXT("util_RPCStatsStateEnable", st);
571         }
572     }
573
574     afsclient_RPCStatClose(conn, 0);
575
576     return 0;
577 }
578
579 int
580 DoClientRPCStatsStateDisable(struct cmd_syndesc *as, char *arock)
581 {
582     typedef enum { SERVER, PROCESS,
583         STAT_TYPE
584     } DoClientRPCStatsDisable_parm_t;
585     afs_status_t st = 0;
586     struct rx_connection *conn;
587     int servAddr = 0;
588     afs_stat_source_t type;
589     int srvrPort;
590     int typeIsValid;
591     afs_stat_type_t which;
592
593     if (as->parms[PROCESS].items) {
594         typeIsValid =
595             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
596                                     &srvrPort);
597     }
598
599     if (as->parms[STAT_TYPE].items) {
600         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
601     }
602
603     if (as->parms[SERVER].items) {
604         if (typeIsValid) {
605             if (!afsclient_RPCStatOpen
606                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
607                  &st)) {
608                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
609             }
610         } else {
611             if (!afsclient_RPCStatOpenPort
612                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
613                  &st)) {
614                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
615             }
616         }
617     }
618
619     if (which == AFS_PEER_STATS) {
620         if (!util_RPCStatsStateDisable
621             (conn, RXSTATS_DisablePeerRPCStats, &st)) {
622             ERR_ST_EXT("util_RPCStatsStateDisable", st);
623         }
624     } else {
625         if (!util_RPCStatsStateDisable
626             (conn, RXSTATS_DisableProcessRPCStats, &st)) {
627             ERR_ST_EXT("util_RPCStatsStateDisable", st);
628         }
629     }
630
631     afsclient_RPCStatClose(conn, 0);
632
633     return 0;
634 }
635
636 static void
637 Print_afs_RPCStats_p(afs_RPCStats_p stat, interface_function_list_p f_list,
638                      const char *prefix)
639 {
640     afs_int32 index = stat->s.stats_v1.func_index;
641
642     if (index > ((afs_int32) f_list->functionListLen - 1)) {
643         printf("%sUnknown function ", prefix);
644     } else {
645         printf("%s%s ", prefix,
646                f_list->functionList[stat->s.stats_v1.func_index]);
647     }
648
649     if (!hiszero(stat->s.stats_v1.invocations)) {
650         printf("%sinvoc (%u.%u) bytes_sent (%u.%u) bytes_rcvd (%u.%u)\n",
651                prefix, hgethi(stat->s.stats_v1.invocations),
652                hgetlo(stat->s.stats_v1.invocations),
653                hgethi(stat->s.stats_v1.bytes_sent),
654                hgetlo(stat->s.stats_v1.bytes_sent),
655                hgethi(stat->s.stats_v1.bytes_rcvd),
656                hgetlo(stat->s.stats_v1.bytes_rcvd)
657             );
658         printf("\tqsum %d.%06d\tqsqr %d.%06d"
659                "\tqmin %d.%06d\tqmax %d.%06d\n",
660                stat->s.stats_v1.queue_time_sum.sec,
661                stat->s.stats_v1.queue_time_sum.usec,
662                stat->s.stats_v1.queue_time_sum_sqr.sec,
663                stat->s.stats_v1.queue_time_sum_sqr.usec,
664                stat->s.stats_v1.queue_time_min.sec,
665                stat->s.stats_v1.queue_time_min.usec,
666                stat->s.stats_v1.queue_time_max.sec,
667                stat->s.stats_v1.queue_time_max.usec);
668         printf("\txsum %d.%06d\txsqr %d.%06d"
669                "\txmin %d.%06d\txmax %d.%06d\n",
670                stat->s.stats_v1.execution_time_sum.sec,
671                stat->s.stats_v1.execution_time_sum.usec,
672                stat->s.stats_v1.execution_time_sum_sqr.sec,
673                stat->s.stats_v1.execution_time_sum_sqr.usec,
674                stat->s.stats_v1.execution_time_min.sec,
675                stat->s.stats_v1.execution_time_min.usec,
676                stat->s.stats_v1.execution_time_max.sec,
677                stat->s.stats_v1.execution_time_max.usec);
678     } else {
679         printf("never invoked\n");
680     }
681 }
682
683 int
684 DoClientRPCStatsList(struct cmd_syndesc *as, char *arock)
685 {
686     typedef enum { SERVER, PROCESS, STAT_TYPE } DoClientRPCStatsList_parm_t;
687     afs_status_t st = 0;
688     struct rx_connection *conn;
689     int servAddr = 0;
690     afs_stat_source_t type;
691     int srvrPort;
692     int typeIsValid;
693     afs_stat_type_t which;
694     afs_RPCStats_t stats;
695     void *iter;
696     int i;
697
698 #ifdef AFS_NT40_ENV
699     (pthread_func_list_done
700      || pthread_once(&pthread_func_list_once, cr_list));
701 #endif
702
703     if (as->parms[PROCESS].items) {
704         typeIsValid =
705             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
706                                     &srvrPort);
707     }
708
709     if (as->parms[STAT_TYPE].items) {
710         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
711     }
712
713     if (as->parms[SERVER].items) {
714         if (typeIsValid) {
715             if (!afsclient_RPCStatOpen
716                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
717                  &st)) {
718                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
719             }
720         } else {
721             if (!afsclient_RPCStatOpenPort
722                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
723                  &st)) {
724                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
725             }
726         }
727     }
728
729     if (which == AFS_PEER_STATS) {
730         if (!util_RPCStatsGetBegin
731             (conn, RXSTATS_RetrievePeerRPCStats, &iter, &st)) {
732             ERR_ST_EXT("util_RPCStatsGetBegin", st);
733         }
734     } else {
735         if (!util_RPCStatsGetBegin
736             (conn, RXSTATS_RetrieveProcessRPCStats, &iter, &st)) {
737             ERR_ST_EXT("util_RPCStatsGetBegin", st);
738         }
739     }
740
741     printf("Listing rpc stats at server %s process %s:\n",
742            as->parms[SERVER].items->data, as->parms[PROCESS].items->data);
743
744     while (util_RPCStatsGetNext(iter, &stats, &st)) {
745
746         /*
747          * Print a new heading for each stat collection
748          */
749
750         if (stats.s.stats_v1.func_index == 0) {
751
752             printf("\n\n");
753
754             /*
755              * Look up the interface in our list
756              */
757
758             for (i = 0; i < ((sizeof(int_list) - 1) / sizeof(interface_t));
759                  i++) {
760                 if (stats.s.stats_v1.interfaceId == int_list[i].interfaceId) {
761                     break;
762                 }
763             }
764
765             /*
766              * Print out a meaningful header for each stat collection
767              */
768
769             if (which == AFS_PEER_STATS) {
770                 struct in_addr ina;
771                 ina.s_addr = htonl(stats.s.stats_v1.remote_peer);
772
773                 printf("%s stats for remote peer located at %s port %u "
774                        "%s %s as a %s via the %s interface\n",
775                        as->parms[PROCESS].items->data, inet_ntoa(ina),
776                        stats.s.stats_v1.remote_port,
777                        ((stats.s.stats_v1.
778                          remote_is_server) ? "accessed by" : "accessing"),
779                        as->parms[PROCESS].items->data,
780                        ((stats.s.stats_v1.
781                          remote_is_server) ? "client" : "server"),
782                        int_list[i].interfaceName);
783             } else {
784                 printf("%s stats for the %s interface " "accessed as a %s\n",
785                        as->parms[PROCESS].items->data,
786                        int_list[i].interfaceName,
787                        ((stats.s.stats_v1.
788                          remote_is_server) ? "client" : "server")
789                     );
790             }
791         }
792         Print_afs_RPCStats_p(&stats, int_list[i].functionList, "    ");
793     }
794
795     if (st != ADMITERATORDONE) {
796         ERR_ST_EXT("util_RPCStatsGetNext", st);
797     }
798
799     if (!util_RPCStatsGetDone(iter, &st)) {
800         ERR_ST_EXT("util_RPCStatsGetDone", st);
801     }
802
803     afsclient_RPCStatClose(conn, 0);
804
805     return 0;
806 }
807
808 int
809 DoClientRPCStatsClear(struct cmd_syndesc *as, char *arock)
810 {
811     typedef enum { SERVER, PROCESS, STAT_TYPE, CLEAR_ALL, CLEAR_INVOCATIONS,
812         CLEAR_BYTES_SENT, CLEAR_BYTES_RCVD,
813         CLEAR_QUEUE_TIME_SUM, CLEAR_QUEUE_TIME_SQUARE,
814         CLEAR_QUEUE_TIME_MIN, CLEAR_QUEUE_TIME_MAX,
815         CLEAR_EXEC_TIME_SUM, CLEAR_EXEC_TIME_SQUARE,
816         CLEAR_EXEC_TIME_MIN, CLEAR_EXEC_TIME_MAX
817     } DoClientRPCStatsClear_parm_t;
818     afs_status_t st = 0;
819     struct rx_connection *conn;
820     int servAddr = 0;
821     afs_stat_source_t type;
822     int srvrPort;
823     int typeIsValid;
824     afs_stat_type_t which;
825     afs_RPCStatsClearFlag_t flag = 0;
826     int seen_all = 0;
827     int seen_any = 0;
828
829     if (as->parms[PROCESS].items) {
830         typeIsValid =
831             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
832                                     &srvrPort);
833     }
834
835     if (as->parms[STAT_TYPE].items) {
836         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
837     }
838
839     if (as->parms[SERVER].items) {
840         if (typeIsValid) {
841             if (!afsclient_RPCStatOpen
842                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
843                  &st)) {
844                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
845             }
846         } else {
847             if (!afsclient_RPCStatOpenPort
848                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
849                  &st)) {
850                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
851             }
852         }
853     }
854
855     if (as->parms[CLEAR_ALL].items) {
856         seen_all = 1;
857         seen_any = 1;
858         flag = AFS_RX_STATS_CLEAR_ALL;
859     }
860
861     if (as->parms[CLEAR_INVOCATIONS].items) {
862         if (seen_all) {
863             ERR_EXT("cannot specify additional flags when "
864                     "specifying clear_all");
865         }
866         seen_any = 1;
867         flag |= AFS_RX_STATS_CLEAR_INVOCATIONS;
868     }
869
870     if (as->parms[CLEAR_BYTES_SENT].items) {
871         if (seen_all) {
872             ERR_EXT("cannot specify additional flags when "
873                     "specifying clear_all");
874         }
875         seen_any = 1;
876         flag |= AFS_RX_STATS_CLEAR_BYTES_SENT;
877     }
878
879     if (as->parms[CLEAR_BYTES_RCVD].items) {
880         if (seen_all) {
881             ERR_EXT("cannot specify additional flags when "
882                     "specifying clear_all");
883         }
884         seen_any = 1;
885         flag |= AFS_RX_STATS_CLEAR_BYTES_RCVD;
886     }
887
888     if (as->parms[CLEAR_QUEUE_TIME_SUM].items) {
889         if (seen_all) {
890             ERR_EXT("cannot specify additional flags when "
891                     "specifying clear_all");
892         }
893         seen_any = 1;
894         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_SUM;
895     }
896
897     if (as->parms[CLEAR_QUEUE_TIME_SQUARE].items) {
898         if (seen_all) {
899             ERR_EXT("cannot specify additional flags when "
900                     "specifying clear_all");
901         }
902         seen_any = 1;
903         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_SQUARE;
904     }
905
906     if (as->parms[CLEAR_QUEUE_TIME_MIN].items) {
907         if (seen_all) {
908             ERR_EXT("cannot specify additional flags when "
909                     "specifying clear_all");
910         }
911         seen_any = 1;
912         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_MIN;
913     }
914
915     if (as->parms[CLEAR_QUEUE_TIME_MAX].items) {
916         if (seen_all) {
917             ERR_EXT("cannot specify additional flags when "
918                     "specifying clear_all");
919         }
920         seen_any = 1;
921         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_MAX;
922     }
923
924     if (as->parms[CLEAR_EXEC_TIME_SUM].items) {
925         if (seen_all) {
926             ERR_EXT("cannot specify additional flags when "
927                     "specifying clear_all");
928         }
929         seen_any = 1;
930         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_SUM;
931     }
932
933     if (as->parms[CLEAR_EXEC_TIME_SQUARE].items) {
934         if (seen_all) {
935             ERR_EXT("cannot specify additional flags when "
936                     "specifying clear_all");
937         }
938         seen_any = 1;
939         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_SQUARE;
940     }
941
942     if (as->parms[CLEAR_EXEC_TIME_MIN].items) {
943         if (seen_all) {
944             ERR_EXT("cannot specify additional flags when "
945                     "specifying clear_all");
946         }
947         seen_any = 1;
948         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_MIN;
949     }
950
951     if (as->parms[CLEAR_EXEC_TIME_MAX].items) {
952         if (seen_all) {
953             ERR_EXT("cannot specify additional flags when "
954                     "specifying clear_all");
955         }
956         seen_any = 1;
957         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_MAX;
958     }
959
960     if (!seen_any) {
961         ERR_EXT("you must specify something to clear");
962     }
963
964     if (which == AFS_PEER_STATS) {
965         if (!util_RPCStatsClear(conn, RXSTATS_ClearPeerRPCStats, flag, &st)) {
966             ERR_ST_EXT("util_RPCStatsClear", st);
967         }
968     } else {
969         if (!util_RPCStatsClear
970             (conn, RXSTATS_ClearProcessRPCStats, flag, &st)) {
971             ERR_ST_EXT("util_RPCStatsClear", st);
972         }
973     }
974
975     afsclient_RPCStatClose(conn, 0);
976
977     return 0;
978 }
979
980 int
981 DoClientRPCStatsVersionGet(struct cmd_syndesc *as, char *arock)
982 {
983     typedef enum { SERVER, PROCESS } DoClientRPCStatsVersionGet_parm_t;
984     afs_status_t st = 0;
985     struct rx_connection *conn;
986     afs_stat_source_t type;
987     int servAddr = 0;
988     int srvrPort;
989     int typeIsValid;
990     afs_RPCStatsVersion_t version;
991
992     if (as->parms[PROCESS].items) {
993         typeIsValid =
994             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
995                                     &srvrPort);
996     }
997
998     if (as->parms[SERVER].items) {
999         if (typeIsValid) {
1000             if (!afsclient_RPCStatOpen
1001                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
1002                  &st)) {
1003                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
1004             }
1005         } else {
1006             if (!afsclient_RPCStatOpenPort
1007                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1008                  &st)) {
1009                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
1010             }
1011         }
1012     }
1013
1014     if (!util_RPCStatsVersionGet(conn, &version, &st)) {
1015         ERR_ST_EXT("util_RPCStatsVersionGet", st);
1016     }
1017
1018     printf("the rpc stat version number is %u\n", version);
1019
1020     afsclient_RPCStatClose(conn, 0);
1021
1022     return 0;
1023 }
1024
1025 static void
1026 Print_afs_CMServerPref_p(afs_CMServerPref_p pref)
1027 {
1028     afs_uint32 taddr;
1029
1030     taddr = pref->ipAddr;
1031     printf("%d.%d.%d.%d\t\t\t%d\n", (taddr >> 24) & 0xff,
1032            (taddr >> 16) & 0xff, (taddr >> 8) & 0xff, taddr & 0xff,
1033            pref->ipRank);
1034 }
1035
1036 int
1037 DoClientCMGetServerPrefs(struct cmd_syndesc *as, char *arock)
1038 {
1039     afs_status_t st = 0;
1040     typedef enum { SERVER, PORT } DoClientCMGetServerPrefs_parm_t;
1041     struct rx_connection *conn;
1042     int servAddr = 0;
1043     int srvrPort = AFSCONF_CALLBACKPORT;
1044     afs_CMServerPref_t prefs;
1045     void *iter;
1046
1047 #ifdef AFS_NT40_ENV
1048     (pthread_func_list_done
1049      || pthread_once(&pthread_func_list_once, cr_list));
1050 #endif
1051
1052     if (as->parms[PORT].items) {
1053         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1054             ERR_EXT("Couldn't undertand port number");
1055         }
1056     }
1057
1058     if (as->parms[SERVER].items) {
1059         if (!afsclient_CMStatOpenPort
1060             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1061              &st)) {
1062             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1063         }
1064     }
1065
1066     if (!util_CMGetServerPrefsBegin(conn, &iter, &st)) {
1067         ERR_ST_EXT("util_CMGetServerPrefsBegin", st);
1068     }
1069
1070     printf("Listing CellServDB for %s at port %s:\n",
1071            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1072
1073     while (util_CMGetServerPrefsNext(iter, &prefs, &st)) {
1074
1075         Print_afs_CMServerPref_p(&prefs);
1076     }
1077
1078     if (st != ADMITERATORDONE) {
1079         ERR_ST_EXT("util_CMGetServerPrefsNext", st);
1080     }
1081
1082     if (!util_CMGetServerPrefsDone(iter, &st)) {
1083         ERR_ST_EXT("util_CMGetServerPrefsDone", st);
1084     }
1085
1086     afsclient_CMStatClose(conn, 0);
1087
1088     return 0;
1089 }
1090
1091 static void
1092 Print_afs_CMListCell_p(afs_CMListCell_p cellInfo)
1093 {
1094     int i;
1095     afs_uint32 taddr;
1096
1097     printf("Cell %s on hosts", cellInfo->cellname);
1098     for (i = 0; i < UTIL_MAX_CELL_HOSTS && cellInfo->serverAddr[i]; i++) {
1099         taddr = cellInfo->serverAddr[i];
1100         printf(" %d.%d.%d.%d", (taddr >> 24) & 0xff, (taddr >> 16) & 0xff,
1101                (taddr >> 8) & 0xff, taddr & 0xff);
1102     }
1103     printf("\n");
1104 }
1105
1106 int
1107 DoClientCMListCells(struct cmd_syndesc *as, char *arock)
1108 {
1109     afs_status_t st = 0;
1110     typedef enum { SERVER, PORT } DoClientCMListCells_parm_t;
1111     struct rx_connection *conn;
1112     int servAddr = 0;
1113     int srvrPort = AFSCONF_CALLBACKPORT;
1114     afs_CMListCell_t cellInfo;
1115     void *iter;
1116
1117 #ifdef AFS_NT40_ENV
1118     (pthread_func_list_done
1119      || pthread_once(&pthread_func_list_once, cr_list));
1120 #endif
1121
1122     if (as->parms[PORT].items) {
1123         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1124             ERR_EXT("Couldn't undertand port number");
1125         }
1126     }
1127
1128     if (as->parms[SERVER].items) {
1129         if (!afsclient_CMStatOpenPort
1130             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1131              &st)) {
1132             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1133         }
1134     }
1135
1136     if (!util_CMListCellsBegin(conn, &iter, &st)) {
1137         ERR_ST_EXT("util_CMListCellsBegin", st);
1138     }
1139
1140     printf("Listing CellServDB for %s at port %s:\n",
1141            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1142
1143     while (util_CMListCellsNext(iter, &cellInfo, &st)) {
1144
1145         Print_afs_CMListCell_p(&cellInfo);
1146     }
1147
1148     if (st != ADMITERATORDONE) {
1149         ERR_ST_EXT("util_CMListCellsNext", st);
1150     }
1151
1152     if (!util_CMListCellsDone(iter, &st)) {
1153         ERR_ST_EXT("util_CMListCellsDone", st);
1154     }
1155
1156     afsclient_CMStatClose(conn, 0);
1157
1158     return 0;
1159 }
1160
1161 int
1162 DoClientCMLocalCell(struct cmd_syndesc *as, char *arock)
1163 {
1164     afs_status_t st = 0;
1165     typedef enum { SERVER, PORT } DoClientCMLocalCell_parm_t;
1166     struct rx_connection *conn;
1167     int servAddr = 0;
1168     int srvrPort = AFSCONF_CALLBACKPORT;
1169     afs_CMCellName_t cellname;
1170
1171 #ifdef AFS_NT40_ENV
1172     (pthread_func_list_done
1173      || pthread_once(&pthread_func_list_once, cr_list));
1174 #endif
1175
1176     if (as->parms[PORT].items) {
1177         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1178             ERR_EXT("Couldn't undertand port number");
1179         }
1180     }
1181
1182     if (as->parms[SERVER].items) {
1183         if (!afsclient_CMStatOpenPort
1184             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1185              &st)) {
1186             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1187         }
1188     }
1189
1190     if (!util_CMLocalCell(conn, cellname, &st)) {
1191         ERR_ST_EXT("util_CMLocalCell", st);
1192     }
1193
1194     printf("Client %s (port %s) is in cell %s\n",
1195            as->parms[SERVER].items->data, as->parms[PORT].items->data,
1196            cellname);
1197
1198     afsclient_CMStatClose(conn, 0);
1199
1200     return 0;
1201 }
1202
1203 static void
1204 Print_afs_ClientConfig_p(afs_ClientConfig_p config)
1205 {
1206     printf("    clientVersion:  %d\n", config->clientVersion);
1207     printf("    serverVersion:  %d\n", config->serverVersion);
1208     printf("    nChunkFiles:    %d\n", config->c.config_v1.nChunkFiles);
1209     printf("    nStatCaches:    %d\n", config->c.config_v1.nStatCaches);
1210     printf("    nDataCaches:    %d\n", config->c.config_v1.nDataCaches);
1211     printf("    nVolumeCaches:  %d\n", config->c.config_v1.nVolumeCaches);
1212     printf("    firstChunkSize: %d\n", config->c.config_v1.firstChunkSize);
1213     printf("    otherChunkSize: %d\n", config->c.config_v1.otherChunkSize);
1214     printf("    cacheSize:      %d\n", config->c.config_v1.cacheSize);
1215     printf("    setTime:        %d\n", config->c.config_v1.setTime);
1216     printf("    memCache:       %d\n", config->c.config_v1.memCache);
1217
1218 }
1219
1220 int
1221 DoClientCMClientConfig(struct cmd_syndesc *as, char *arock)
1222 {
1223     afs_status_t st = 0;
1224     typedef enum { SERVER, PORT } DoClientCMLocalCell_parm_t;
1225     struct rx_connection *conn;
1226     int servAddr = 0;
1227     int srvrPort = AFSCONF_CALLBACKPORT;
1228     afs_ClientConfig_t config;
1229
1230 #ifdef AFS_NT40_ENV
1231     (pthread_func_list_done
1232      || pthread_once(&pthread_func_list_once, cr_list));
1233 #endif
1234
1235     if (as->parms[PORT].items) {
1236         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1237             ERR_EXT("Couldn't undertand port number");
1238         }
1239     }
1240
1241     if (as->parms[SERVER].items) {
1242         if (!afsclient_CMStatOpenPort
1243             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1244              &st)) {
1245             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1246         }
1247     }
1248
1249     if (!util_CMClientConfig(conn, &config, &st)) {
1250         ERR_ST_EXT("util_CMClientConfig", st);
1251     }
1252
1253     printf("Cache configuration for client %s (port %s):\n\n",
1254            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1255
1256     Print_afs_ClientConfig_p(&config);
1257
1258     printf("\n");
1259
1260     afsclient_CMStatClose(conn, 0);
1261
1262     return 0;
1263 }
1264
1265 void
1266 SetupClientAdminCmd(void)
1267 {
1268     struct cmd_syndesc *ts;
1269
1270     ts = cmd_CreateSyntax("ClientLocalCellGet", DoClientLocalCellGet, 0,
1271                           "get the name of this machine's cell");
1272     SetupCommonCmdArgs(ts);
1273
1274     ts = cmd_CreateSyntax("ClientMountPointCreate", DoClientMountPointCreate,
1275                           0, "create a mount point");
1276     cmd_AddParm(ts, "-directory", CMD_SINGLE, CMD_REQUIRED,
1277                 "directory where mount point will be created");
1278     cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_REQUIRED,
1279                 "the name of the volume to mount");
1280     cmd_AddParm(ts, "-readwrite", CMD_FLAG, CMD_OPTIONAL,
1281                 "mount a read write volume");
1282     cmd_AddParm(ts, "-check", CMD_FLAG, CMD_OPTIONAL,
1283                 "check that the volume exists before mounting");
1284     SetupCommonCmdArgs(ts);
1285
1286     ts = cmd_CreateSyntax("ClientAFSServerGet", DoClientAFSServerGet, 0,
1287                           "retrieve information about an afs server");
1288     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "server to query");
1289     SetupCommonCmdArgs(ts);
1290
1291     ts = cmd_CreateSyntax("ClientAFSServerList", DoClientAFSServerList, 0,
1292                           "retrieve information about all afs "
1293                           "servers in a cell");
1294     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1295                 "server where command will execute");
1296     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1297                 "process to query <bosserver fileserver ptserver "
1298                 "kaserver client vlserver volserver>");
1299     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1300                 "stats to retrieve <peer or process>");
1301     SetupCommonCmdArgs(ts);
1302
1303     ts = cmd_CreateSyntax("ClientRPCStatsStateGet", DoClientRPCStatsStateGet,
1304                           0, "retrieve the rpc stat collection state");
1305     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1306                 "server where command will execute");
1307     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1308                 "process to query <bosserver fileserver ptserver "
1309                 "kaserver client vlserver volserver>");
1310     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1311                 "stats to retrieve <peer or process>");
1312     SetupCommonCmdArgs(ts);
1313
1314     ts = cmd_CreateSyntax("ClientRPCStatsStateEnable",
1315                           DoClientRPCStatsStateEnable, 0,
1316                           "set the rpc stat collection state to on");
1317     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1318                 "server where command will execute");
1319     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1320                 "process to query <bosserver fileserver ptserver "
1321                 "kaserver client vlserver volserver>");
1322     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1323                 "stats to retrieve <peer or process>");
1324     SetupCommonCmdArgs(ts);
1325
1326     ts = cmd_CreateSyntax("ClientRPCStatsStateDisable",
1327                           DoClientRPCStatsStateDisable, 0,
1328                           "set the rpc stat collection state to off");
1329     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1330                 "server where command will execute");
1331     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1332                 "process to query <bosserver fileserver ptserver "
1333                 "kaserver client vlserver volserver>");
1334     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1335                 "stats to retrieve <peer or process>");
1336     SetupCommonCmdArgs(ts);
1337
1338     ts = cmd_CreateSyntax("ClientRPCStatsList", DoClientRPCStatsList, 0,
1339                           "list the rpc stats");
1340     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1341                 "server where command will execute");
1342     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1343                 "process to query <bosserver fileserver ptserver "
1344                 "kaserver client vlserver volserver>");
1345     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1346                 "stats to retrieve <peer or process>");
1347     SetupCommonCmdArgs(ts);
1348
1349     ts = cmd_CreateSyntax("ClientRPCStatsClear", DoClientRPCStatsClear, 0,
1350                           "reset rpc stat counters");
1351     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1352                 "server where command will execute");
1353     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1354                 "process to query <bosserver fileserver ptserver "
1355                 "kaserver client vlserver volserver>");
1356     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1357                 "stats to retrieve <peer or process>");
1358     cmd_AddParm(ts, "-clear_all", CMD_FLAG, CMD_OPTIONAL,
1359                 "clear all existing counters");
1360     cmd_AddParm(ts, "-clear_invocations", CMD_FLAG, CMD_OPTIONAL,
1361                 "clear invocation count");
1362     cmd_AddParm(ts, "-clear_bytes_sent", CMD_FLAG, CMD_OPTIONAL,
1363                 "clear bytes_sent count");
1364     cmd_AddParm(ts, "-clear_bytes_rcvd", CMD_FLAG, CMD_OPTIONAL,
1365                 "clear bytes_rcvd count");
1366     cmd_AddParm(ts, "-clear_queue_time_sum", CMD_FLAG, CMD_OPTIONAL,
1367                 "clear queue time sum");
1368     cmd_AddParm(ts, "-clear_queue_time_square", CMD_FLAG, CMD_OPTIONAL,
1369                 "clear queue time square");
1370     cmd_AddParm(ts, "-clear_queue_time_min", CMD_FLAG, CMD_OPTIONAL,
1371                 "clear queue time min");
1372     cmd_AddParm(ts, "-clear_queue_time_max", CMD_FLAG, CMD_OPTIONAL,
1373                 "clear queue time max");
1374     cmd_AddParm(ts, "-clear_exec_time_sum", CMD_FLAG, CMD_OPTIONAL,
1375                 "clear exec time sum");
1376     cmd_AddParm(ts, "-clear_exec_time_square", CMD_FLAG, CMD_OPTIONAL,
1377                 "clear exec time square");
1378     cmd_AddParm(ts, "-clear_exec_time_min", CMD_FLAG, CMD_OPTIONAL,
1379                 "clear exec time min");
1380     cmd_AddParm(ts, "-clear_exec_time_max", CMD_FLAG, CMD_OPTIONAL,
1381                 "clear exec time max");
1382     SetupCommonCmdArgs(ts);
1383
1384     ts = cmd_CreateSyntax("ClientRPCStatsVersionGet",
1385                           DoClientRPCStatsVersionGet, 0,
1386                           "list the server's rpc stats version");
1387     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1388                 "server where command will execute");
1389     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1390                 "process to query <bosserver fileserver ptserver "
1391                 "kaserver client vlserver volserver>");
1392     SetupCommonCmdArgs(ts);
1393
1394     ts = cmd_CreateSyntax("ClientCMGetServerPrefs", DoClientCMGetServerPrefs,
1395                           0, "list a client's server preferences ");
1396     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1397                 "server where command will execute");
1398     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1399     SetupCommonCmdArgs(ts);
1400
1401     ts = cmd_CreateSyntax("ClientCMListCells", DoClientCMListCells, 0,
1402                           "list a client's CellServDB ");
1403     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1404                 "server where command will execute");
1405     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1406     SetupCommonCmdArgs(ts);
1407
1408     ts = cmd_CreateSyntax("ClientCMLocalCell", DoClientCMLocalCell, 0,
1409                           "get the name of the client's local cell");
1410     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1411                 "server where command will execute");
1412     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1413     SetupCommonCmdArgs(ts);
1414
1415     ts = cmd_CreateSyntax("ClientCMClientConfig", DoClientCMClientConfig, 0,
1416                           "get the client's cache configuration");
1417     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1418                 "server where command will execute");
1419     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1420     SetupCommonCmdArgs(ts);
1421 }