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/afscbint.h>
34 #include <afs/volser.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 = malloc(sizeof(afs_admin_iterator_t));
230 database_server_get_p serv = calloc(1, sizeof(database_server_get_t));
231 char copyCell[MAXCELLCHARS];
237 if ((cellName == NULL) || (*cellName == 0)) {
238 tst = ADMUTILCELLNAMENULL;
239 goto fail_util_DatabaseServerGetBegin;
242 if (iterationIdP == NULL) {
243 goto fail_util_DatabaseServerGetBegin;
246 if ((iter == NULL) || (serv == NULL)) {
248 goto fail_util_DatabaseServerGetBegin;
252 * Fill in the serv structure
255 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
256 if (serv->conf == NULL) {
257 tst = ADMUTILCANTOPENCELLSERVDB;
258 goto fail_util_DatabaseServerGetBegin;
262 * We must copy the cellname because afsconf_GetCellInfo
263 * actually writes over the cell name it is passed.
265 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
267 afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
270 goto fail_util_DatabaseServerGetBegin;
273 serv->total = serv->cell.numServers;
275 (iter, (void *)serv, GetDatabaseServerRPC, GetDatabaseServerFromCache,
276 NULL, DestroyDatabaseServer, &tst)) {
277 *iterationIdP = (void *)iter;
279 goto fail_util_DatabaseServerGetBegin;
283 fail_util_DatabaseServerGetBegin:
301 * util_DatabaseServerGetNext - get the next server address.
305 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
307 * OUT serverAddressP - upon successful completion contains the next
308 * server address in the cell.
312 * This function locks the iterator for the duration of its processing.
320 * Returns != 0 upon successful completion.
325 util_DatabaseServerGetNext(const void *iterationId,
326 util_databaseServerEntry_p serverP,
330 afs_status_t tst = 0;
331 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
334 tst = ADMITERATORNULL;
335 goto fail_util_DatabaseServerGetNext;
338 if (serverP == NULL) {
339 tst = ADMUTILSERVERADDRESSPNULL;
340 goto fail_util_DatabaseServerGetNext;
343 rc = IteratorNext(iter, (void *)serverP, &tst);
345 fail_util_DatabaseServerGetNext:
354 * util_DatabaseServerGetDone - stop using a database iterator.
358 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
362 * This function locks the iterator for the duration of its processing.
363 * And then destroys it before returning.
371 * Returns != 0 upon successful completion.
375 util_DatabaseServerGetDone(const void *iterationId, afs_status_p st)
378 afs_status_t tst = 0;
379 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
382 * Validate parameters
386 tst = ADMITERATORNULL;
387 goto fail_util_DatabaseServerGetDone;
390 rc = IteratorDone(iter, &tst);
392 fail_util_DatabaseServerGetDone:
401 * GetServerAddressFromName - translate a character string server name
402 * to an integer representation of an IP address.
406 * IN serverName - the character string server name in either foo.com
407 * format, or 123.12.1.1 format.
409 * OUT serverAddress - an integer that is filled with the correct address
410 * in host byte order upon successful completion.
414 * No locks are obtained or released by this function
418 * On many platforms, gethostbyname is not thread safe. Since we are
419 * only working under NT for now I'll use it directly. In future UNIX
420 * ports, a wrapper function should be written to call the correct function
421 * on the particular platform.
425 * Returns != 0 upon successful completion.
429 util_AdminServerAddressGetFromName(const char *serverName, int *serverAddress,
433 afs_status_t tst = 0;
434 struct hostent *server;
435 int part1, part2, part3, part4;
438 if ((serverName == NULL) || (*serverName == 0)) {
439 tst = ADMUTILSERVERNAMENULL;
440 goto fail_util_AdminServerAddressGetFromName;
443 if (serverAddress == NULL) {
444 tst = ADMUTILSERVERADDRESSNULL;
445 goto fail_util_AdminServerAddressGetFromName;
449 sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
450 if (num_converted == 4) {
451 *serverAddress = (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
454 server = gethostbyname(serverName);
455 if (server != NULL) {
456 memcpy((void *)serverAddress, (const void *)server->h_addr,
458 *serverAddress = ntohl(*serverAddress);
460 tst = ADMUTILCANTGETSERVERNAME;
462 goto fail_util_AdminServerAddressGetFromName;
468 fail_util_AdminServerAddressGetFromName:
478 * This file contains functions that can be used to create iterator
479 * functions within the api. I have attempted to make these functions
480 * generic so that they can be used across the admin components.
482 * The functions in this file are a generalized producer/consumer
483 * implementation. They manage access to a queue of data. The only
484 * assumption these functions make about this data is that it is
485 * stored in a queue which is implemented via an array. These functions
486 * know about the index into the array, but they know nothing about
487 * the contents of the array.
489 * The data specific functions you implement will have to create some
490 * data specific storage structure that will have an array
491 * of size CACHED_ITEMS data items. This structure will also need to
492 * store any necessary parameters/state variables you need to issue the
493 * rpc to retrieve the next item.
495 * In order to use the generic functions, you must implement four functions
496 * for each type of data you wish to retrieve. The functions are:
498 * validate_specific_data_func - this function is handed a void pointer
499 * that points to the rpc specific data you've allocated. The function
500 * should examine the data for validity and return an appropriate error.
501 * This function is called every time the iterator is validated.
503 * destroy_specific_data_func - this function is handed a void pointer
504 * that points to the rpc specific data you've allocated. It should
505 * destroy any components of the specific data as required and then
506 * return. The void pointer is free'd by the generic functions.
508 * get_cached_data_func - this function is handed a void pointer
509 * that points to the rpc specific data you've allocated, an index
510 * into the cache of the item to be copied to the caller, and a void
511 * pointer where the cache item should be copied.
513 * make_rpc_func - this function is handed a void pointer that points
514 * to the rpc specific data you've allocated, an index into the cache
515 * of the item to be filled with the next retrieved item, and an int
516 * pointer that should be set to 1 if there are no more items to be
517 * retrieved. The assumption made by the generic functions is that
518 * the last_item status requires an individual rpc - the data isn't
519 * piggybacked on the last data item.
523 * IteratorDelete - delete an iterator.
527 * IN interator - the iterator to delete.
531 * No locks are held by this function.
535 * Returns != 0 upon successful completion.
539 IteratorDelete(afs_admin_iterator_p iter, afs_status_p st)
542 afs_status_t tst = 0;
544 if (pthread_mutex_destroy(&iter->mutex)) {
545 tst = ADMMUTEXDESTROY;
546 goto fail_IteratorDelete;
548 if (pthread_cond_destroy(&iter->add_item)) {
549 tst = ADMCONDDESTROY;
550 goto fail_IteratorDelete;
552 if (pthread_cond_destroy(&iter->remove_item)) {
553 tst = ADMCONDDESTROY;
554 goto fail_IteratorDelete;
557 if (iter->destroy_specific != NULL) {
558 iter->destroy_specific(iter->rpc_specific, &tst);
560 free(iter->rpc_specific);
573 * DataGet - the background thread that is spawned for every
574 * IteratorBegin call that is successful. This thread tries
575 * to fetch the data from the server ahead of the
576 * IteratorNext calls.
580 * IN arg - the address of the iterator structure to be used for this
585 * The iterator mutex is used by this function to protect elements
586 * of the iterator structure.
590 * Returns != 0 upon successful completion.
596 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
598 afs_status_t tst = 0;
599 int mutex_locked = 0;
601 int last_item_contains_data = 0;
603 if (pthread_mutex_lock(&iter->mutex)) {
604 iter->st = ADMMUTEXLOCK;
613 * Check to see if there's room for this datum. If not, wait
614 * on the consumer to free up another slot.
617 while (iter->cache_slots_used == CACHED_ITEMS) {
618 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
619 iter->st = ADMCONDWAIT;
625 * Check to see if someone called Done and terminated the request.
626 * We could have gone to sleep above when the buffer was full and
627 * instead of being awoken because another slot is open, we were
628 * awoken because the request was terminated.
631 if (iter->request_terminated) {
635 if (pthread_mutex_unlock(&iter->mutex)) {
636 iter->st = ADMMUTEXUNLOCK;
643 * Make an rpc without holding the iter mutex
644 * We reference an item in the principal cache here without
645 * holding the mutex. This is safe because:
646 * 1. The iter structure is ref counted and won't be deleted
647 * from underneath us.
648 * 2. cache_queue_tail is always one item ahead of the consumer
649 * thread so we are the only thread accessing this member.
652 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail, &last_item,
653 &last_item_contains_data, &tst);
655 if (pthread_mutex_lock(&iter->mutex)) {
656 iter->st = ADMMUTEXLOCK;
663 * Check to see if someone called Done and terminated the request
666 if (iter->request_terminated) {
671 * Check the rc of the rpc, and see if there are no more items
681 * Check to see if this is the last item produced by the rpc.
682 * If it isn't, add the item to the cache and proceed.
683 * If it is, check to see if the last item contains valid data.
684 * If it contains valid data, we need to add it to our cache.
685 * If it doesn't, we mark the iterator as complete.
688 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
689 iter->cache_queue_tail =
690 (iter->cache_queue_tail + 1) % CACHED_ITEMS;
691 iter->cache_slots_used++;
694 iter->st = ADMITERATORDONE;
695 iter->done_iterating = 1;
697 * There's a small chance that the consumer emptied the
698 * cache queue while we were making the last rpc and has
699 * since gone to sleep waiting for more data. In this case
700 * there will never be more data so we signal him here.
702 pthread_cond_signal(&iter->add_item);
708 * If the cache was empty and we just added another item, signal
712 if (iter->cache_slots_used == 1) {
713 if (pthread_cond_signal(&iter->add_item)) {
714 iter->st = ADMCONDSIGNAL;
724 * If we are exiting with an error, signal the consumer in the event
725 * they were waiting for us to produce more data
729 pthread_cond_signal(&iter->add_item);
733 pthread_mutex_unlock(&iter->mutex);
740 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
744 * IN interator - the interator to be verified.
748 * We assume the iter->mutex lock is already held.
752 * Returns != 0 upon successful completion.
756 IsValidIterator(const afs_admin_iterator_p iterator, afs_status_p st)
759 afs_status_t tst = 0;
762 * Validate input parameters
765 if (iterator == NULL) {
766 tst = ADMITERATORNULL;
767 goto fail_IsValidIterator;
770 if ((iterator->begin_magic != BEGIN_MAGIC)
771 || (iterator->end_magic != END_MAGIC)) {
772 tst = ADMITERATORBADMAGICNULL;
773 goto fail_IsValidIterator;
776 if (iterator->is_valid == 0) {
777 tst = ADMITERATORINVALID;
778 goto fail_IsValidIterator;
782 * Call the iterator specific validation function
785 if (iterator->validate_specific != NULL) {
786 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
787 goto fail_IsValidIterator;
792 fail_IsValidIterator:
801 * IteratorNext - return the next datum in an interator.
805 * IN interator - the iterator containing the data.
807 * IN dest - the address where the data should be copied.
811 * Lock the iterator upon entry, and hold it during the duration of this
816 * Returns != 0 upon successful completion.
820 IteratorNext(afs_admin_iterator_p iter, void *dest, afs_status_p st)
823 afs_status_t tst = 0;
827 * We have to lock the iterator before we validate it
830 if (pthread_mutex_lock(&iter->mutex)) {
832 goto fail_IteratorNext;
837 if (!IsValidIterator(iter, &tst)) {
838 goto fail_IteratorNext;
841 if (iter->request_terminated == 1) {
842 tst = ADMITERATORTERMINATED;
843 goto fail_IteratorNext;
846 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
848 goto fail_IteratorNext;
852 * Check to see if there are any queue'd items. If not, wait here
853 * until signalled by the producer.
856 while (iter->cache_slots_used == 0) {
859 * Maybe the producer experienced an rpc failure.
862 if ((!iter->done_iterating) && (iter->st != 0)) {
864 goto fail_IteratorNext;
868 * Maybe there are no queue'd items because the producer is done
871 if (iter->done_iterating) {
873 goto fail_IteratorNext;
876 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
878 goto fail_IteratorNext;
883 * Copy the next cached item and update the cached item count
884 * and the index into the cache array
888 get_cached_data(iter->rpc_specific, iter->cache_queue_head, dest,
890 goto fail_IteratorNext;
893 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
894 iter->cache_slots_used--;
897 * If the cache was full before we removed the item above, the
898 * producer may have been waiting for us to remove an item.
899 * Signal the producer letting him know that we've opened a slot
903 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
904 if (pthread_cond_signal(&iter->remove_item)) {
906 goto fail_IteratorNext;
914 if (locked_iter == 1) {
915 pthread_mutex_unlock(&iter->mutex);
925 * IteratorDone - mark the iterator done.
929 * IN interator - the iterator to mark done.
933 * Lock the iterator upon entry, and hold it during the duration of this
938 * Returns != 0 upon successful completion.
942 IteratorDone(afs_admin_iterator_p iter, afs_status_p st)
945 afs_status_t tst = 0;
946 int mutex_locked = 1;
948 if (pthread_mutex_lock(&iter->mutex)) {
950 goto fail_IteratorDone;
956 if (!IsValidIterator(iter, &tst)) {
957 goto fail_IteratorDone;
962 * Depending upon the status of the background worker thread,
963 * we can either join with him immediately (if we know he has
964 * terminated), or we need to tell him the request has been
965 * terminated and then join with him.
968 if (!iter->done_iterating) {
969 iter->request_terminated = 1;
970 iter->cache_slots_used = 0;
971 pthread_cond_signal(&iter->remove_item);
975 * We have to unlock the mutex to allow the background thread to
979 if (pthread_mutex_unlock(&iter->mutex)) {
980 tst = ADMMUTEXUNLOCK;
981 goto fail_IteratorDone;
984 if (iter->make_rpc != NULL) {
985 if (pthread_join(iter->bg_worker, (void **)0)) {
987 goto fail_IteratorDone;
992 * We don't relock the mutex here since we are the only thread
993 * that has access to the iter now
996 rc = IteratorDelete(iter, &tst);
1002 pthread_mutex_unlock(&iter->mutex);
1012 * IteratorInit - initialize an iterator.
1016 * IN interator - the iterator to initialize.
1020 * No locks are held by this function.
1024 * Returns != 0 upon successful completion.
1028 IteratorInit(afs_admin_iterator_p iter, void *rpc_specific,
1029 make_rpc_func make_rpc, get_cached_data_func get_cached_data,
1030 validate_specific_data_func validate_specific_data,
1031 destroy_specific_data_func destroy_specific_data,
1035 afs_status_t tst = 0;
1036 int mutex_inited = 0;
1037 int add_item_cond_inited = 0;
1038 int remove_item_cond_inited = 0;
1041 tst = ADMITERATORNULL;
1042 goto fail_IteratorInit;
1045 if (rpc_specific == NULL) {
1046 tst = ADMITERATORRPCSPECIFICNULL;
1047 goto fail_IteratorInit;
1051 * Initialize the iterator structure
1053 iter->begin_magic = BEGIN_MAGIC;
1054 iter->end_magic = END_MAGIC;
1056 iter->cache_slots_used = 0;
1057 iter->done_iterating = 0;
1058 iter->request_terminated = 0;
1059 iter->st = AFS_STATUS_OK;
1060 iter->cache_queue_head = 0;
1061 iter->cache_queue_tail = 0;
1062 iter->cache_slots_used = 0;
1063 iter->rpc_specific = rpc_specific;
1064 iter->make_rpc = make_rpc;
1065 iter->get_cached_data = get_cached_data;
1066 iter->validate_specific = validate_specific_data;
1067 iter->destroy_specific = destroy_specific_data;
1069 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *)0)) {
1071 goto fail_IteratorInit;
1076 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *)0)) {
1078 goto fail_IteratorInit;
1080 add_item_cond_inited = 1;
1083 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *)0)) {
1085 goto fail_IteratorInit;
1087 remove_item_cond_inited = 1;
1091 * Create a worker thread that will begin to query the server
1092 * and cache responses.
1095 if (iter->make_rpc != NULL) {
1096 pthread_attr_t tattr;
1098 if (pthread_attr_init(&tattr)) {
1099 tst = ADMTHREADATTRINIT;
1100 goto fail_IteratorInit;
1103 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1104 tst = ADMTHREADATTRSETDETACHSTATE;
1105 goto fail_IteratorInit;
1108 if (pthread_create(&iter->bg_worker, &tattr, DataGet, (void *)iter)) {
1109 tst = ADMTHREADCREATE;
1110 goto fail_IteratorInit;
1119 pthread_mutex_destroy(&iter->mutex);
1121 if (remove_item_cond_inited) {
1122 pthread_cond_destroy(&iter->remove_item);
1124 if (add_item_cond_inited) {
1125 pthread_cond_destroy(&iter->add_item);
1136 CellHandleIsValid(const void *cellHandle, afs_status_p st)
1139 afs_status_t tst = 0;
1140 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1143 * Validate input parameters
1146 if (c_handle == NULL) {
1147 tst = ADMCLIENTCELLHANDLENULL;
1148 goto fail_CellHandleIsValid;
1151 if ((c_handle->begin_magic != BEGIN_MAGIC)
1152 || (c_handle->end_magic != END_MAGIC)) {
1153 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1154 goto fail_CellHandleIsValid;
1157 if (c_handle->is_valid == 0) {
1158 tst = ADMCLIENTCELLINVALID;
1159 goto fail_CellHandleIsValid;
1163 fail_CellHandleIsValid:
1172 * The iterator functions and data for the rpc statistic retrieval functions
1175 typedef struct rpc_stat_get {
1176 afs_uint32 clock_sec;
1177 afs_uint32 clock_usec;
1180 afs_uint32 clientVersion;
1181 afs_uint32 serverVersion;
1182 struct rpcStats stat_list;
1183 afs_RPCStats_t stats[CACHED_ITEMS];
1184 afs_uint32 *pointer;
1185 } rpc_stat_get_t, *rpc_stat_get_p;
1188 UnmarshallRPCStats(afs_uint32 serverVersion, afs_uint32 ** ptrP,
1192 unsigned int hi, lo;
1195 * Server must always match lower versions. We are version 1.
1198 s->stats_v1.remote_peer = *(ptr++);
1199 s->stats_v1.remote_port = *(ptr++);
1200 s->stats_v1.remote_is_server = *(ptr++);
1201 s->stats_v1.interfaceId = *(ptr++);
1202 s->stats_v1.func_total = *(ptr++);
1203 s->stats_v1.func_index = *(ptr++);
1206 s->stats_v1.invocations = ((afs_uint64) hi << 32) + lo;
1209 s->stats_v1.bytes_sent = ((afs_uint64) hi << 32) + lo;
1212 s->stats_v1.bytes_rcvd = ((afs_uint64) hi << 32) + lo;
1213 s->stats_v1.queue_time_sum.sec = *(ptr++);
1214 s->stats_v1.queue_time_sum.usec = *(ptr++);
1215 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1216 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1217 s->stats_v1.queue_time_min.sec = *(ptr++);
1218 s->stats_v1.queue_time_min.usec = *(ptr++);
1219 s->stats_v1.queue_time_max.sec = *(ptr++);
1220 s->stats_v1.queue_time_max.usec = *(ptr++);
1221 s->stats_v1.execution_time_sum.sec = *(ptr++);
1222 s->stats_v1.execution_time_sum.usec = *(ptr++);
1223 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1224 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1225 s->stats_v1.execution_time_min.sec = *(ptr++);
1226 s->stats_v1.execution_time_min.usec = *(ptr++);
1227 s->stats_v1.execution_time_max.sec = *(ptr++);
1228 s->stats_v1.execution_time_max.usec = *(ptr++);
1233 GetRPCStatsRPC(void *rpc_specific, int slot, int *last_item,
1234 int *last_item_contains_data, afs_status_p st)
1237 afs_status_t tst = 0;
1238 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1240 t->stats[slot].clientVersion = t->clientVersion;
1241 t->stats[slot].serverVersion = t->serverVersion;
1242 t->stats[slot].statCount = t->total;
1245 * If the server stat version is greater than or equal to my version
1246 * number, it is required to return the values in the client's current
1250 UnmarshallRPCStats(t->serverVersion, &t->pointer, &t->stats[slot].s);
1255 * See if we've processed all the entries
1258 if (t->index == t->total) {
1260 *last_item_contains_data = 1;
1271 GetRPCStatsFromCache(void *rpc_specific, int slot, void *dest,
1275 afs_status_t tst = 0;
1276 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1278 memcpy(dest, (const void *)&stat->stats[slot], sizeof(afs_RPCStats_t));
1288 DestroyRPCStats(void *rpc_specific, afs_status_p st)
1291 afs_status_t tst = 0;
1292 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1294 if (stat->stat_list.rpcStats_val != NULL) {
1295 free(stat->stat_list.rpcStats_val);
1306 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1310 * IN conn - an rx connection to the process to be queried
1312 * IN rpc - the function to call to make the actual rpc
1314 * OUT iterationIdP - an iteration id that can be passed to
1315 * util_RPCStatsGetNext to get the next rpc stat
1319 * No locks are obtained or released by this function
1323 * Returns != 0 upon successful completion.
1328 util_RPCStatsGetBegin(struct rx_connection *conn,
1329 int (*rpc) (struct rx_connection *,
1330 afs_uint32, afs_uint32 *,
1331 afs_uint32 *, afs_uint32 *,
1332 afs_uint32 *, struct rpcStats *),
1333 void **iterationIdP, afs_status_p st)
1336 afs_status_t tst = 0;
1337 afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
1338 rpc_stat_get_p stat = malloc(sizeof(rpc_stat_get_t));
1341 tst = ADMRXCONNNULL;
1342 goto fail_util_RPCStatsGetBegin;
1346 tst = ADMRPCPTRNULL;
1347 goto fail_util_RPCStatsGetBegin;
1350 if (iterationIdP == NULL) {
1351 tst = ADMITERATIONIDPNULL;
1352 goto fail_util_RPCStatsGetBegin;
1355 if ((iter == NULL) || (stat == NULL)) {
1357 goto fail_util_RPCStatsGetBegin;
1360 stat->stat_list.rpcStats_len = 0;
1361 stat->stat_list.rpcStats_val = 0;
1363 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1366 (*rpc) (conn, stat->clientVersion, &stat->serverVersion,
1367 &stat->clock_sec, &stat->clock_usec, &stat->total,
1371 goto fail_util_RPCStatsGetBegin;
1375 * If there are no statistics, just mark the iterator done and
1379 if (stat->stat_list.rpcStats_len == 0) {
1380 stat->pointer = NULL;
1381 if (!IteratorInit(iter, (void *)stat, NULL, NULL, NULL, NULL, &tst)) {
1382 goto fail_util_RPCStatsGetBegin;
1384 iter->done_iterating = 1;
1385 iter->st = ADMITERATORDONE;
1387 stat->pointer = stat->stat_list.rpcStats_val;
1389 (iter, (void *)stat, GetRPCStatsRPC, GetRPCStatsFromCache, NULL,
1390 DestroyRPCStats, &tst)) {
1391 goto fail_util_RPCStatsGetBegin;
1394 *iterationIdP = (void *)iter;
1397 fail_util_RPCStatsGetBegin:
1415 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1419 * IN iterationId - an iterator previously returned by
1420 * util_RPCStatsGetBegin.
1422 * OUT stats - upon successful completion contains the next set of stats
1427 * No locks are obtained or released by this function
1431 * Returns != 0 upon successful completion.
1436 util_RPCStatsGetNext(const void *iterationId, afs_RPCStats_p stats,
1440 afs_status_t tst = 0;
1441 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1443 if (iterationId == NULL) {
1444 tst = ADMITERATIONIDPNULL;
1445 goto fail_util_RPCStatsGetNext;
1448 if (stats == NULL) {
1449 tst = ADMUTILRPCSTATSNULL;
1450 goto fail_util_RPCStatsGetNext;
1453 rc = IteratorNext(iter, (void *)stats, &tst);
1455 fail_util_RPCStatsGetNext:
1464 * util_RPCStatsGetDone - finish using a stats iterator
1468 * IN iterationId - an iterator previously returned by
1469 * util_RPCStatsGetBegin.
1473 * No locks are obtained or released by this function
1477 * Returns != 0 upon successful completion.
1482 util_RPCStatsGetDone(const void *iterationId, afs_status_p st)
1485 afs_status_t tst = 0;
1486 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1488 if (iterationId == NULL) {
1489 tst = ADMITERATIONIDPNULL;
1490 goto fail_util_RPCStatsGetDone;
1493 rc = IteratorDone(iter, &tst);
1495 fail_util_RPCStatsGetDone:
1504 * util_RPCStatsStateGet - get the current state of rpc stat collection
1508 * IN conn - an rx connection to the process to be queried
1510 * IN rpc - the function to call to make the actual rpc
1512 * OUT state - the rpc stat collection state.
1516 * No locks are obtained or released by this function
1520 * Returns != 0 upon successful completion.
1525 util_RPCStatsStateGet(struct rx_connection *conn,
1526 int (*rpc) (struct rx_connection *,
1527 afs_RPCStatsState_p),
1528 afs_RPCStatsState_p state, afs_status_p st)
1531 afs_status_t tst = 0;
1534 tst = ADMRXCONNNULL;
1535 goto fail_util_RPCStatsStateGet;
1539 tst = ADMRPCPTRNULL;
1540 goto fail_util_RPCStatsStateGet;
1543 if (state == NULL) {
1544 tst = ADMRPCSTATENULL;
1545 goto fail_util_RPCStatsStateGet;
1548 tst = (*rpc) (conn, state);
1554 fail_util_RPCStatsStateGet:
1563 * util_RPCStatsStateEnable - enable rpc stat collection
1568 * IN conn - an rx connection to the process to be modified
1570 * IN rpc - the function to call to make the actual rpc
1574 * No locks are obtained or released by this function
1578 * Returns != 0 upon successful completion.
1583 util_RPCStatsStateEnable(struct rx_connection *conn,
1584 int (*rpc) (struct rx_connection *),
1588 afs_status_t tst = 0;
1591 tst = ADMRXCONNNULL;
1592 goto fail_util_RPCStatsStateEnable;
1596 tst = ADMRPCPTRNULL;
1597 goto fail_util_RPCStatsStateEnable;
1600 tst = (*rpc) (conn);
1606 fail_util_RPCStatsStateEnable:
1615 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1620 * IN conn - an rx connection to the process to be modified
1622 * IN rpc - the function to call to make the actual rpc
1626 * No locks are obtained or released by this function
1630 * Returns != 0 upon successful completion.
1635 util_RPCStatsStateDisable(struct rx_connection *conn,
1636 int (*rpc) (struct rx_connection *),
1640 afs_status_t tst = 0;
1643 tst = ADMRXCONNNULL;
1644 goto fail_util_RPCStatsStateDisable;
1648 tst = ADMRPCPTRNULL;
1649 goto fail_util_RPCStatsStateDisable;
1652 tst = (*rpc) (conn);
1658 fail_util_RPCStatsStateDisable:
1667 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1668 * collection at a server
1672 * IN conn - an rx connection to the process to be modified
1674 * IN rpc - the function to call to make the actual rpc
1676 * IN flag - a flag containing the fields to be cleared
1681 * No locks are obtained or released by this function
1685 * Returns != 0 upon successful completion.
1690 util_RPCStatsClear(struct rx_connection *conn,
1691 int (*rpc) (struct rx_connection *,
1692 afs_RPCStatsClearFlag_t),
1693 afs_RPCStatsClearFlag_t flag, afs_status_p st)
1696 afs_status_t tst = 0;
1699 tst = ADMRXCONNNULL;
1700 goto fail_util_RPCStatsClear;
1704 tst = ADMRPCPTRNULL;
1705 goto fail_util_RPCStatsClear;
1708 tst = (*rpc) (conn, flag);
1714 fail_util_RPCStatsClear:
1723 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1727 * IN conn - an rx connection to the process to be modified
1729 * OUT version - the version of rpc stat collection at the remote process
1733 * No locks are obtained or released by this function
1737 * Returns != 0 upon successful completion.
1742 util_RPCStatsVersionGet(struct rx_connection *conn,
1743 afs_RPCStatsVersion_p version, afs_status_p st)
1746 afs_status_t tst = 0;
1749 tst = ADMRXCONNNULL;
1750 goto fail_util_RPCStatsVersionGet;
1753 if (version == NULL) {
1754 tst = ADMRPCVERSIONNULL;
1755 goto fail_util_RPCStatsVersionGet;
1758 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1764 fail_util_RPCStatsVersionGet:
1773 * The iterator for listing CM server preferences
1776 typedef struct cm_srvr_pref_get {
1777 struct rx_connection *conn;
1779 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1780 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1783 GetServerPrefsRPC(void *rpc_specific, int slot, int *last_item,
1784 int *last_item_contains_data, afs_status_p st)
1787 afs_status_t tst = 0;
1788 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1791 * Get the next entry in the list of server preferences.
1794 RXAFSCB_GetServerPrefs(t->conn, t->index, &t->srvrPrefs[slot].ipAddr,
1795 &t->srvrPrefs[slot].ipRank);
1797 goto fail_GetServerPrefsRPC;
1801 * See if we've processed all the entries
1803 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1805 *last_item_contains_data = 0;
1811 fail_GetServerPrefsRPC:
1820 GetServerPrefsFromCache(void *rpc_specific, int slot, void *dest,
1824 afs_status_t tst = 0;
1825 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1827 memcpy(dest, (const void *)&prefs->srvrPrefs[slot],
1828 sizeof(afs_CMServerPref_t));
1838 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1842 * IN conn - an rx connection to the process to be queried
1844 * OUT iterationIdP - an iteration id that can be passed to
1845 * util_CMGetServerPrefsNext to get the next server preference
1849 * No locks are obtained or released by this function
1853 * Returns != 0 upon successful completion.
1858 util_CMGetServerPrefsBegin(struct rx_connection *conn, void **iterationIdP,
1862 afs_status_t tst = 0;
1863 afs_admin_iterator_p iter;
1864 cm_srvr_pref_get_p pref;
1867 tst = ADMRXCONNNULL;
1868 goto fail_util_CMGetServerPrefsBegin;
1871 iter = malloc(sizeof(afs_admin_iterator_t));
1874 goto fail_util_CMGetServerPrefsBegin;
1877 pref = malloc(sizeof(cm_srvr_pref_get_t));
1881 goto fail_util_CMGetServerPrefsBegin;
1887 (iter, (void *)pref, GetServerPrefsRPC, GetServerPrefsFromCache, NULL,
1891 goto fail_util_CMGetServerPrefsBegin;
1893 *iterationIdP = (void *)iter;
1896 fail_util_CMGetServerPrefsBegin:
1905 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1910 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1912 * OUT prefs - Next entry in cache manager server preferences.
1916 * No locks are obtained or released by this function
1920 * Returns != 0 upon successful completion.
1925 util_CMGetServerPrefsNext(const void *iterationId, afs_CMServerPref_p prefs,
1929 afs_status_t tst = 0;
1930 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1932 if (iterationId == NULL) {
1933 tst = ADMITERATIONIDPNULL;
1934 goto fail_util_CMGetServerPrefsNext;
1937 rc = IteratorNext(iter, (void *)prefs, &tst);
1939 fail_util_CMGetServerPrefsNext:
1948 * util_CMGetServerPrefsDone - Finish listing cache manager server
1953 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1957 * No locks are obtained or released by this function
1961 * Returns != 0 upon successful completion.
1966 util_CMGetServerPrefsDone(const void *iterationId, afs_status_p st)
1969 afs_status_t tst = 0;
1970 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1972 if (iterationId == NULL) {
1973 tst = ADMITERATIONIDPNULL;
1974 goto fail_util_CMGetServerPrefsDone;
1977 rc = IteratorDone(iter, &tst);
1980 fail_util_CMGetServerPrefsDone:
1989 * The iterator for listing CM CellServDB
1992 typedef struct cm_list_cell_get {
1993 struct rx_connection *conn;
1995 afs_CMListCell_t cell[CACHED_ITEMS];
1996 } cm_list_cell_get_t, *cm_list_cell_get_p;
1999 ListCellsRPC(void *rpc_specific, int slot, int *last_item,
2000 int *last_item_contains_data, afs_status_p st)
2003 afs_status_t tst = 0;
2004 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2011 * Get the next entry in the CellServDB.
2013 sl.serverList_len = 0;
2014 sl.serverList_val = NULL;
2015 memset(t->cell[slot].serverAddr, 0, sizeof(afs_int32)*UTIL_MAX_CELL_HOSTS);
2017 RXAFSCB_GetCellServDB(t->conn, t->index, &name, &sl);
2019 goto fail_ListCellsRPC;
2021 len = strlcpy(t->cell[slot].cellname, name, sizeof(t->cell[slot].cellname));
2022 if (len >= sizeof(t->cell[slot].cellname)) {
2024 goto fail_ListCellsRPC;
2026 if (sl.serverList_val) {
2027 for (n=0; n<sl.serverList_len && n<UTIL_MAX_CELL_HOSTS; n++) {
2028 t->cell[slot].serverAddr[n] = sl.serverList_val[n];
2033 * See if we've processed all the entries
2035 if (strlen(t->cell[slot].cellname) == 0) {
2037 *last_item_contains_data = 0;
2044 xdr_free((xdrproc_t) xdr_serverList, &sl);
2045 xdr_free((xdrproc_t) xdr_string, &name);
2054 ListCellsFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2057 afs_status_t tst = 0;
2058 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2060 memcpy(dest, (const void *)&cell->cell[slot], sizeof(afs_CMListCell_t));
2070 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2074 * IN conn - an rx connection to the process to be queried
2076 * OUT iterationIdP - an iteration id that can be passed to
2077 * util_CMListCellsNext to get the next cell
2081 * No locks are obtained or released by this function
2085 * Returns != 0 upon successful completion.
2090 util_CMListCellsBegin(struct rx_connection *conn, void **iterationIdP,
2094 afs_status_t tst = 0;
2095 afs_admin_iterator_p iter;
2096 cm_list_cell_get_p cell;
2099 tst = ADMRXCONNNULL;
2100 goto fail_util_CMListCellsBegin;
2103 iter = malloc(sizeof(afs_admin_iterator_t));
2106 goto fail_util_CMListCellsBegin;
2109 cell = malloc(sizeof(cm_list_cell_get_t));
2113 goto fail_util_CMListCellsBegin;
2119 (iter, (void *)cell, ListCellsRPC, ListCellsFromCache, NULL, NULL,
2123 goto fail_util_CMListCellsBegin;
2125 *iterationIdP = (void *)iter;
2128 fail_util_CMListCellsBegin:
2137 * util_CMListCellsNext - Get next entry in cache manager cells
2141 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2143 * OUT cell - Next entry in cache manager cells.
2147 * No locks are obtained or released by this function
2151 * Returns != 0 upon successful completion.
2156 util_CMListCellsNext(const void *iterationId, afs_CMListCell_p cell,
2160 afs_status_t tst = 0;
2161 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2163 if (iterationId == NULL) {
2164 tst = ADMITERATIONIDPNULL;
2165 goto fail_util_CMListCellsNext;
2168 rc = IteratorNext(iter, (void *)cell, &tst);
2170 fail_util_CMListCellsNext:
2179 * util_CMListCellsDone - Finish listing cache manager cells
2183 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2187 * No locks are obtained or released by this function
2191 * Returns != 0 upon successful completion.
2196 util_CMListCellsDone(const void *iterationId, afs_status_p st)
2199 afs_status_t tst = 0;
2200 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2202 if (iterationId == NULL) {
2203 tst = ADMITERATIONIDPNULL;
2204 goto fail_util_CMListCellsDone;
2207 rc = IteratorDone(iter, &tst);
2210 fail_util_CMListCellsDone:
2219 * util_CMLocalCell - Get the name of the cache manager's local cell.
2223 * IN conn - an rx connection to the process to be queried
2225 * OUT cellName - the name of the cache manager's local cell.
2229 * No locks are obtained or released by this function
2233 * Returns != 0 upon successful completion.
2238 util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
2242 afs_status_t tst = 0;
2247 tst = ADMRXCONNNULL;
2248 goto fail_util_CMLocalCell;
2251 if (cellName == NULL) {
2252 tst = ADMCLIENTCMCELLNAMENULL;
2253 goto fail_util_CMLocalCell;
2256 tst = RXAFSCB_GetLocalCell(conn, &name);
2258 goto fail_util_CMLocalCell;
2261 len = strlcpy(cellName, name, sizeof(cellName));
2262 if (len >= sizeof(cellName)) {
2264 goto fail_util_CMLocalCell;
2268 fail_util_CMLocalCell:
2270 xdr_free((xdrproc_t)xdr_string, &name);
2278 UnmarshallCMClientConfig(afs_uint32 serverVersion, afs_uint32 * ptr,
2279 afs_ClientConfigUnion_p config)
2282 * We currently only support version 1.
2284 config->config_v1.nChunkFiles = *(ptr++);
2285 config->config_v1.nStatCaches = *(ptr++);
2286 config->config_v1.nDataCaches = *(ptr++);
2287 config->config_v1.nVolumeCaches = *(ptr++);
2288 config->config_v1.firstChunkSize = *(ptr++);
2289 config->config_v1.otherChunkSize = *(ptr++);
2290 config->config_v1.cacheSize = *(ptr++);
2291 config->config_v1.setTime = *(ptr++);
2292 config->config_v1.memCache = *(ptr++);
2296 * util_CMClientConfig - Get the cache manager's configuration parameters.
2300 * IN conn - an rx connection to the process to be queried
2302 * OUT config - the cache manager's configuration parameters.
2306 * No locks are obtained or released by this function
2310 * Returns != 0 upon successful completion.
2315 util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
2319 afs_status_t tst = 0;
2320 afs_uint32 allocbytes;
2321 struct cacheConfig tconfig;
2324 tst = ADMRXCONNNULL;
2325 goto fail_util_CMClientConfig;
2328 if (config == NULL) {
2329 tst = ADMCLIENTCMCELLNAMENULL;
2330 goto fail_util_CMClientConfig;
2333 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2334 tconfig.cacheConfig_val = NULL;
2335 tconfig.cacheConfig_len = 0;
2337 RXAFSCB_GetCacheConfig(conn, config->clientVersion,
2338 &config->serverVersion, &allocbytes, &tconfig);
2341 goto fail_util_CMClientConfig;
2344 UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
2347 free(tconfig.cacheConfig_val);
2349 fail_util_CMClientConfig:
2358 * util_RXDebugVersion - Get the rxdebug version string.
2362 * IN handle - an rxdebug handle for the process to be queried.
2364 * OUT version - the rxdebug version string.
2368 * No locks are obtained or released by this function
2372 * Returns != 0 upon successful completion.
2377 util_RXDebugVersion(rxdebugHandle_p handle, rxdebugVersion_p version,
2381 afs_status_t tst = 0;
2384 if (handle == NULL) {
2385 tst = ADMRXDEBUGHANDLENULL;
2386 goto fail_util_RXDebugVersion;
2389 if (version == NULL) {
2390 tst = ADMRXDEBUGVERSIONNULL;
2391 goto fail_util_RXDebugVersion;
2395 rx_GetServerVersion(handle->sock, handle->ipAddr, handle->udpPort,
2396 UTIL_MAX_RXDEBUG_VERSION_LEN, version);
2398 tst = ADMCLIENTRXDEBUGTIMEOUT;
2399 goto fail_util_RXDebugVersion;
2404 fail_util_RXDebugVersion:
2413 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2418 * IN handle - an rxdebug handle for the process to be queried.
2420 * OUT supportedStats - bit mask with supported rxstats.
2424 * No locks are obtained or released by this function
2428 * Returns != 0 upon successful completion.
2433 util_RXDebugSupportedStats(rxdebugHandle_p handle,
2434 afs_uint32 * supportedStats, afs_status_p st)
2437 afs_status_t tst = 0;
2438 struct rx_debugStats tstats;
2440 if (handle == NULL) {
2441 tst = ADMRXDEBUGHANDLENULL;
2442 goto fail_util_RXDebugSupportedStats;
2445 if (supportedStats == NULL) {
2446 tst = ADMRXDEBUGSTATSNULL;
2447 goto fail_util_RXDebugSupportedStats;
2450 if (handle->firstFlag) {
2451 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2453 goto fail_util_RXDebugSupportedStats;
2457 *supportedStats = handle->supportedStats;
2460 fail_util_RXDebugSupportedStats:
2470 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2474 * IN handle - an rxdebug handle for the process to be queried.
2476 * OUT stats - Basic rxdebug statistics for the process.
2480 * No locks are obtained or released by this function
2484 * Returns != 0 upon successful completion.
2489 util_RXDebugBasicStats(rxdebugHandle_p handle, struct rx_debugStats *stats,
2493 afs_status_t tst = 0;
2496 if (handle == NULL) {
2497 tst = ADMRXDEBUGHANDLENULL;
2498 goto fail_util_RXDebugBasicStats;
2501 if (stats == NULL) {
2502 tst = ADMRXDEBUGSTATSNULL;
2503 goto fail_util_RXDebugBasicStats;
2507 rx_GetServerDebug(handle->sock, handle->ipAddr, handle->udpPort,
2508 stats, &handle->supportedStats);
2510 tst = ADMCLIENTRXDEBUGTIMEOUT;
2511 goto fail_util_RXDebugBasicStats;
2514 handle->firstFlag = 0;
2517 fail_util_RXDebugBasicStats:
2527 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2531 * IN handle - an rxdebug handle for the process to be queried.
2533 * OUT stats - Detailed rxdebug statistics for the process.
2537 * No locks are obtained or released by this function
2541 * Returns != 0 upon successful completion.
2546 util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_statistics *stats,
2547 afs_uint32 * supportedValues, afs_status_p st)
2551 afs_status_t tst = 0;
2553 afs_uint32 tsupported;
2555 if (handle == NULL) {
2556 tst = ADMRXDEBUGHANDLENULL;
2557 goto fail_util_RXDebugRxStats;
2560 if (supportedValues == NULL) {
2561 tst = ADMRXDEBUGSTATSNULL;
2562 goto fail_util_RXDebugRxStats;
2565 if (stats == NULL) {
2566 tst = ADMRXDEBUGSTATSNULL;
2567 goto fail_util_RXDebugRxStats;
2570 if (handle->firstFlag) {
2571 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2574 goto fail_util_RXDebugRxStats;
2578 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2579 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2580 goto fail_util_RXDebugRxStats;
2584 rx_GetServerStats(handle->sock, handle->ipAddr, handle->udpPort,
2585 stats, &handle->supportedStats);
2587 tst = ADMCLIENTRXDEBUGTIMEOUT;
2588 goto fail_util_RXDebugRxStats;
2593 fail_util_RXDebugRxStats:
2602 * The iterator for listing RXDebug connections
2605 typedef struct rxdebug_conn_item {
2606 struct rx_debugConn conn;
2607 afs_uint32 supportedValues;
2608 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2610 typedef struct rxdebug_conn_get {
2612 rxdebugHandle_p handle;
2614 rxdebug_conn_item_t items[CACHED_ITEMS];
2615 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2618 RXDebugConnsFromServer(void *rpc_specific, int slot, int *last_item,
2619 int *last_item_contains_data, afs_status_p st)
2623 afs_status_t tst = 0;
2624 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2627 * Get the next entry the list of connections
2630 rx_GetServerConnections(t->handle->sock, t->handle->ipAddr,
2631 t->handle->udpPort, &t->index, t->allconns,
2632 t->handle->supportedStats,
2633 &t->items[slot].conn,
2634 &t->items[slot].supportedValues);
2636 tst = ADMCLIENTRXDEBUGTIMEOUT;
2637 goto fail_ListCellsRPC;
2641 * See if we've processed all the entries
2643 if (t->items[slot].conn.cid == 0xffffffff) {
2645 *last_item_contains_data = 0;
2658 RXDebugConnsFromCache(void *rpc_specific, int slot, void *dest,
2662 afs_status_t tst = 0;
2663 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2665 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_conn_item_t));
2675 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2680 * IN handle - an rxdebug handle for the process to be queried
2682 * IN allcons - non-zero to list all connections. If zero, only
2683 * "interesting" connections will be listed.
2685 * OUT iterationIdP - an iteration id that can be passed to
2686 * util_RXDebugConnectionsNext.
2690 * No locks are obtained or released by this function
2694 * Returns != 0 upon successful completion.
2699 util_RXDebugConnectionsBegin(rxdebugHandle_p handle, int allconns,
2700 void **iterationIdP, afs_status_p st)
2704 afs_uint32 tsupported;
2705 afs_status_t tst = 0;
2706 afs_admin_iterator_p iter;
2707 rxdebug_conn_get_p t;
2709 if (handle == NULL) {
2710 tst = ADMRXDEBUGHANDLENULL;
2711 goto fail_util_RXDebugConnectionsBegin;
2714 iter = malloc(sizeof(afs_admin_iterator_t));
2717 goto fail_util_RXDebugConnectionsBegin;
2720 if (handle->firstFlag) {
2721 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2724 goto fail_util_RXDebugConnectionsBegin;
2728 if (allconns && !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2729 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2730 goto fail_util_RXDebugConnectionsBegin;
2733 t = malloc(sizeof(rxdebug_conn_get_t));
2737 goto fail_util_RXDebugConnectionsBegin;
2740 t->allconns = allconns;
2744 (iter, (void *)t, RXDebugConnsFromServer, RXDebugConnsFromCache, NULL,
2746 goto fail_util_RXDebugConnectionsBegin;
2748 *iterationIdP = (void *)iter;
2751 fail_util_RXDebugConnectionsBegin:
2761 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2766 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2768 * OUT conn - Rxdebug information for the next connection.
2770 * OUT supportedValues - Bit mask of supported rxdebug values.
2774 * No locks are obtained or released by this function
2778 * Returns != 0 upon successful completion.
2783 util_RXDebugConnectionsNext(const void *iterationId,
2784 struct rx_debugConn *conn,
2785 afs_uint32 * supportedValues, afs_status_p st)
2788 afs_status_t tst = 0;
2789 rxdebug_conn_item_t item;
2790 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2792 if (iterationId == NULL) {
2793 tst = ADMITERATIONIDPNULL;
2794 goto fail_util_RXDebugConnectionsNext;
2798 tst = ADMRXDEBUGHANDLENULL;
2799 goto fail_util_RXDebugConnectionsNext;
2802 if (supportedValues == NULL) {
2803 tst = ADMRXDEBUGHANDLENULL;
2804 goto fail_util_RXDebugConnectionsNext;
2807 rc = IteratorNext(iter, (void *)&item, &tst);
2809 goto fail_util_RXDebugConnectionsNext;
2813 *supportedValues = item.supportedValues;
2815 fail_util_RXDebugConnectionsNext:
2825 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2829 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2833 * No locks are obtained or released by this function
2837 * Returns != 0 upon successful completion.
2842 util_RXDebugConnectionsDone(const void *iterationId, afs_status_p st)
2845 afs_status_t tst = 0;
2846 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2849 * Validate parameters
2853 tst = ADMITERATORNULL;
2854 goto fail_util_RXDebugConnectionsDone;
2857 rc = IteratorDone(iter, &tst);
2859 fail_util_RXDebugConnectionsDone:
2869 * The iterator for listing RXDebug peer
2872 typedef struct rxdebug_peer_item {
2873 struct rx_debugPeer peer;
2874 afs_uint32 supportedValues;
2875 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2877 typedef struct rxdebug_peer_get {
2878 rxdebugHandle_p handle;
2880 rxdebug_peer_item_t items[CACHED_ITEMS];
2881 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2884 RXDebugPeersFromServer(void *rpc_specific, int slot, int *last_item,
2885 int *last_item_contains_data, afs_status_p st)
2889 afs_status_t tst = 0;
2890 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2893 * Get the next entry the list of peers
2896 rx_GetServerPeers(t->handle->sock, t->handle->ipAddr,
2897 t->handle->udpPort, &t->index,
2898 t->handle->supportedStats, &t->items[slot].peer,
2899 &t->items[slot].supportedValues);
2901 tst = ADMCLIENTRXDEBUGTIMEOUT;
2902 goto fail_ListCellsRPC;
2906 * See if we've processed all the entries
2908 if (t->items[slot].peer.host == 0xffffffff) {
2910 *last_item_contains_data = 0;
2923 RXDebugPeersFromCache(void *rpc_specific, int slot, void *dest,
2927 afs_status_t tst = 0;
2928 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2930 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_peer_item_t));
2941 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
2946 * IN handle - an rxdebug handle for the process to be queried
2948 * OUT iterationIdP - an iteration id that can be passed to
2949 * util_RXDebugPeersNext.
2953 * No locks are obtained or released by this function
2957 * Returns != 0 upon successful completion.
2962 util_RXDebugPeersBegin(rxdebugHandle_p handle, void **iterationIdP,
2967 afs_uint32 tsupported;
2968 afs_status_t tst = 0;
2969 afs_admin_iterator_p iter;
2970 rxdebug_peer_get_p t;
2972 if (handle == NULL) {
2973 tst = ADMRXDEBUGHANDLENULL;
2974 goto fail_util_RXDebugPeersBegin;
2977 iter = malloc(sizeof(afs_admin_iterator_t));
2980 goto fail_util_RXDebugPeersBegin;
2983 if (handle->firstFlag) {
2984 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2987 goto fail_util_RXDebugPeersBegin;
2991 if (!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
2992 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2993 goto fail_util_RXDebugPeersBegin;
2996 t = malloc(sizeof(rxdebug_peer_get_t));
3000 goto fail_util_RXDebugPeersBegin;
3006 (iter, (void *)t, RXDebugPeersFromServer, RXDebugPeersFromCache, NULL,
3008 goto fail_util_RXDebugPeersBegin;
3010 *iterationIdP = (void *)iter;
3013 fail_util_RXDebugPeersBegin:
3022 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3026 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3028 * OUT peer - Rxdebug information for the next peer.
3030 * OUT supportedValues - Bit mask of supported rxdebug values.
3034 * No locks are obtained or released by this function
3038 * Returns != 0 upon successful completion.
3042 util_RXDebugPeersNext(const void *iterationId, struct rx_debugPeer *peer,
3043 afs_uint32 * supportedValues, afs_status_p st)
3046 afs_status_t tst = 0;
3047 rxdebug_peer_item_t item;
3048 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3050 if (iterationId == NULL) {
3051 tst = ADMITERATIONIDPNULL;
3052 goto fail_util_RXDebugPeersNext;
3056 tst = ADMRXDEBUGHANDLENULL;
3057 goto fail_util_RXDebugPeersNext;
3060 if (supportedValues == NULL) {
3061 tst = ADMRXDEBUGHANDLENULL;
3062 goto fail_util_RXDebugPeersNext;
3065 rc = IteratorNext(iter, (void *)&item, &tst);
3067 goto fail_util_RXDebugPeersNext;
3071 *supportedValues = item.supportedValues;
3073 fail_util_RXDebugPeersNext:
3082 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3086 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3090 * No locks are obtained or released by this function
3094 * Returns != 0 upon successful completion.
3099 util_RXDebugPeersDone(const void *iterationId, afs_status_p st)
3102 afs_status_t tst = 0;
3103 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3106 * Validate parameters
3110 tst = ADMITERATORNULL;
3111 goto fail_util_RXDebugPeersDone;
3114 rc = IteratorDone(iter, &tst);
3116 fail_util_RXDebugPeersDone: