2 * Copyright 2000, International Business Machines Corporation and others.
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
10 #include <afsconfig.h>
11 #include <afs/param.h>
17 #include <rx/rxstat.h>
20 # include <afs/krb5_nt.h>
23 #include <afs/afs_Admin.h>
24 #include <afs/pthread_glock.h>
25 #include <afs/cellconfig.h>
26 #include <afs/dirpath.h>
27 #include <afs/com_err.h>
28 #include <afs/kautils.h>
30 #include <afs/vlserver.h>
31 #include <afs/pterror.h>
32 #include <afs/bnode.h>
33 #include <afs/volser.h>
34 #include <afs/afscbint.h>
36 #include "afs_AdminInternal.h"
37 #include "afs_utilAdmin.h"
40 * AIX 4.2 has PTHREAD_CREATE_UNDETACHED and not PTHREAD_CREATE_JOINABLE
42 * This fix should be done more centrally, but there's no time right now.
44 #if defined(AFS_AIX_ENV)
45 # if !defined(PTHREAD_CREATE_JOINABLE) && defined(PTHREAD_CREATE_UNDETACHED)
46 # define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
50 #define ERRCODE_RANGE 8
51 static pthread_once_t error_init_once = PTHREAD_ONCE_INIT;
52 static int error_init_done;
58 initialize_KA_error_table();
59 initialize_RXK_error_table();
60 initialize_KTC_error_table();
61 initialize_ACFG_error_table();
62 initialize_CMD_error_table();
63 initialize_VL_error_table();
64 initialize_PT_error_table();
65 initialize_BZ_error_table();
66 initialize_U_error_table();
67 initialize_AB_error_table();
68 initialize_AF_error_table();
69 initialize_AL_error_table();
70 initialize_AC_error_table();
71 initialize_AK_error_table();
72 initialize_AM_error_table();
73 initialize_AP_error_table();
74 initialize_AU_error_table();
75 initialize_AV_error_table();
76 initialize_VOLS_error_table();
77 #ifdef AFS_KRB5_ERROR_ENV
84 * (*errorTextP) will not be freed by the caller.
87 util_AdminErrorCodeTranslate(afs_status_t errorCode, int langId,
88 const char **errorTextP, afs_status_p st)
94 if (errorTextP == NULL) {
95 tst = ADMUTILERRORTEXTPNULL;
96 goto fail_util_AdminErrorCodeTranslate;
100 * Translate the error
103 if (!error_init_done)
104 pthread_once(&error_init_once, init_once);
105 code = (afs_int32) errorCode;
106 *errorTextP = afs_error_message(code);
107 #ifdef AFS_KRB5_ERROR_ENV
108 if (strncmp(*errorTextP, "unknown", strlen("unknown")) == 0) {
109 const char *msg = fetch_krb5_error_message(code);
116 fail_util_AdminErrorCodeTranslate:
125 * The iterator functions and data for the database server retrieval functions.
128 typedef struct database_server_get {
131 struct afsconf_dir *conf;
132 struct afsconf_cell cell;
133 util_databaseServerEntry_t server[CACHED_ITEMS];
134 } database_server_get_t, *database_server_get_p;
137 GetDatabaseServerRPC(void *rpc_specific, int slot, int *last_item,
138 int *last_item_contains_data, afs_status_p st)
141 afs_status_t tst = 0;
142 database_server_get_p serv = (database_server_get_p) rpc_specific;
144 serv->server[slot].serverAddress =
145 ntohl(serv->cell.hostAddr[serv->index].sin_addr.s_addr);
146 strcpy(serv->server[slot].serverName, serv->cell.hostName[serv->index]);
150 * See if we've processed all the entries
153 if (serv->index == serv->total) {
155 *last_item_contains_data = 1;
166 GetDatabaseServerFromCache(void *rpc_specific, int slot, void *dest,
170 afs_status_t tst = 0;
171 database_server_get_p serv = (database_server_get_p) rpc_specific;
173 memcpy(dest, (const void *)&serv->server[slot],
174 sizeof(util_databaseServerEntry_t));
184 DestroyDatabaseServer(void *rpc_specific, afs_status_p st)
187 afs_status_t tst = 0;
188 database_server_get_p serv = (database_server_get_p) rpc_specific;
190 afsconf_Close(serv->conf);
200 * util_DatabaseServerGetBegin - begin iterating over the database
201 * server machines in a cell.
205 * IN cellName - the cell where database servers reside.
207 * OUT iterationIdP - upon successful completion contains an iterator that
208 * can be passed to util_DatabaseServerGetNext.
212 * No locks are obtained or released by this function
220 * Returns != 0 upon successful completion.
224 util_DatabaseServerGetBegin(const char *cellName, void **iterationIdP,
228 afs_status_t tst = 0;
229 afs_admin_iterator_p iter =
230 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
231 database_server_get_p serv =
232 (database_server_get_p) calloc(1, sizeof(database_server_get_t));
233 char copyCell[MAXCELLCHARS];
239 if ((cellName == NULL) || (*cellName == 0)) {
240 tst = ADMUTILCELLNAMENULL;
241 goto fail_util_DatabaseServerGetBegin;
244 if (iterationIdP == NULL) {
245 goto fail_util_DatabaseServerGetBegin;
248 if ((iter == NULL) || (serv == NULL)) {
250 goto fail_util_DatabaseServerGetBegin;
254 * Fill in the serv structure
257 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
258 if (serv->conf == NULL) {
259 tst = ADMUTILCANTOPENCELLSERVDB;
260 goto fail_util_DatabaseServerGetBegin;
264 * We must copy the cellname because afsconf_GetCellInfo
265 * actually writes over the cell name it is passed.
267 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
269 afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
272 goto fail_util_DatabaseServerGetBegin;
275 serv->total = serv->cell.numServers;
277 (iter, (void *)serv, GetDatabaseServerRPC, GetDatabaseServerFromCache,
278 NULL, DestroyDatabaseServer, &tst)) {
279 *iterationIdP = (void *)iter;
281 goto fail_util_DatabaseServerGetBegin;
285 fail_util_DatabaseServerGetBegin:
303 * util_DatabaseServerGetNext - get the next server address.
307 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
309 * OUT serverAddressP - upon successful completion contains the next
310 * server address in the cell.
314 * This function locks the iterator for the duration of its processing.
322 * Returns != 0 upon successful completion.
327 util_DatabaseServerGetNext(const void *iterationId,
328 util_databaseServerEntry_p serverP,
332 afs_status_t tst = 0;
333 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
336 tst = ADMITERATORNULL;
337 goto fail_util_DatabaseServerGetNext;
340 if (serverP == NULL) {
341 tst = ADMUTILSERVERADDRESSPNULL;
342 goto fail_util_DatabaseServerGetNext;
345 rc = IteratorNext(iter, (void *)serverP, &tst);
347 fail_util_DatabaseServerGetNext:
356 * util_DatabaseServerGetDone - stop using a database iterator.
360 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
364 * This function locks the iterator for the duration of its processing.
365 * And then destroys it before returning.
373 * Returns != 0 upon successful completion.
377 util_DatabaseServerGetDone(const void *iterationId, afs_status_p st)
380 afs_status_t tst = 0;
381 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
384 * Validate parameters
388 tst = ADMITERATORNULL;
389 goto fail_util_DatabaseServerGetDone;
392 rc = IteratorDone(iter, &tst);
394 fail_util_DatabaseServerGetDone:
403 * GetServerAddressFromName - translate a character string server name
404 * to an integer representation of an IP address.
408 * IN serverName - the character string server name in either foo.com
409 * format, or 123.12.1.1 format.
411 * OUT serverAddress - an integer that is filled with the correct address
412 * in host byte order upon successful completion.
416 * No locks are obtained or released by this function
420 * On many platforms, gethostbyname is not thread safe. Since we are
421 * only working under NT for now I'll use it directly. In future UNIX
422 * ports, a wrapper function should be written to call the correct function
423 * on the particular platform.
427 * Returns != 0 upon successful completion.
431 util_AdminServerAddressGetFromName(const char *serverName, int *serverAddress,
435 afs_status_t tst = 0;
436 struct hostent *server;
437 int part1, part2, part3, part4;
440 if ((serverName == NULL) || (*serverName == 0)) {
441 tst = ADMUTILSERVERNAMENULL;
442 goto fail_util_AdminServerAddressGetFromName;
445 if (serverAddress == NULL) {
446 tst = ADMUTILSERVERADDRESSNULL;
447 goto fail_util_AdminServerAddressGetFromName;
451 sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
452 if (num_converted == 4) {
453 *serverAddress = (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
456 server = gethostbyname(serverName);
457 if (server != NULL) {
458 memcpy((void *)serverAddress, (const void *)server->h_addr,
460 *serverAddress = ntohl(*serverAddress);
462 tst = ADMUTILCANTGETSERVERNAME;
464 goto fail_util_AdminServerAddressGetFromName;
470 fail_util_AdminServerAddressGetFromName:
480 * This file contains functions that can be used to create iterator
481 * functions within the api. I have attempted to make these functions
482 * generic so that they can be used across the admin components.
484 * The functions in this file are a generalized producer/consumer
485 * implementation. They manage access to a queue of data. The only
486 * assumption these functions make about this data is that it is
487 * stored in a queue which is implemented via an array. These functions
488 * know about the index into the array, but they know nothing about
489 * the contents of the array.
491 * The data specific functions you implement will have to create some
492 * data specific storage structure that will have an array
493 * of size CACHED_ITEMS data items. This structure will also need to
494 * store any necessary parameters/state variables you need to issue the
495 * rpc to retrieve the next item.
497 * In order to use the generic functions, you must implement four functions
498 * for each type of data you wish to retrieve. The functions are:
500 * validate_specific_data_func - this function is handed a void pointer
501 * that points to the rpc specific data you've allocated. The function
502 * should examine the data for validity and return an appropriate error.
503 * This function is called every time the iterator is validated.
505 * destroy_specific_data_func - this function is handed a void pointer
506 * that points to the rpc specific data you've allocated. It should
507 * destroy any components of the specific data as required and then
508 * return. The void pointer is free'd by the generic functions.
510 * get_cached_data_func - this function is handed a void pointer
511 * that points to the rpc specific data you've allocated, an index
512 * into the cache of the item to be copied to the caller, and a void
513 * pointer where the cache item should be copied.
515 * make_rpc_func - this function is handed a void pointer that points
516 * to the rpc specific data you've allocated, an index into the cache
517 * of the item to be filled with the next retrieved item, and an int
518 * pointer that should be set to 1 if there are no more items to be
519 * retrieved. The assumption made by the generic functions is that
520 * the last_item status requires an individual rpc - the data isn't
521 * piggybacked on the last data item.
525 * IteratorDelete - delete an iterator.
529 * IN interator - the iterator to delete.
533 * No locks are held by this function.
537 * Returns != 0 upon successful completion.
541 IteratorDelete(afs_admin_iterator_p iter, afs_status_p st)
544 afs_status_t tst = 0;
546 if (pthread_mutex_destroy(&iter->mutex)) {
547 tst = ADMMUTEXDESTROY;
548 goto fail_IteratorDelete;
550 if (pthread_cond_destroy(&iter->add_item)) {
551 tst = ADMCONDDESTROY;
552 goto fail_IteratorDelete;
554 if (pthread_cond_destroy(&iter->remove_item)) {
555 tst = ADMCONDDESTROY;
556 goto fail_IteratorDelete;
559 if (iter->destroy_specific != NULL) {
560 iter->destroy_specific(iter->rpc_specific, &tst);
562 free(iter->rpc_specific);
575 * DataGet - the background thread that is spawned for every
576 * IteratorBegin call that is successful. This thread tries
577 * to fetch the data from the server ahead of the
578 * IteratorNext calls.
582 * IN arg - the address of the iterator structure to be used for this
587 * The iterator mutex is used by this function to protect elements
588 * of the iterator structure.
592 * Returns != 0 upon successful completion.
598 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
600 afs_status_t tst = 0;
601 int mutex_locked = 0;
603 int last_item_contains_data = 0;
605 if (pthread_mutex_lock(&iter->mutex)) {
606 iter->st = ADMMUTEXLOCK;
615 * Check to see if there's room for this datum. If not, wait
616 * on the consumer to free up another slot.
619 while (iter->cache_slots_used == CACHED_ITEMS) {
620 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
621 iter->st = ADMCONDWAIT;
627 * Check to see if someone called Done and terminated the request.
628 * We could have gone to sleep above when the buffer was full and
629 * instead of being awoken because another slot is open, we were
630 * awoken because the request was terminated.
633 if (iter->request_terminated) {
637 if (pthread_mutex_unlock(&iter->mutex)) {
638 iter->st = ADMMUTEXUNLOCK;
645 * Make an rpc without holding the iter mutex
646 * We reference an item in the principal cache here without
647 * holding the mutex. This is safe because:
648 * 1. The iter structure is ref counted and won't be deleted
649 * from underneath us.
650 * 2. cache_queue_tail is always one item ahead of the consumer
651 * thread so we are the only thread accessing this member.
654 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail, &last_item,
655 &last_item_contains_data, &tst);
657 if (pthread_mutex_lock(&iter->mutex)) {
658 iter->st = ADMMUTEXLOCK;
665 * Check to see if someone called Done and terminated the request
668 if (iter->request_terminated) {
673 * Check the rc of the rpc, and see if there are no more items
683 * Check to see if this is the last item produced by the rpc.
684 * If it isn't, add the item to the cache and proceed.
685 * If it is, check to see if the last item contains valid data.
686 * If it contains valid data, we need to add it to our cache.
687 * If it doesn't, we mark the iterator as complete.
690 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
691 iter->cache_queue_tail =
692 (iter->cache_queue_tail + 1) % CACHED_ITEMS;
693 iter->cache_slots_used++;
696 iter->st = ADMITERATORDONE;
697 iter->done_iterating = 1;
699 * There's a small chance that the consumer emptied the
700 * cache queue while we were making the last rpc and has
701 * since gone to sleep waiting for more data. In this case
702 * there will never be more data so we signal him here.
704 pthread_cond_signal(&iter->add_item);
710 * If the cache was empty and we just added another item, signal
714 if (iter->cache_slots_used == 1) {
715 if (pthread_cond_signal(&iter->add_item)) {
716 iter->st = ADMCONDSIGNAL;
726 * If we are exiting with an error, signal the consumer in the event
727 * they were waiting for us to produce more data
731 pthread_cond_signal(&iter->add_item);
735 pthread_mutex_unlock(&iter->mutex);
742 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
746 * IN interator - the interator to be verified.
750 * We assume the iter->mutex lock is already held.
754 * Returns != 0 upon successful completion.
758 IsValidIterator(const afs_admin_iterator_p iterator, afs_status_p st)
761 afs_status_t tst = 0;
764 * Validate input parameters
767 if (iterator == NULL) {
768 tst = ADMITERATORNULL;
769 goto fail_IsValidIterator;
772 if ((iterator->begin_magic != BEGIN_MAGIC)
773 || (iterator->end_magic != END_MAGIC)) {
774 tst = ADMITERATORBADMAGICNULL;
775 goto fail_IsValidIterator;
778 if (iterator->is_valid == 0) {
779 tst = ADMITERATORINVALID;
780 goto fail_IsValidIterator;
784 * Call the iterator specific validation function
787 if (iterator->validate_specific != NULL) {
788 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
789 goto fail_IsValidIterator;
794 fail_IsValidIterator:
803 * IteratorNext - return the next datum in an interator.
807 * IN interator - the iterator containing the data.
809 * IN dest - the address where the data should be copied.
813 * Lock the iterator upon entry, and hold it during the duration of this
818 * Returns != 0 upon successful completion.
822 IteratorNext(afs_admin_iterator_p iter, void *dest, afs_status_p st)
825 afs_status_t tst = 0;
829 * We have to lock the iterator before we validate it
832 if (pthread_mutex_lock(&iter->mutex)) {
834 goto fail_IteratorNext;
839 if (!IsValidIterator(iter, &tst)) {
840 goto fail_IteratorNext;
843 if (iter->request_terminated == 1) {
844 tst = ADMITERATORTERMINATED;
845 goto fail_IteratorNext;
848 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
850 goto fail_IteratorNext;
854 * Check to see if there are any queue'd items. If not, wait here
855 * until signalled by the producer.
858 while (iter->cache_slots_used == 0) {
861 * Maybe the producer experienced an rpc failure.
864 if ((!iter->done_iterating) && (iter->st != 0)) {
866 goto fail_IteratorNext;
870 * Maybe there are no queue'd items because the producer is done
873 if (iter->done_iterating) {
875 goto fail_IteratorNext;
878 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
880 goto fail_IteratorNext;
885 * Copy the next cached item and update the cached item count
886 * and the index into the cache array
890 get_cached_data(iter->rpc_specific, iter->cache_queue_head, dest,
892 goto fail_IteratorNext;
895 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
896 iter->cache_slots_used--;
899 * If the cache was full before we removed the item above, the
900 * producer may have been waiting for us to remove an item.
901 * Signal the producer letting him know that we've opened a slot
905 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
906 if (pthread_cond_signal(&iter->remove_item)) {
908 goto fail_IteratorNext;
916 if (locked_iter == 1) {
917 pthread_mutex_unlock(&iter->mutex);
927 * IteratorDone - mark the iterator done.
931 * IN interator - the iterator to mark done.
935 * Lock the iterator upon entry, and hold it during the duration of this
940 * Returns != 0 upon successful completion.
944 IteratorDone(afs_admin_iterator_p iter, afs_status_p st)
947 afs_status_t tst = 0;
948 int mutex_locked = 1;
950 if (pthread_mutex_lock(&iter->mutex)) {
952 goto fail_IteratorDone;
958 if (!IsValidIterator(iter, &tst)) {
959 goto fail_IteratorDone;
964 * Depending upon the status of the background worker thread,
965 * we can either join with him immediately (if we know he has
966 * terminated), or we need to tell him the request has been
967 * terminated and then join with him.
970 if (!iter->done_iterating) {
971 iter->request_terminated = 1;
972 iter->cache_slots_used = 0;
973 pthread_cond_signal(&iter->remove_item);
977 * We have to unlock the mutex to allow the background thread to
981 if (pthread_mutex_unlock(&iter->mutex)) {
982 tst = ADMMUTEXUNLOCK;
983 goto fail_IteratorDone;
986 if (iter->make_rpc != NULL) {
987 if (pthread_join(iter->bg_worker, (void **)0)) {
989 goto fail_IteratorDone;
994 * We don't relock the mutex here since we are the only thread
995 * that has access to the iter now
998 rc = IteratorDelete(iter, &tst);
1004 pthread_mutex_unlock(&iter->mutex);
1014 * IteratorInit - initialize an iterator.
1018 * IN interator - the iterator to initialize.
1022 * No locks are held by this function.
1026 * Returns != 0 upon successful completion.
1030 IteratorInit(afs_admin_iterator_p iter, void *rpc_specific,
1031 make_rpc_func make_rpc, get_cached_data_func get_cached_data,
1032 validate_specific_data_func validate_specific_data,
1033 destroy_specific_data_func destroy_specific_data,
1037 afs_status_t tst = 0;
1038 int mutex_inited = 0;
1039 int add_item_cond_inited = 0;
1040 int remove_item_cond_inited = 0;
1043 tst = ADMITERATORNULL;
1044 goto fail_IteratorInit;
1047 if (rpc_specific == NULL) {
1048 tst = ADMITERATORRPCSPECIFICNULL;
1049 goto fail_IteratorInit;
1053 * Initialize the iterator structure
1055 iter->begin_magic = BEGIN_MAGIC;
1056 iter->end_magic = END_MAGIC;
1058 iter->cache_slots_used = 0;
1059 iter->done_iterating = 0;
1060 iter->request_terminated = 0;
1061 iter->st = AFS_STATUS_OK;
1062 iter->cache_queue_head = 0;
1063 iter->cache_queue_tail = 0;
1064 iter->cache_slots_used = 0;
1065 iter->rpc_specific = rpc_specific;
1066 iter->make_rpc = make_rpc;
1067 iter->get_cached_data = get_cached_data;
1068 iter->validate_specific = validate_specific_data;
1069 iter->destroy_specific = destroy_specific_data;
1071 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *)0)) {
1073 goto fail_IteratorInit;
1078 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *)0)) {
1080 goto fail_IteratorInit;
1082 add_item_cond_inited = 1;
1085 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *)0)) {
1087 goto fail_IteratorInit;
1089 remove_item_cond_inited = 1;
1093 * Create a worker thread that will begin to query the server
1094 * and cache responses.
1097 if (iter->make_rpc != NULL) {
1098 pthread_attr_t tattr;
1100 if (pthread_attr_init(&tattr)) {
1101 tst = ADMTHREADATTRINIT;
1102 goto fail_IteratorInit;
1105 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1106 tst = ADMTHREADATTRSETDETACHSTATE;
1107 goto fail_IteratorInit;
1110 if (pthread_create(&iter->bg_worker, &tattr, DataGet, (void *)iter)) {
1111 tst = ADMTHREADCREATE;
1112 goto fail_IteratorInit;
1121 pthread_mutex_destroy(&iter->mutex);
1123 if (remove_item_cond_inited) {
1124 pthread_cond_destroy(&iter->remove_item);
1126 if (add_item_cond_inited) {
1127 pthread_cond_destroy(&iter->add_item);
1138 CellHandleIsValid(const void *cellHandle, afs_status_p st)
1141 afs_status_t tst = 0;
1142 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1145 * Validate input parameters
1148 if (c_handle == NULL) {
1149 tst = ADMCLIENTCELLHANDLENULL;
1150 goto fail_CellHandleIsValid;
1153 if ((c_handle->begin_magic != BEGIN_MAGIC)
1154 || (c_handle->end_magic != END_MAGIC)) {
1155 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1156 goto fail_CellHandleIsValid;
1159 if (c_handle->is_valid == 0) {
1160 tst = ADMCLIENTCELLINVALID;
1161 goto fail_CellHandleIsValid;
1165 fail_CellHandleIsValid:
1174 * The iterator functions and data for the rpc statistic retrieval functions
1177 typedef struct rpc_stat_get {
1178 afs_uint32 clock_sec;
1179 afs_uint32 clock_usec;
1182 afs_uint32 clientVersion;
1183 afs_uint32 serverVersion;
1184 struct rpcStats stat_list;
1185 afs_RPCStats_t stats[CACHED_ITEMS];
1186 afs_uint32 *pointer;
1187 } rpc_stat_get_t, *rpc_stat_get_p;
1190 UnmarshallRPCStats(afs_uint32 serverVersion, afs_uint32 ** ptrP,
1194 unsigned int hi, lo;
1197 * Server must always match lower versions. We are version 1.
1200 s->stats_v1.remote_peer = *(ptr++);
1201 s->stats_v1.remote_port = *(ptr++);
1202 s->stats_v1.remote_is_server = *(ptr++);
1203 s->stats_v1.interfaceId = *(ptr++);
1204 s->stats_v1.func_total = *(ptr++);
1205 s->stats_v1.func_index = *(ptr++);
1208 s->stats_v1.invocations = ((afs_uint64) hi << 32) + lo;
1211 s->stats_v1.bytes_sent = ((afs_uint64) hi << 32) + lo;
1214 s->stats_v1.bytes_rcvd = ((afs_uint64) hi << 32) + lo;
1215 s->stats_v1.queue_time_sum.sec = *(ptr++);
1216 s->stats_v1.queue_time_sum.usec = *(ptr++);
1217 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1218 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1219 s->stats_v1.queue_time_min.sec = *(ptr++);
1220 s->stats_v1.queue_time_min.usec = *(ptr++);
1221 s->stats_v1.queue_time_max.sec = *(ptr++);
1222 s->stats_v1.queue_time_max.usec = *(ptr++);
1223 s->stats_v1.execution_time_sum.sec = *(ptr++);
1224 s->stats_v1.execution_time_sum.usec = *(ptr++);
1225 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1226 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1227 s->stats_v1.execution_time_min.sec = *(ptr++);
1228 s->stats_v1.execution_time_min.usec = *(ptr++);
1229 s->stats_v1.execution_time_max.sec = *(ptr++);
1230 s->stats_v1.execution_time_max.usec = *(ptr++);
1235 GetRPCStatsRPC(void *rpc_specific, int slot, int *last_item,
1236 int *last_item_contains_data, afs_status_p st)
1239 afs_status_t tst = 0;
1240 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1242 t->stats[slot].clientVersion = t->clientVersion;
1243 t->stats[slot].serverVersion = t->serverVersion;
1244 t->stats[slot].statCount = t->total;
1247 * If the server stat version is greater than or equal to my version
1248 * number, it is required to return the values in the client's current
1252 UnmarshallRPCStats(t->serverVersion, &t->pointer, &t->stats[slot].s);
1257 * See if we've processed all the entries
1260 if (t->index == t->total) {
1262 *last_item_contains_data = 1;
1273 GetRPCStatsFromCache(void *rpc_specific, int slot, void *dest,
1277 afs_status_t tst = 0;
1278 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1280 memcpy(dest, (const void *)&stat->stats[slot], sizeof(afs_RPCStats_t));
1290 DestroyRPCStats(void *rpc_specific, afs_status_p st)
1293 afs_status_t tst = 0;
1294 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1296 if (stat->stat_list.rpcStats_val != NULL) {
1297 free(stat->stat_list.rpcStats_val);
1308 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1312 * IN conn - an rx connection to the process to be queried
1314 * IN rpc - the function to call to make the actual rpc
1316 * OUT iterationIdP - an iteration id that can be passed to
1317 * util_RPCStatsGetNext to get the next rpc stat
1321 * No locks are obtained or released by this function
1325 * Returns != 0 upon successful completion.
1330 util_RPCStatsGetBegin(struct rx_connection *conn,
1331 int (*rpc) (struct rx_connection *,
1332 afs_uint32, afs_uint32 *,
1333 afs_uint32 *, afs_uint32 *,
1334 afs_uint32 *, struct rpcStats *),
1335 void **iterationIdP, afs_status_p st)
1338 afs_status_t tst = 0;
1339 afs_admin_iterator_p iter =
1340 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1341 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1344 tst = ADMRXCONNNULL;
1345 goto fail_util_RPCStatsGetBegin;
1349 tst = ADMRPCPTRNULL;
1350 goto fail_util_RPCStatsGetBegin;
1353 if (iterationIdP == NULL) {
1354 tst = ADMITERATIONIDPNULL;
1355 goto fail_util_RPCStatsGetBegin;
1358 if ((iter == NULL) || (stat == NULL)) {
1360 goto fail_util_RPCStatsGetBegin;
1363 stat->stat_list.rpcStats_len = 0;
1364 stat->stat_list.rpcStats_val = 0;
1366 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1369 (*rpc) (conn, stat->clientVersion, &stat->serverVersion,
1370 &stat->clock_sec, &stat->clock_usec, &stat->total,
1374 goto fail_util_RPCStatsGetBegin;
1378 * If there are no statistics, just mark the iterator done and
1382 if (stat->stat_list.rpcStats_len == 0) {
1383 stat->pointer = NULL;
1384 if (!IteratorInit(iter, (void *)stat, NULL, NULL, NULL, NULL, &tst)) {
1385 goto fail_util_RPCStatsGetBegin;
1387 iter->done_iterating = 1;
1388 iter->st = ADMITERATORDONE;
1390 stat->pointer = stat->stat_list.rpcStats_val;
1392 (iter, (void *)stat, GetRPCStatsRPC, GetRPCStatsFromCache, NULL,
1393 DestroyRPCStats, &tst)) {
1394 goto fail_util_RPCStatsGetBegin;
1397 *iterationIdP = (void *)iter;
1400 fail_util_RPCStatsGetBegin:
1418 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1422 * IN iterationId - an iterator previously returned by
1423 * util_RPCStatsGetBegin.
1425 * OUT stats - upon successful completion contains the next set of stats
1430 * No locks are obtained or released by this function
1434 * Returns != 0 upon successful completion.
1439 util_RPCStatsGetNext(const void *iterationId, afs_RPCStats_p stats,
1443 afs_status_t tst = 0;
1444 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1446 if (iterationId == NULL) {
1447 tst = ADMITERATIONIDPNULL;
1448 goto fail_util_RPCStatsGetNext;
1451 if (stats == NULL) {
1452 tst = ADMUTILRPCSTATSNULL;
1453 goto fail_util_RPCStatsGetNext;
1456 rc = IteratorNext(iter, (void *)stats, &tst);
1458 fail_util_RPCStatsGetNext:
1467 * util_RPCStatsGetDone - finish using a stats iterator
1471 * IN iterationId - an iterator previously returned by
1472 * util_RPCStatsGetBegin.
1476 * No locks are obtained or released by this function
1480 * Returns != 0 upon successful completion.
1485 util_RPCStatsGetDone(const void *iterationId, afs_status_p st)
1488 afs_status_t tst = 0;
1489 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1491 if (iterationId == NULL) {
1492 tst = ADMITERATIONIDPNULL;
1493 goto fail_util_RPCStatsGetDone;
1496 rc = IteratorDone(iter, &tst);
1498 fail_util_RPCStatsGetDone:
1507 * util_RPCStatsStateGet - get the current state of rpc stat collection
1511 * IN conn - an rx connection to the process to be queried
1513 * IN rpc - the function to call to make the actual rpc
1515 * OUT state - the rpc stat collection state.
1519 * No locks are obtained or released by this function
1523 * Returns != 0 upon successful completion.
1528 util_RPCStatsStateGet(struct rx_connection *conn,
1529 int (*rpc) (struct rx_connection *,
1530 afs_RPCStatsState_p),
1531 afs_RPCStatsState_p state, afs_status_p st)
1534 afs_status_t tst = 0;
1537 tst = ADMRXCONNNULL;
1538 goto fail_util_RPCStatsStateGet;
1542 tst = ADMRPCPTRNULL;
1543 goto fail_util_RPCStatsStateGet;
1546 if (state == NULL) {
1547 tst = ADMRPCSTATENULL;
1548 goto fail_util_RPCStatsStateGet;
1551 tst = (*rpc) (conn, state);
1557 fail_util_RPCStatsStateGet:
1566 * util_RPCStatsStateEnable - enable rpc stat collection
1571 * IN conn - an rx connection to the process to be modified
1573 * IN rpc - the function to call to make the actual rpc
1577 * No locks are obtained or released by this function
1581 * Returns != 0 upon successful completion.
1586 util_RPCStatsStateEnable(struct rx_connection *conn,
1587 int (*rpc) (struct rx_connection *),
1591 afs_status_t tst = 0;
1594 tst = ADMRXCONNNULL;
1595 goto fail_util_RPCStatsStateEnable;
1599 tst = ADMRPCPTRNULL;
1600 goto fail_util_RPCStatsStateEnable;
1603 tst = (*rpc) (conn);
1609 fail_util_RPCStatsStateEnable:
1618 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1623 * IN conn - an rx connection to the process to be modified
1625 * IN rpc - the function to call to make the actual rpc
1629 * No locks are obtained or released by this function
1633 * Returns != 0 upon successful completion.
1638 util_RPCStatsStateDisable(struct rx_connection *conn,
1639 int (*rpc) (struct rx_connection *),
1643 afs_status_t tst = 0;
1646 tst = ADMRXCONNNULL;
1647 goto fail_util_RPCStatsStateDisable;
1651 tst = ADMRPCPTRNULL;
1652 goto fail_util_RPCStatsStateDisable;
1655 tst = (*rpc) (conn);
1661 fail_util_RPCStatsStateDisable:
1670 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1671 * collection at a server
1675 * IN conn - an rx connection to the process to be modified
1677 * IN rpc - the function to call to make the actual rpc
1679 * IN flag - a flag containing the fields to be cleared
1684 * No locks are obtained or released by this function
1688 * Returns != 0 upon successful completion.
1693 util_RPCStatsClear(struct rx_connection *conn,
1694 int (*rpc) (struct rx_connection *,
1695 afs_RPCStatsClearFlag_t),
1696 afs_RPCStatsClearFlag_t flag, afs_status_p st)
1699 afs_status_t tst = 0;
1702 tst = ADMRXCONNNULL;
1703 goto fail_util_RPCStatsClear;
1707 tst = ADMRPCPTRNULL;
1708 goto fail_util_RPCStatsClear;
1711 tst = (*rpc) (conn, flag);
1717 fail_util_RPCStatsClear:
1726 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1730 * IN conn - an rx connection to the process to be modified
1732 * OUT version - the version of rpc stat collection at the remote process
1736 * No locks are obtained or released by this function
1740 * Returns != 0 upon successful completion.
1745 util_RPCStatsVersionGet(struct rx_connection *conn,
1746 afs_RPCStatsVersion_p version, afs_status_p st)
1749 afs_status_t tst = 0;
1752 tst = ADMRXCONNNULL;
1753 goto fail_util_RPCStatsVersionGet;
1756 if (version == NULL) {
1757 tst = ADMRPCVERSIONNULL;
1758 goto fail_util_RPCStatsVersionGet;
1761 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1767 fail_util_RPCStatsVersionGet:
1776 * The iterator for listing CM server preferences
1779 typedef struct cm_srvr_pref_get {
1780 struct rx_connection *conn;
1782 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1783 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1786 GetServerPrefsRPC(void *rpc_specific, int slot, int *last_item,
1787 int *last_item_contains_data, afs_status_p st)
1790 afs_status_t tst = 0;
1791 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1794 * Get the next entry in the list of server preferences.
1797 RXAFSCB_GetServerPrefs(t->conn, t->index, &t->srvrPrefs[slot].ipAddr,
1798 &t->srvrPrefs[slot].ipRank);
1800 goto fail_GetServerPrefsRPC;
1804 * See if we've processed all the entries
1806 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1808 *last_item_contains_data = 0;
1814 fail_GetServerPrefsRPC:
1823 GetServerPrefsFromCache(void *rpc_specific, int slot, void *dest,
1827 afs_status_t tst = 0;
1828 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1830 memcpy(dest, (const void *)&prefs->srvrPrefs[slot],
1831 sizeof(afs_CMServerPref_t));
1841 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1845 * IN conn - an rx connection to the process to be queried
1847 * OUT iterationIdP - an iteration id that can be passed to
1848 * util_CMGetServerPrefsNext to get the next server preference
1852 * No locks are obtained or released by this function
1856 * Returns != 0 upon successful completion.
1861 util_CMGetServerPrefsBegin(struct rx_connection *conn, void **iterationIdP,
1865 afs_status_t tst = 0;
1866 afs_admin_iterator_p iter;
1867 cm_srvr_pref_get_p pref;
1870 tst = ADMRXCONNNULL;
1871 goto fail_util_CMGetServerPrefsBegin;
1874 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1877 goto fail_util_CMGetServerPrefsBegin;
1880 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1884 goto fail_util_CMGetServerPrefsBegin;
1890 (iter, (void *)pref, GetServerPrefsRPC, GetServerPrefsFromCache, NULL,
1894 goto fail_util_CMGetServerPrefsBegin;
1896 *iterationIdP = (void *)iter;
1899 fail_util_CMGetServerPrefsBegin:
1908 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1913 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1915 * OUT prefs - Next entry in cache manager server preferences.
1919 * No locks are obtained or released by this function
1923 * Returns != 0 upon successful completion.
1928 util_CMGetServerPrefsNext(const void *iterationId, afs_CMServerPref_p prefs,
1932 afs_status_t tst = 0;
1933 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1935 if (iterationId == NULL) {
1936 tst = ADMITERATIONIDPNULL;
1937 goto fail_util_CMGetServerPrefsNext;
1940 rc = IteratorNext(iter, (void *)prefs, &tst);
1942 fail_util_CMGetServerPrefsNext:
1951 * util_CMGetServerPrefsDone - Finish listing cache manager server
1956 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1960 * No locks are obtained or released by this function
1964 * Returns != 0 upon successful completion.
1969 util_CMGetServerPrefsDone(const void *iterationId, afs_status_p st)
1972 afs_status_t tst = 0;
1973 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1975 if (iterationId == NULL) {
1976 tst = ADMITERATIONIDPNULL;
1977 goto fail_util_CMGetServerPrefsDone;
1980 rc = IteratorDone(iter, &tst);
1983 fail_util_CMGetServerPrefsDone:
1992 * The iterator for listing CM CellServDB
1995 typedef struct cm_list_cell_get {
1996 struct rx_connection *conn;
1998 afs_CMListCell_t cell[CACHED_ITEMS];
1999 } cm_list_cell_get_t, *cm_list_cell_get_p;
2002 ListCellsRPC(void *rpc_specific, int slot, int *last_item,
2003 int *last_item_contains_data, afs_status_p st)
2006 afs_status_t tst = 0;
2007 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2013 * Get the next entry in the CellServDB.
2015 name = t->cell[slot].cellname;
2016 sl.serverList_len = 0;
2017 sl.serverList_val = NULL;
2018 memset(t->cell[slot].serverAddr, 0, sizeof(afs_int32)*UTIL_MAX_CELL_HOSTS);
2020 RXAFSCB_GetCellServDB(t->conn, t->index, &name, &sl);
2022 goto fail_ListCellsRPC;
2024 strcpy(t->cell[slot].cellname, name);
2025 if (sl.serverList_val) {
2026 for (n=0; n<sl.serverList_len && n<UTIL_MAX_CELL_HOSTS; n++) {
2027 t->cell[slot].serverAddr[n] = sl.serverList_val[n];
2029 xdr_free((xdrproc_t) xdr_serverList, &sl);
2033 * See if we've processed all the entries
2035 if (strlen(t->cell[slot].cellname) == 0) {
2037 *last_item_contains_data = 0;
2052 ListCellsFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2055 afs_status_t tst = 0;
2056 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2058 memcpy(dest, (const void *)&cell->cell[slot], sizeof(afs_CMListCell_t));
2068 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2072 * IN conn - an rx connection to the process to be queried
2074 * OUT iterationIdP - an iteration id that can be passed to
2075 * util_CMListCellsNext to get the next cell
2079 * No locks are obtained or released by this function
2083 * Returns != 0 upon successful completion.
2088 util_CMListCellsBegin(struct rx_connection *conn, void **iterationIdP,
2092 afs_status_t tst = 0;
2093 afs_admin_iterator_p iter;
2094 cm_list_cell_get_p cell;
2097 tst = ADMRXCONNNULL;
2098 goto fail_util_CMListCellsBegin;
2101 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2104 goto fail_util_CMListCellsBegin;
2107 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2111 goto fail_util_CMListCellsBegin;
2117 (iter, (void *)cell, ListCellsRPC, ListCellsFromCache, NULL, NULL,
2121 goto fail_util_CMListCellsBegin;
2123 *iterationIdP = (void *)iter;
2126 fail_util_CMListCellsBegin:
2135 * util_CMListCellsNext - Get next entry in cache manager cells
2139 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2141 * OUT cell - Next entry in cache manager cells.
2145 * No locks are obtained or released by this function
2149 * Returns != 0 upon successful completion.
2154 util_CMListCellsNext(const void *iterationId, afs_CMListCell_p cell,
2158 afs_status_t tst = 0;
2159 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2161 if (iterationId == NULL) {
2162 tst = ADMITERATIONIDPNULL;
2163 goto fail_util_CMListCellsNext;
2166 rc = IteratorNext(iter, (void *)cell, &tst);
2168 fail_util_CMListCellsNext:
2177 * util_CMListCellsDone - Finish listing cache manager cells
2181 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2185 * No locks are obtained or released by this function
2189 * Returns != 0 upon successful completion.
2194 util_CMListCellsDone(const void *iterationId, afs_status_p st)
2197 afs_status_t tst = 0;
2198 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2200 if (iterationId == NULL) {
2201 tst = ADMITERATIONIDPNULL;
2202 goto fail_util_CMListCellsDone;
2205 rc = IteratorDone(iter, &tst);
2208 fail_util_CMListCellsDone:
2217 * util_CMLocalCell - Get the name of the cache manager's local cell.
2221 * IN conn - an rx connection to the process to be queried
2223 * OUT cellName - the name of the cache manager's local cell.
2227 * No locks are obtained or released by this function
2231 * Returns != 0 upon successful completion.
2236 util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
2240 afs_status_t tst = 0;
2241 afs_CMCellName_p name;
2244 tst = ADMRXCONNNULL;
2245 goto fail_util_CMLocalCell;
2248 if (cellName == NULL) {
2249 tst = ADMCLIENTCMCELLNAMENULL;
2250 goto fail_util_CMLocalCell;
2254 tst = RXAFSCB_GetLocalCell(conn, &name);
2260 fail_util_CMLocalCell:
2269 UnmarshallCMClientConfig(afs_uint32 serverVersion, afs_uint32 * ptr,
2270 afs_ClientConfigUnion_p config)
2273 * We currently only support version 1.
2275 config->config_v1.nChunkFiles = *(ptr++);
2276 config->config_v1.nStatCaches = *(ptr++);
2277 config->config_v1.nDataCaches = *(ptr++);
2278 config->config_v1.nVolumeCaches = *(ptr++);
2279 config->config_v1.firstChunkSize = *(ptr++);
2280 config->config_v1.otherChunkSize = *(ptr++);
2281 config->config_v1.cacheSize = *(ptr++);
2282 config->config_v1.setTime = *(ptr++);
2283 config->config_v1.memCache = *(ptr++);
2287 * util_CMClientConfig - Get the cache manager's configuration parameters.
2291 * IN conn - an rx connection to the process to be queried
2293 * OUT config - the cache manager's configuration parameters.
2297 * No locks are obtained or released by this function
2301 * Returns != 0 upon successful completion.
2306 util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
2310 afs_status_t tst = 0;
2311 afs_uint32 allocbytes;
2312 struct cacheConfig tconfig;
2315 tst = ADMRXCONNNULL;
2316 goto fail_util_CMClientConfig;
2319 if (config == NULL) {
2320 tst = ADMCLIENTCMCELLNAMENULL;
2321 goto fail_util_CMClientConfig;
2324 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2325 tconfig.cacheConfig_val = NULL;
2326 tconfig.cacheConfig_len = 0;
2328 RXAFSCB_GetCacheConfig(conn, config->clientVersion,
2329 &config->serverVersion, &allocbytes, &tconfig);
2332 goto fail_util_CMClientConfig;
2335 UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
2338 free(tconfig.cacheConfig_val);
2340 fail_util_CMClientConfig:
2349 * util_RXDebugVersion - Get the rxdebug version string.
2353 * IN handle - an rxdebug handle for the process to be queried.
2355 * OUT version - the rxdebug version string.
2359 * No locks are obtained or released by this function
2363 * Returns != 0 upon successful completion.
2368 util_RXDebugVersion(rxdebugHandle_p handle, rxdebugVersion_p version,
2372 afs_status_t tst = 0;
2375 if (handle == NULL) {
2376 tst = ADMRXDEBUGHANDLENULL;
2377 goto fail_util_RXDebugVersion;
2380 if (version == NULL) {
2381 tst = ADMRXDEBUGVERSIONNULL;
2382 goto fail_util_RXDebugVersion;
2386 rx_GetServerVersion(handle->sock, handle->ipAddr, handle->udpPort,
2387 UTIL_MAX_RXDEBUG_VERSION_LEN, version);
2389 tst = ADMCLIENTRXDEBUGTIMEOUT;
2390 goto fail_util_RXDebugVersion;
2395 fail_util_RXDebugVersion:
2404 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2409 * IN handle - an rxdebug handle for the process to be queried.
2411 * OUT supportedStats - bit mask with supported rxstats.
2415 * No locks are obtained or released by this function
2419 * Returns != 0 upon successful completion.
2424 util_RXDebugSupportedStats(rxdebugHandle_p handle,
2425 afs_uint32 * supportedStats, afs_status_p st)
2428 afs_status_t tst = 0;
2429 struct rx_debugStats tstats;
2431 if (handle == NULL) {
2432 tst = ADMRXDEBUGHANDLENULL;
2433 goto fail_util_RXDebugSupportedStats;
2436 if (supportedStats == NULL) {
2437 tst = ADMRXDEBUGSTATSNULL;
2438 goto fail_util_RXDebugSupportedStats;
2441 if (handle->firstFlag) {
2442 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2444 goto fail_util_RXDebugSupportedStats;
2448 *supportedStats = handle->supportedStats;
2451 fail_util_RXDebugSupportedStats:
2461 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2465 * IN handle - an rxdebug handle for the process to be queried.
2467 * OUT stats - Basic rxdebug statistics for the process.
2471 * No locks are obtained or released by this function
2475 * Returns != 0 upon successful completion.
2480 util_RXDebugBasicStats(rxdebugHandle_p handle, struct rx_debugStats *stats,
2484 afs_status_t tst = 0;
2487 if (handle == NULL) {
2488 tst = ADMRXDEBUGHANDLENULL;
2489 goto fail_util_RXDebugBasicStats;
2492 if (stats == NULL) {
2493 tst = ADMRXDEBUGSTATSNULL;
2494 goto fail_util_RXDebugBasicStats;
2498 rx_GetServerDebug(handle->sock, handle->ipAddr, handle->udpPort,
2499 stats, &handle->supportedStats);
2501 tst = ADMCLIENTRXDEBUGTIMEOUT;
2502 goto fail_util_RXDebugBasicStats;
2505 handle->firstFlag = 0;
2508 fail_util_RXDebugBasicStats:
2518 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2522 * IN handle - an rxdebug handle for the process to be queried.
2524 * OUT stats - Detailed rxdebug statistics for the process.
2528 * No locks are obtained or released by this function
2532 * Returns != 0 upon successful completion.
2537 util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_statistics *stats,
2538 afs_uint32 * supportedValues, afs_status_p st)
2542 afs_status_t tst = 0;
2544 afs_uint32 tsupported;
2546 if (handle == NULL) {
2547 tst = ADMRXDEBUGHANDLENULL;
2548 goto fail_util_RXDebugRxStats;
2551 if (supportedValues == NULL) {
2552 tst = ADMRXDEBUGSTATSNULL;
2553 goto fail_util_RXDebugRxStats;
2556 if (stats == NULL) {
2557 tst = ADMRXDEBUGSTATSNULL;
2558 goto fail_util_RXDebugRxStats;
2561 if (handle->firstFlag) {
2562 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2565 goto fail_util_RXDebugRxStats;
2569 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2570 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2571 goto fail_util_RXDebugRxStats;
2575 rx_GetServerStats(handle->sock, handle->ipAddr, handle->udpPort,
2576 stats, &handle->supportedStats);
2578 tst = ADMCLIENTRXDEBUGTIMEOUT;
2579 goto fail_util_RXDebugRxStats;
2584 fail_util_RXDebugRxStats:
2593 * The iterator for listing RXDebug connections
2596 typedef struct rxdebug_conn_item {
2597 struct rx_debugConn conn;
2598 afs_uint32 supportedValues;
2599 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2601 typedef struct rxdebug_conn_get {
2603 rxdebugHandle_p handle;
2605 rxdebug_conn_item_t items[CACHED_ITEMS];
2606 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2609 RXDebugConnsFromServer(void *rpc_specific, int slot, int *last_item,
2610 int *last_item_contains_data, afs_status_p st)
2614 afs_status_t tst = 0;
2615 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2618 * Get the next entry the list of connections
2621 rx_GetServerConnections(t->handle->sock, t->handle->ipAddr,
2622 t->handle->udpPort, &t->index, t->allconns,
2623 t->handle->supportedStats,
2624 &t->items[slot].conn,
2625 &t->items[slot].supportedValues);
2627 tst = ADMCLIENTRXDEBUGTIMEOUT;
2628 goto fail_ListCellsRPC;
2632 * See if we've processed all the entries
2634 if (t->items[slot].conn.cid == 0xffffffff) {
2636 *last_item_contains_data = 0;
2649 RXDebugConnsFromCache(void *rpc_specific, int slot, void *dest,
2653 afs_status_t tst = 0;
2654 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2656 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_conn_item_t));
2666 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2671 * IN handle - an rxdebug handle for the process to be queried
2673 * IN allcons - non-zero to list all connections. If zero, only
2674 * "interesting" connections will be listed.
2676 * OUT iterationIdP - an iteration id that can be passed to
2677 * util_RXDebugConnectionsNext.
2681 * No locks are obtained or released by this function
2685 * Returns != 0 upon successful completion.
2690 util_RXDebugConnectionsBegin(rxdebugHandle_p handle, int allconns,
2691 void **iterationIdP, afs_status_p st)
2695 afs_uint32 tsupported;
2696 afs_status_t tst = 0;
2697 afs_admin_iterator_p iter;
2698 rxdebug_conn_get_p t;
2700 if (handle == NULL) {
2701 tst = ADMRXDEBUGHANDLENULL;
2702 goto fail_util_RXDebugConnectionsBegin;
2705 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2708 goto fail_util_RXDebugConnectionsBegin;
2711 if (handle->firstFlag) {
2712 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2715 goto fail_util_RXDebugConnectionsBegin;
2719 if (allconns && !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2720 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2721 goto fail_util_RXDebugConnectionsBegin;
2724 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2728 goto fail_util_RXDebugConnectionsBegin;
2731 t->allconns = allconns;
2735 (iter, (void *)t, RXDebugConnsFromServer, RXDebugConnsFromCache, NULL,
2737 goto fail_util_RXDebugConnectionsBegin;
2739 *iterationIdP = (void *)iter;
2742 fail_util_RXDebugConnectionsBegin:
2752 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2757 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2759 * OUT conn - Rxdebug information for the next connection.
2761 * OUT supportedValues - Bit mask of supported rxdebug values.
2765 * No locks are obtained or released by this function
2769 * Returns != 0 upon successful completion.
2774 util_RXDebugConnectionsNext(const void *iterationId,
2775 struct rx_debugConn *conn,
2776 afs_uint32 * supportedValues, afs_status_p st)
2779 afs_status_t tst = 0;
2780 rxdebug_conn_item_t item;
2781 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2783 if (iterationId == NULL) {
2784 tst = ADMITERATIONIDPNULL;
2785 goto fail_util_RXDebugConnectionsNext;
2789 tst = ADMRXDEBUGHANDLENULL;
2790 goto fail_util_RXDebugConnectionsNext;
2793 if (supportedValues == NULL) {
2794 tst = ADMRXDEBUGHANDLENULL;
2795 goto fail_util_RXDebugConnectionsNext;
2798 rc = IteratorNext(iter, (void *)&item, &tst);
2800 goto fail_util_RXDebugConnectionsNext;
2804 *supportedValues = item.supportedValues;
2806 fail_util_RXDebugConnectionsNext:
2816 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2820 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2824 * No locks are obtained or released by this function
2828 * Returns != 0 upon successful completion.
2833 util_RXDebugConnectionsDone(const void *iterationId, afs_status_p st)
2836 afs_status_t tst = 0;
2837 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2840 * Validate parameters
2844 tst = ADMITERATORNULL;
2845 goto fail_util_RXDebugConnectionsDone;
2848 rc = IteratorDone(iter, &tst);
2850 fail_util_RXDebugConnectionsDone:
2860 * The iterator for listing RXDebug peer
2863 typedef struct rxdebug_peer_item {
2864 struct rx_debugPeer peer;
2865 afs_uint32 supportedValues;
2866 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2868 typedef struct rxdebug_peer_get {
2869 rxdebugHandle_p handle;
2871 rxdebug_peer_item_t items[CACHED_ITEMS];
2872 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2875 RXDebugPeersFromServer(void *rpc_specific, int slot, int *last_item,
2876 int *last_item_contains_data, afs_status_p st)
2880 afs_status_t tst = 0;
2881 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2884 * Get the next entry the list of peers
2887 rx_GetServerPeers(t->handle->sock, t->handle->ipAddr,
2888 t->handle->udpPort, &t->index,
2889 t->handle->supportedStats, &t->items[slot].peer,
2890 &t->items[slot].supportedValues);
2892 tst = ADMCLIENTRXDEBUGTIMEOUT;
2893 goto fail_ListCellsRPC;
2897 * See if we've processed all the entries
2899 if (t->items[slot].peer.host == 0xffffffff) {
2901 *last_item_contains_data = 0;
2914 RXDebugPeersFromCache(void *rpc_specific, int slot, void *dest,
2918 afs_status_t tst = 0;
2919 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2921 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_peer_item_t));
2932 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
2937 * IN handle - an rxdebug handle for the process to be queried
2939 * OUT iterationIdP - an iteration id that can be passed to
2940 * util_RXDebugPeersNext.
2944 * No locks are obtained or released by this function
2948 * Returns != 0 upon successful completion.
2953 util_RXDebugPeersBegin(rxdebugHandle_p handle, void **iterationIdP,
2958 afs_uint32 tsupported;
2959 afs_status_t tst = 0;
2960 afs_admin_iterator_p iter;
2961 rxdebug_peer_get_p t;
2963 if (handle == NULL) {
2964 tst = ADMRXDEBUGHANDLENULL;
2965 goto fail_util_RXDebugPeersBegin;
2968 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2971 goto fail_util_RXDebugPeersBegin;
2974 if (handle->firstFlag) {
2975 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2978 goto fail_util_RXDebugPeersBegin;
2982 if (!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
2983 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2984 goto fail_util_RXDebugPeersBegin;
2987 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
2991 goto fail_util_RXDebugPeersBegin;
2997 (iter, (void *)t, RXDebugPeersFromServer, RXDebugPeersFromCache, NULL,
2999 goto fail_util_RXDebugPeersBegin;
3001 *iterationIdP = (void *)iter;
3004 fail_util_RXDebugPeersBegin:
3013 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3017 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3019 * OUT peer - Rxdebug information for the next peer.
3021 * OUT supportedValues - Bit mask of supported rxdebug values.
3025 * No locks are obtained or released by this function
3029 * Returns != 0 upon successful completion.
3033 util_RXDebugPeersNext(const void *iterationId, struct rx_debugPeer *peer,
3034 afs_uint32 * supportedValues, afs_status_p st)
3037 afs_status_t tst = 0;
3038 rxdebug_peer_item_t item;
3039 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3041 if (iterationId == NULL) {
3042 tst = ADMITERATIONIDPNULL;
3043 goto fail_util_RXDebugPeersNext;
3047 tst = ADMRXDEBUGHANDLENULL;
3048 goto fail_util_RXDebugPeersNext;
3051 if (supportedValues == NULL) {
3052 tst = ADMRXDEBUGHANDLENULL;
3053 goto fail_util_RXDebugPeersNext;
3056 rc = IteratorNext(iter, (void *)&item, &tst);
3058 goto fail_util_RXDebugPeersNext;
3062 *supportedValues = item.supportedValues;
3064 fail_util_RXDebugPeersNext:
3073 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3077 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3081 * No locks are obtained or released by this function
3085 * Returns != 0 upon successful completion.
3090 util_RXDebugPeersDone(const void *iterationId, afs_status_p st)
3093 afs_status_t tst = 0;
3094 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3097 * Validate parameters
3101 tst = ADMITERATORNULL;
3102 goto fail_util_RXDebugPeersDone;
3105 rc = IteratorDone(iter, &tst);
3107 fail_util_RXDebugPeersDone: