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 = calloc(1, sizeof(database_server_get_t));
232 char copyCell[MAXCELLCHARS];
238 if ((cellName == NULL) || (*cellName == 0)) {
239 tst = ADMUTILCELLNAMENULL;
240 goto fail_util_DatabaseServerGetBegin;
243 if (iterationIdP == NULL) {
244 goto fail_util_DatabaseServerGetBegin;
247 if ((iter == NULL) || (serv == NULL)) {
249 goto fail_util_DatabaseServerGetBegin;
253 * Fill in the serv structure
256 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
257 if (serv->conf == NULL) {
258 tst = ADMUTILCANTOPENCELLSERVDB;
259 goto fail_util_DatabaseServerGetBegin;
263 * We must copy the cellname because afsconf_GetCellInfo
264 * actually writes over the cell name it is passed.
266 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
268 afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
271 goto fail_util_DatabaseServerGetBegin;
274 serv->total = serv->cell.numServers;
276 (iter, (void *)serv, GetDatabaseServerRPC, GetDatabaseServerFromCache,
277 NULL, DestroyDatabaseServer, &tst)) {
278 *iterationIdP = (void *)iter;
280 goto fail_util_DatabaseServerGetBegin;
284 fail_util_DatabaseServerGetBegin:
302 * util_DatabaseServerGetNext - get the next server address.
306 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
308 * OUT serverAddressP - upon successful completion contains the next
309 * server address in the cell.
313 * This function locks the iterator for the duration of its processing.
321 * Returns != 0 upon successful completion.
326 util_DatabaseServerGetNext(const void *iterationId,
327 util_databaseServerEntry_p serverP,
331 afs_status_t tst = 0;
332 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
335 tst = ADMITERATORNULL;
336 goto fail_util_DatabaseServerGetNext;
339 if (serverP == NULL) {
340 tst = ADMUTILSERVERADDRESSPNULL;
341 goto fail_util_DatabaseServerGetNext;
344 rc = IteratorNext(iter, (void *)serverP, &tst);
346 fail_util_DatabaseServerGetNext:
355 * util_DatabaseServerGetDone - stop using a database iterator.
359 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
363 * This function locks the iterator for the duration of its processing.
364 * And then destroys it before returning.
372 * Returns != 0 upon successful completion.
376 util_DatabaseServerGetDone(const void *iterationId, afs_status_p st)
379 afs_status_t tst = 0;
380 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
383 * Validate parameters
387 tst = ADMITERATORNULL;
388 goto fail_util_DatabaseServerGetDone;
391 rc = IteratorDone(iter, &tst);
393 fail_util_DatabaseServerGetDone:
402 * GetServerAddressFromName - translate a character string server name
403 * to an integer representation of an IP address.
407 * IN serverName - the character string server name in either foo.com
408 * format, or 123.12.1.1 format.
410 * OUT serverAddress - an integer that is filled with the correct address
411 * in host byte order upon successful completion.
415 * No locks are obtained or released by this function
419 * On many platforms, gethostbyname is not thread safe. Since we are
420 * only working under NT for now I'll use it directly. In future UNIX
421 * ports, a wrapper function should be written to call the correct function
422 * on the particular platform.
426 * Returns != 0 upon successful completion.
430 util_AdminServerAddressGetFromName(const char *serverName, int *serverAddress,
434 afs_status_t tst = 0;
435 struct hostent *server;
436 int part1, part2, part3, part4;
439 if ((serverName == NULL) || (*serverName == 0)) {
440 tst = ADMUTILSERVERNAMENULL;
441 goto fail_util_AdminServerAddressGetFromName;
444 if (serverAddress == NULL) {
445 tst = ADMUTILSERVERADDRESSNULL;
446 goto fail_util_AdminServerAddressGetFromName;
450 sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
451 if (num_converted == 4) {
452 *serverAddress = (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
455 server = gethostbyname(serverName);
456 if (server != NULL) {
457 memcpy((void *)serverAddress, (const void *)server->h_addr,
459 *serverAddress = ntohl(*serverAddress);
461 tst = ADMUTILCANTGETSERVERNAME;
463 goto fail_util_AdminServerAddressGetFromName;
469 fail_util_AdminServerAddressGetFromName:
479 * This file contains functions that can be used to create iterator
480 * functions within the api. I have attempted to make these functions
481 * generic so that they can be used across the admin components.
483 * The functions in this file are a generalized producer/consumer
484 * implementation. They manage access to a queue of data. The only
485 * assumption these functions make about this data is that it is
486 * stored in a queue which is implemented via an array. These functions
487 * know about the index into the array, but they know nothing about
488 * the contents of the array.
490 * The data specific functions you implement will have to create some
491 * data specific storage structure that will have an array
492 * of size CACHED_ITEMS data items. This structure will also need to
493 * store any necessary parameters/state variables you need to issue the
494 * rpc to retrieve the next item.
496 * In order to use the generic functions, you must implement four functions
497 * for each type of data you wish to retrieve. The functions are:
499 * validate_specific_data_func - this function is handed a void pointer
500 * that points to the rpc specific data you've allocated. The function
501 * should examine the data for validity and return an appropriate error.
502 * This function is called every time the iterator is validated.
504 * destroy_specific_data_func - this function is handed a void pointer
505 * that points to the rpc specific data you've allocated. It should
506 * destroy any components of the specific data as required and then
507 * return. The void pointer is free'd by the generic functions.
509 * get_cached_data_func - this function is handed a void pointer
510 * that points to the rpc specific data you've allocated, an index
511 * into the cache of the item to be copied to the caller, and a void
512 * pointer where the cache item should be copied.
514 * make_rpc_func - this function is handed a void pointer that points
515 * to the rpc specific data you've allocated, an index into the cache
516 * of the item to be filled with the next retrieved item, and an int
517 * pointer that should be set to 1 if there are no more items to be
518 * retrieved. The assumption made by the generic functions is that
519 * the last_item status requires an individual rpc - the data isn't
520 * piggybacked on the last data item.
524 * IteratorDelete - delete an iterator.
528 * IN interator - the iterator to delete.
532 * No locks are held by this function.
536 * Returns != 0 upon successful completion.
540 IteratorDelete(afs_admin_iterator_p iter, afs_status_p st)
543 afs_status_t tst = 0;
545 if (pthread_mutex_destroy(&iter->mutex)) {
546 tst = ADMMUTEXDESTROY;
547 goto fail_IteratorDelete;
549 if (pthread_cond_destroy(&iter->add_item)) {
550 tst = ADMCONDDESTROY;
551 goto fail_IteratorDelete;
553 if (pthread_cond_destroy(&iter->remove_item)) {
554 tst = ADMCONDDESTROY;
555 goto fail_IteratorDelete;
558 if (iter->destroy_specific != NULL) {
559 iter->destroy_specific(iter->rpc_specific, &tst);
561 free(iter->rpc_specific);
574 * DataGet - the background thread that is spawned for every
575 * IteratorBegin call that is successful. This thread tries
576 * to fetch the data from the server ahead of the
577 * IteratorNext calls.
581 * IN arg - the address of the iterator structure to be used for this
586 * The iterator mutex is used by this function to protect elements
587 * of the iterator structure.
591 * Returns != 0 upon successful completion.
597 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
599 afs_status_t tst = 0;
600 int mutex_locked = 0;
602 int last_item_contains_data = 0;
604 if (pthread_mutex_lock(&iter->mutex)) {
605 iter->st = ADMMUTEXLOCK;
614 * Check to see if there's room for this datum. If not, wait
615 * on the consumer to free up another slot.
618 while (iter->cache_slots_used == CACHED_ITEMS) {
619 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
620 iter->st = ADMCONDWAIT;
626 * Check to see if someone called Done and terminated the request.
627 * We could have gone to sleep above when the buffer was full and
628 * instead of being awoken because another slot is open, we were
629 * awoken because the request was terminated.
632 if (iter->request_terminated) {
636 if (pthread_mutex_unlock(&iter->mutex)) {
637 iter->st = ADMMUTEXUNLOCK;
644 * Make an rpc without holding the iter mutex
645 * We reference an item in the principal cache here without
646 * holding the mutex. This is safe because:
647 * 1. The iter structure is ref counted and won't be deleted
648 * from underneath us.
649 * 2. cache_queue_tail is always one item ahead of the consumer
650 * thread so we are the only thread accessing this member.
653 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail, &last_item,
654 &last_item_contains_data, &tst);
656 if (pthread_mutex_lock(&iter->mutex)) {
657 iter->st = ADMMUTEXLOCK;
664 * Check to see if someone called Done and terminated the request
667 if (iter->request_terminated) {
672 * Check the rc of the rpc, and see if there are no more items
682 * Check to see if this is the last item produced by the rpc.
683 * If it isn't, add the item to the cache and proceed.
684 * If it is, check to see if the last item contains valid data.
685 * If it contains valid data, we need to add it to our cache.
686 * If it doesn't, we mark the iterator as complete.
689 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
690 iter->cache_queue_tail =
691 (iter->cache_queue_tail + 1) % CACHED_ITEMS;
692 iter->cache_slots_used++;
695 iter->st = ADMITERATORDONE;
696 iter->done_iterating = 1;
698 * There's a small chance that the consumer emptied the
699 * cache queue while we were making the last rpc and has
700 * since gone to sleep waiting for more data. In this case
701 * there will never be more data so we signal him here.
703 pthread_cond_signal(&iter->add_item);
709 * If the cache was empty and we just added another item, signal
713 if (iter->cache_slots_used == 1) {
714 if (pthread_cond_signal(&iter->add_item)) {
715 iter->st = ADMCONDSIGNAL;
725 * If we are exiting with an error, signal the consumer in the event
726 * they were waiting for us to produce more data
730 pthread_cond_signal(&iter->add_item);
734 pthread_mutex_unlock(&iter->mutex);
741 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
745 * IN interator - the interator to be verified.
749 * We assume the iter->mutex lock is already held.
753 * Returns != 0 upon successful completion.
757 IsValidIterator(const afs_admin_iterator_p iterator, afs_status_p st)
760 afs_status_t tst = 0;
763 * Validate input parameters
766 if (iterator == NULL) {
767 tst = ADMITERATORNULL;
768 goto fail_IsValidIterator;
771 if ((iterator->begin_magic != BEGIN_MAGIC)
772 || (iterator->end_magic != END_MAGIC)) {
773 tst = ADMITERATORBADMAGICNULL;
774 goto fail_IsValidIterator;
777 if (iterator->is_valid == 0) {
778 tst = ADMITERATORINVALID;
779 goto fail_IsValidIterator;
783 * Call the iterator specific validation function
786 if (iterator->validate_specific != NULL) {
787 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
788 goto fail_IsValidIterator;
793 fail_IsValidIterator:
802 * IteratorNext - return the next datum in an interator.
806 * IN interator - the iterator containing the data.
808 * IN dest - the address where the data should be copied.
812 * Lock the iterator upon entry, and hold it during the duration of this
817 * Returns != 0 upon successful completion.
821 IteratorNext(afs_admin_iterator_p iter, void *dest, afs_status_p st)
824 afs_status_t tst = 0;
828 * We have to lock the iterator before we validate it
831 if (pthread_mutex_lock(&iter->mutex)) {
833 goto fail_IteratorNext;
838 if (!IsValidIterator(iter, &tst)) {
839 goto fail_IteratorNext;
842 if (iter->request_terminated == 1) {
843 tst = ADMITERATORTERMINATED;
844 goto fail_IteratorNext;
847 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
849 goto fail_IteratorNext;
853 * Check to see if there are any queue'd items. If not, wait here
854 * until signalled by the producer.
857 while (iter->cache_slots_used == 0) {
860 * Maybe the producer experienced an rpc failure.
863 if ((!iter->done_iterating) && (iter->st != 0)) {
865 goto fail_IteratorNext;
869 * Maybe there are no queue'd items because the producer is done
872 if (iter->done_iterating) {
874 goto fail_IteratorNext;
877 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
879 goto fail_IteratorNext;
884 * Copy the next cached item and update the cached item count
885 * and the index into the cache array
889 get_cached_data(iter->rpc_specific, iter->cache_queue_head, dest,
891 goto fail_IteratorNext;
894 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
895 iter->cache_slots_used--;
898 * If the cache was full before we removed the item above, the
899 * producer may have been waiting for us to remove an item.
900 * Signal the producer letting him know that we've opened a slot
904 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
905 if (pthread_cond_signal(&iter->remove_item)) {
907 goto fail_IteratorNext;
915 if (locked_iter == 1) {
916 pthread_mutex_unlock(&iter->mutex);
926 * IteratorDone - mark the iterator done.
930 * IN interator - the iterator to mark done.
934 * Lock the iterator upon entry, and hold it during the duration of this
939 * Returns != 0 upon successful completion.
943 IteratorDone(afs_admin_iterator_p iter, afs_status_p st)
946 afs_status_t tst = 0;
947 int mutex_locked = 1;
949 if (pthread_mutex_lock(&iter->mutex)) {
951 goto fail_IteratorDone;
957 if (!IsValidIterator(iter, &tst)) {
958 goto fail_IteratorDone;
963 * Depending upon the status of the background worker thread,
964 * we can either join with him immediately (if we know he has
965 * terminated), or we need to tell him the request has been
966 * terminated and then join with him.
969 if (!iter->done_iterating) {
970 iter->request_terminated = 1;
971 iter->cache_slots_used = 0;
972 pthread_cond_signal(&iter->remove_item);
976 * We have to unlock the mutex to allow the background thread to
980 if (pthread_mutex_unlock(&iter->mutex)) {
981 tst = ADMMUTEXUNLOCK;
982 goto fail_IteratorDone;
985 if (iter->make_rpc != NULL) {
986 if (pthread_join(iter->bg_worker, (void **)0)) {
988 goto fail_IteratorDone;
993 * We don't relock the mutex here since we are the only thread
994 * that has access to the iter now
997 rc = IteratorDelete(iter, &tst);
1003 pthread_mutex_unlock(&iter->mutex);
1013 * IteratorInit - initialize an iterator.
1017 * IN interator - the iterator to initialize.
1021 * No locks are held by this function.
1025 * Returns != 0 upon successful completion.
1029 IteratorInit(afs_admin_iterator_p iter, void *rpc_specific,
1030 make_rpc_func make_rpc, get_cached_data_func get_cached_data,
1031 validate_specific_data_func validate_specific_data,
1032 destroy_specific_data_func destroy_specific_data,
1036 afs_status_t tst = 0;
1037 int mutex_inited = 0;
1038 int add_item_cond_inited = 0;
1039 int remove_item_cond_inited = 0;
1042 tst = ADMITERATORNULL;
1043 goto fail_IteratorInit;
1046 if (rpc_specific == NULL) {
1047 tst = ADMITERATORRPCSPECIFICNULL;
1048 goto fail_IteratorInit;
1052 * Initialize the iterator structure
1054 iter->begin_magic = BEGIN_MAGIC;
1055 iter->end_magic = END_MAGIC;
1057 iter->cache_slots_used = 0;
1058 iter->done_iterating = 0;
1059 iter->request_terminated = 0;
1060 iter->st = AFS_STATUS_OK;
1061 iter->cache_queue_head = 0;
1062 iter->cache_queue_tail = 0;
1063 iter->cache_slots_used = 0;
1064 iter->rpc_specific = rpc_specific;
1065 iter->make_rpc = make_rpc;
1066 iter->get_cached_data = get_cached_data;
1067 iter->validate_specific = validate_specific_data;
1068 iter->destroy_specific = destroy_specific_data;
1070 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *)0)) {
1072 goto fail_IteratorInit;
1077 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *)0)) {
1079 goto fail_IteratorInit;
1081 add_item_cond_inited = 1;
1084 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *)0)) {
1086 goto fail_IteratorInit;
1088 remove_item_cond_inited = 1;
1092 * Create a worker thread that will begin to query the server
1093 * and cache responses.
1096 if (iter->make_rpc != NULL) {
1097 pthread_attr_t tattr;
1099 if (pthread_attr_init(&tattr)) {
1100 tst = ADMTHREADATTRINIT;
1101 goto fail_IteratorInit;
1104 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1105 tst = ADMTHREADATTRSETDETACHSTATE;
1106 goto fail_IteratorInit;
1109 if (pthread_create(&iter->bg_worker, &tattr, DataGet, (void *)iter)) {
1110 tst = ADMTHREADCREATE;
1111 goto fail_IteratorInit;
1120 pthread_mutex_destroy(&iter->mutex);
1122 if (remove_item_cond_inited) {
1123 pthread_cond_destroy(&iter->remove_item);
1125 if (add_item_cond_inited) {
1126 pthread_cond_destroy(&iter->add_item);
1137 CellHandleIsValid(const void *cellHandle, afs_status_p st)
1140 afs_status_t tst = 0;
1141 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1144 * Validate input parameters
1147 if (c_handle == NULL) {
1148 tst = ADMCLIENTCELLHANDLENULL;
1149 goto fail_CellHandleIsValid;
1152 if ((c_handle->begin_magic != BEGIN_MAGIC)
1153 || (c_handle->end_magic != END_MAGIC)) {
1154 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1155 goto fail_CellHandleIsValid;
1158 if (c_handle->is_valid == 0) {
1159 tst = ADMCLIENTCELLINVALID;
1160 goto fail_CellHandleIsValid;
1164 fail_CellHandleIsValid:
1173 * The iterator functions and data for the rpc statistic retrieval functions
1176 typedef struct rpc_stat_get {
1177 afs_uint32 clock_sec;
1178 afs_uint32 clock_usec;
1181 afs_uint32 clientVersion;
1182 afs_uint32 serverVersion;
1183 struct rpcStats stat_list;
1184 afs_RPCStats_t stats[CACHED_ITEMS];
1185 afs_uint32 *pointer;
1186 } rpc_stat_get_t, *rpc_stat_get_p;
1189 UnmarshallRPCStats(afs_uint32 serverVersion, afs_uint32 ** ptrP,
1193 unsigned int hi, lo;
1196 * Server must always match lower versions. We are version 1.
1199 s->stats_v1.remote_peer = *(ptr++);
1200 s->stats_v1.remote_port = *(ptr++);
1201 s->stats_v1.remote_is_server = *(ptr++);
1202 s->stats_v1.interfaceId = *(ptr++);
1203 s->stats_v1.func_total = *(ptr++);
1204 s->stats_v1.func_index = *(ptr++);
1207 s->stats_v1.invocations = ((afs_uint64) hi << 32) + lo;
1210 s->stats_v1.bytes_sent = ((afs_uint64) hi << 32) + lo;
1213 s->stats_v1.bytes_rcvd = ((afs_uint64) hi << 32) + lo;
1214 s->stats_v1.queue_time_sum.sec = *(ptr++);
1215 s->stats_v1.queue_time_sum.usec = *(ptr++);
1216 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1217 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1218 s->stats_v1.queue_time_min.sec = *(ptr++);
1219 s->stats_v1.queue_time_min.usec = *(ptr++);
1220 s->stats_v1.queue_time_max.sec = *(ptr++);
1221 s->stats_v1.queue_time_max.usec = *(ptr++);
1222 s->stats_v1.execution_time_sum.sec = *(ptr++);
1223 s->stats_v1.execution_time_sum.usec = *(ptr++);
1224 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1225 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1226 s->stats_v1.execution_time_min.sec = *(ptr++);
1227 s->stats_v1.execution_time_min.usec = *(ptr++);
1228 s->stats_v1.execution_time_max.sec = *(ptr++);
1229 s->stats_v1.execution_time_max.usec = *(ptr++);
1234 GetRPCStatsRPC(void *rpc_specific, int slot, int *last_item,
1235 int *last_item_contains_data, afs_status_p st)
1238 afs_status_t tst = 0;
1239 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1241 t->stats[slot].clientVersion = t->clientVersion;
1242 t->stats[slot].serverVersion = t->serverVersion;
1243 t->stats[slot].statCount = t->total;
1246 * If the server stat version is greater than or equal to my version
1247 * number, it is required to return the values in the client's current
1251 UnmarshallRPCStats(t->serverVersion, &t->pointer, &t->stats[slot].s);
1256 * See if we've processed all the entries
1259 if (t->index == t->total) {
1261 *last_item_contains_data = 1;
1272 GetRPCStatsFromCache(void *rpc_specific, int slot, void *dest,
1276 afs_status_t tst = 0;
1277 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1279 memcpy(dest, (const void *)&stat->stats[slot], sizeof(afs_RPCStats_t));
1289 DestroyRPCStats(void *rpc_specific, afs_status_p st)
1292 afs_status_t tst = 0;
1293 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1295 if (stat->stat_list.rpcStats_val != NULL) {
1296 free(stat->stat_list.rpcStats_val);
1307 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1311 * IN conn - an rx connection to the process to be queried
1313 * IN rpc - the function to call to make the actual rpc
1315 * OUT iterationIdP - an iteration id that can be passed to
1316 * util_RPCStatsGetNext to get the next rpc stat
1320 * No locks are obtained or released by this function
1324 * Returns != 0 upon successful completion.
1329 util_RPCStatsGetBegin(struct rx_connection *conn,
1330 int (*rpc) (struct rx_connection *,
1331 afs_uint32, afs_uint32 *,
1332 afs_uint32 *, afs_uint32 *,
1333 afs_uint32 *, struct rpcStats *),
1334 void **iterationIdP, afs_status_p st)
1337 afs_status_t tst = 0;
1338 afs_admin_iterator_p iter =
1339 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1340 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1343 tst = ADMRXCONNNULL;
1344 goto fail_util_RPCStatsGetBegin;
1348 tst = ADMRPCPTRNULL;
1349 goto fail_util_RPCStatsGetBegin;
1352 if (iterationIdP == NULL) {
1353 tst = ADMITERATIONIDPNULL;
1354 goto fail_util_RPCStatsGetBegin;
1357 if ((iter == NULL) || (stat == NULL)) {
1359 goto fail_util_RPCStatsGetBegin;
1362 stat->stat_list.rpcStats_len = 0;
1363 stat->stat_list.rpcStats_val = 0;
1365 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1368 (*rpc) (conn, stat->clientVersion, &stat->serverVersion,
1369 &stat->clock_sec, &stat->clock_usec, &stat->total,
1373 goto fail_util_RPCStatsGetBegin;
1377 * If there are no statistics, just mark the iterator done and
1381 if (stat->stat_list.rpcStats_len == 0) {
1382 stat->pointer = NULL;
1383 if (!IteratorInit(iter, (void *)stat, NULL, NULL, NULL, NULL, &tst)) {
1384 goto fail_util_RPCStatsGetBegin;
1386 iter->done_iterating = 1;
1387 iter->st = ADMITERATORDONE;
1389 stat->pointer = stat->stat_list.rpcStats_val;
1391 (iter, (void *)stat, GetRPCStatsRPC, GetRPCStatsFromCache, NULL,
1392 DestroyRPCStats, &tst)) {
1393 goto fail_util_RPCStatsGetBegin;
1396 *iterationIdP = (void *)iter;
1399 fail_util_RPCStatsGetBegin:
1417 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1421 * IN iterationId - an iterator previously returned by
1422 * util_RPCStatsGetBegin.
1424 * OUT stats - upon successful completion contains the next set of stats
1429 * No locks are obtained or released by this function
1433 * Returns != 0 upon successful completion.
1438 util_RPCStatsGetNext(const void *iterationId, afs_RPCStats_p stats,
1442 afs_status_t tst = 0;
1443 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1445 if (iterationId == NULL) {
1446 tst = ADMITERATIONIDPNULL;
1447 goto fail_util_RPCStatsGetNext;
1450 if (stats == NULL) {
1451 tst = ADMUTILRPCSTATSNULL;
1452 goto fail_util_RPCStatsGetNext;
1455 rc = IteratorNext(iter, (void *)stats, &tst);
1457 fail_util_RPCStatsGetNext:
1466 * util_RPCStatsGetDone - finish using a stats iterator
1470 * IN iterationId - an iterator previously returned by
1471 * util_RPCStatsGetBegin.
1475 * No locks are obtained or released by this function
1479 * Returns != 0 upon successful completion.
1484 util_RPCStatsGetDone(const void *iterationId, afs_status_p st)
1487 afs_status_t tst = 0;
1488 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1490 if (iterationId == NULL) {
1491 tst = ADMITERATIONIDPNULL;
1492 goto fail_util_RPCStatsGetDone;
1495 rc = IteratorDone(iter, &tst);
1497 fail_util_RPCStatsGetDone:
1506 * util_RPCStatsStateGet - get the current state of rpc stat collection
1510 * IN conn - an rx connection to the process to be queried
1512 * IN rpc - the function to call to make the actual rpc
1514 * OUT state - the rpc stat collection state.
1518 * No locks are obtained or released by this function
1522 * Returns != 0 upon successful completion.
1527 util_RPCStatsStateGet(struct rx_connection *conn,
1528 int (*rpc) (struct rx_connection *,
1529 afs_RPCStatsState_p),
1530 afs_RPCStatsState_p state, afs_status_p st)
1533 afs_status_t tst = 0;
1536 tst = ADMRXCONNNULL;
1537 goto fail_util_RPCStatsStateGet;
1541 tst = ADMRPCPTRNULL;
1542 goto fail_util_RPCStatsStateGet;
1545 if (state == NULL) {
1546 tst = ADMRPCSTATENULL;
1547 goto fail_util_RPCStatsStateGet;
1550 tst = (*rpc) (conn, state);
1556 fail_util_RPCStatsStateGet:
1565 * util_RPCStatsStateEnable - enable rpc stat collection
1570 * IN conn - an rx connection to the process to be modified
1572 * IN rpc - the function to call to make the actual rpc
1576 * No locks are obtained or released by this function
1580 * Returns != 0 upon successful completion.
1585 util_RPCStatsStateEnable(struct rx_connection *conn,
1586 int (*rpc) (struct rx_connection *),
1590 afs_status_t tst = 0;
1593 tst = ADMRXCONNNULL;
1594 goto fail_util_RPCStatsStateEnable;
1598 tst = ADMRPCPTRNULL;
1599 goto fail_util_RPCStatsStateEnable;
1602 tst = (*rpc) (conn);
1608 fail_util_RPCStatsStateEnable:
1617 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1622 * IN conn - an rx connection to the process to be modified
1624 * IN rpc - the function to call to make the actual rpc
1628 * No locks are obtained or released by this function
1632 * Returns != 0 upon successful completion.
1637 util_RPCStatsStateDisable(struct rx_connection *conn,
1638 int (*rpc) (struct rx_connection *),
1642 afs_status_t tst = 0;
1645 tst = ADMRXCONNNULL;
1646 goto fail_util_RPCStatsStateDisable;
1650 tst = ADMRPCPTRNULL;
1651 goto fail_util_RPCStatsStateDisable;
1654 tst = (*rpc) (conn);
1660 fail_util_RPCStatsStateDisable:
1669 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1670 * collection at a server
1674 * IN conn - an rx connection to the process to be modified
1676 * IN rpc - the function to call to make the actual rpc
1678 * IN flag - a flag containing the fields to be cleared
1683 * No locks are obtained or released by this function
1687 * Returns != 0 upon successful completion.
1692 util_RPCStatsClear(struct rx_connection *conn,
1693 int (*rpc) (struct rx_connection *,
1694 afs_RPCStatsClearFlag_t),
1695 afs_RPCStatsClearFlag_t flag, afs_status_p st)
1698 afs_status_t tst = 0;
1701 tst = ADMRXCONNNULL;
1702 goto fail_util_RPCStatsClear;
1706 tst = ADMRPCPTRNULL;
1707 goto fail_util_RPCStatsClear;
1710 tst = (*rpc) (conn, flag);
1716 fail_util_RPCStatsClear:
1725 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1729 * IN conn - an rx connection to the process to be modified
1731 * OUT version - the version of rpc stat collection at the remote process
1735 * No locks are obtained or released by this function
1739 * Returns != 0 upon successful completion.
1744 util_RPCStatsVersionGet(struct rx_connection *conn,
1745 afs_RPCStatsVersion_p version, afs_status_p st)
1748 afs_status_t tst = 0;
1751 tst = ADMRXCONNNULL;
1752 goto fail_util_RPCStatsVersionGet;
1755 if (version == NULL) {
1756 tst = ADMRPCVERSIONNULL;
1757 goto fail_util_RPCStatsVersionGet;
1760 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1766 fail_util_RPCStatsVersionGet:
1775 * The iterator for listing CM server preferences
1778 typedef struct cm_srvr_pref_get {
1779 struct rx_connection *conn;
1781 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1782 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1785 GetServerPrefsRPC(void *rpc_specific, int slot, int *last_item,
1786 int *last_item_contains_data, afs_status_p st)
1789 afs_status_t tst = 0;
1790 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1793 * Get the next entry in the list of server preferences.
1796 RXAFSCB_GetServerPrefs(t->conn, t->index, &t->srvrPrefs[slot].ipAddr,
1797 &t->srvrPrefs[slot].ipRank);
1799 goto fail_GetServerPrefsRPC;
1803 * See if we've processed all the entries
1805 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1807 *last_item_contains_data = 0;
1813 fail_GetServerPrefsRPC:
1822 GetServerPrefsFromCache(void *rpc_specific, int slot, void *dest,
1826 afs_status_t tst = 0;
1827 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1829 memcpy(dest, (const void *)&prefs->srvrPrefs[slot],
1830 sizeof(afs_CMServerPref_t));
1840 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1844 * IN conn - an rx connection to the process to be queried
1846 * OUT iterationIdP - an iteration id that can be passed to
1847 * util_CMGetServerPrefsNext to get the next server preference
1851 * No locks are obtained or released by this function
1855 * Returns != 0 upon successful completion.
1860 util_CMGetServerPrefsBegin(struct rx_connection *conn, void **iterationIdP,
1864 afs_status_t tst = 0;
1865 afs_admin_iterator_p iter;
1866 cm_srvr_pref_get_p pref;
1869 tst = ADMRXCONNNULL;
1870 goto fail_util_CMGetServerPrefsBegin;
1873 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1876 goto fail_util_CMGetServerPrefsBegin;
1879 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1883 goto fail_util_CMGetServerPrefsBegin;
1889 (iter, (void *)pref, GetServerPrefsRPC, GetServerPrefsFromCache, NULL,
1893 goto fail_util_CMGetServerPrefsBegin;
1895 *iterationIdP = (void *)iter;
1898 fail_util_CMGetServerPrefsBegin:
1907 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1912 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1914 * OUT prefs - Next entry in cache manager server preferences.
1918 * No locks are obtained or released by this function
1922 * Returns != 0 upon successful completion.
1927 util_CMGetServerPrefsNext(const void *iterationId, afs_CMServerPref_p prefs,
1931 afs_status_t tst = 0;
1932 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1934 if (iterationId == NULL) {
1935 tst = ADMITERATIONIDPNULL;
1936 goto fail_util_CMGetServerPrefsNext;
1939 rc = IteratorNext(iter, (void *)prefs, &tst);
1941 fail_util_CMGetServerPrefsNext:
1950 * util_CMGetServerPrefsDone - Finish listing cache manager server
1955 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1959 * No locks are obtained or released by this function
1963 * Returns != 0 upon successful completion.
1968 util_CMGetServerPrefsDone(const void *iterationId, afs_status_p st)
1971 afs_status_t tst = 0;
1972 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1974 if (iterationId == NULL) {
1975 tst = ADMITERATIONIDPNULL;
1976 goto fail_util_CMGetServerPrefsDone;
1979 rc = IteratorDone(iter, &tst);
1982 fail_util_CMGetServerPrefsDone:
1991 * The iterator for listing CM CellServDB
1994 typedef struct cm_list_cell_get {
1995 struct rx_connection *conn;
1997 afs_CMListCell_t cell[CACHED_ITEMS];
1998 } cm_list_cell_get_t, *cm_list_cell_get_p;
2001 ListCellsRPC(void *rpc_specific, int slot, int *last_item,
2002 int *last_item_contains_data, afs_status_p st)
2005 afs_status_t tst = 0;
2006 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2012 * Get the next entry in the CellServDB.
2014 name = t->cell[slot].cellname;
2015 sl.serverList_len = 0;
2016 sl.serverList_val = NULL;
2017 memset(t->cell[slot].serverAddr, 0, sizeof(afs_int32)*UTIL_MAX_CELL_HOSTS);
2019 RXAFSCB_GetCellServDB(t->conn, t->index, &name, &sl);
2021 goto fail_ListCellsRPC;
2023 strcpy(t->cell[slot].cellname, name);
2024 if (sl.serverList_val) {
2025 for (n=0; n<sl.serverList_len && n<UTIL_MAX_CELL_HOSTS; n++) {
2026 t->cell[slot].serverAddr[n] = sl.serverList_val[n];
2028 xdr_free((xdrproc_t) xdr_serverList, &sl);
2032 * See if we've processed all the entries
2034 if (strlen(t->cell[slot].cellname) == 0) {
2036 *last_item_contains_data = 0;
2051 ListCellsFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2054 afs_status_t tst = 0;
2055 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2057 memcpy(dest, (const void *)&cell->cell[slot], sizeof(afs_CMListCell_t));
2067 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2071 * IN conn - an rx connection to the process to be queried
2073 * OUT iterationIdP - an iteration id that can be passed to
2074 * util_CMListCellsNext to get the next cell
2078 * No locks are obtained or released by this function
2082 * Returns != 0 upon successful completion.
2087 util_CMListCellsBegin(struct rx_connection *conn, void **iterationIdP,
2091 afs_status_t tst = 0;
2092 afs_admin_iterator_p iter;
2093 cm_list_cell_get_p cell;
2096 tst = ADMRXCONNNULL;
2097 goto fail_util_CMListCellsBegin;
2100 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2103 goto fail_util_CMListCellsBegin;
2106 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2110 goto fail_util_CMListCellsBegin;
2116 (iter, (void *)cell, ListCellsRPC, ListCellsFromCache, NULL, NULL,
2120 goto fail_util_CMListCellsBegin;
2122 *iterationIdP = (void *)iter;
2125 fail_util_CMListCellsBegin:
2134 * util_CMListCellsNext - Get next entry in cache manager cells
2138 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2140 * OUT cell - Next entry in cache manager cells.
2144 * No locks are obtained or released by this function
2148 * Returns != 0 upon successful completion.
2153 util_CMListCellsNext(const void *iterationId, afs_CMListCell_p cell,
2157 afs_status_t tst = 0;
2158 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2160 if (iterationId == NULL) {
2161 tst = ADMITERATIONIDPNULL;
2162 goto fail_util_CMListCellsNext;
2165 rc = IteratorNext(iter, (void *)cell, &tst);
2167 fail_util_CMListCellsNext:
2176 * util_CMListCellsDone - Finish listing cache manager cells
2180 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2184 * No locks are obtained or released by this function
2188 * Returns != 0 upon successful completion.
2193 util_CMListCellsDone(const void *iterationId, afs_status_p st)
2196 afs_status_t tst = 0;
2197 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2199 if (iterationId == NULL) {
2200 tst = ADMITERATIONIDPNULL;
2201 goto fail_util_CMListCellsDone;
2204 rc = IteratorDone(iter, &tst);
2207 fail_util_CMListCellsDone:
2216 * util_CMLocalCell - Get the name of the cache manager's local cell.
2220 * IN conn - an rx connection to the process to be queried
2222 * OUT cellName - the name of the cache manager's local cell.
2226 * No locks are obtained or released by this function
2230 * Returns != 0 upon successful completion.
2235 util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
2239 afs_status_t tst = 0;
2240 afs_CMCellName_p name;
2243 tst = ADMRXCONNNULL;
2244 goto fail_util_CMLocalCell;
2247 if (cellName == NULL) {
2248 tst = ADMCLIENTCMCELLNAMENULL;
2249 goto fail_util_CMLocalCell;
2253 tst = RXAFSCB_GetLocalCell(conn, &name);
2259 fail_util_CMLocalCell:
2268 UnmarshallCMClientConfig(afs_uint32 serverVersion, afs_uint32 * ptr,
2269 afs_ClientConfigUnion_p config)
2272 * We currently only support version 1.
2274 config->config_v1.nChunkFiles = *(ptr++);
2275 config->config_v1.nStatCaches = *(ptr++);
2276 config->config_v1.nDataCaches = *(ptr++);
2277 config->config_v1.nVolumeCaches = *(ptr++);
2278 config->config_v1.firstChunkSize = *(ptr++);
2279 config->config_v1.otherChunkSize = *(ptr++);
2280 config->config_v1.cacheSize = *(ptr++);
2281 config->config_v1.setTime = *(ptr++);
2282 config->config_v1.memCache = *(ptr++);
2286 * util_CMClientConfig - Get the cache manager's configuration parameters.
2290 * IN conn - an rx connection to the process to be queried
2292 * OUT config - the cache manager's configuration parameters.
2296 * No locks are obtained or released by this function
2300 * Returns != 0 upon successful completion.
2305 util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
2309 afs_status_t tst = 0;
2310 afs_uint32 allocbytes;
2311 struct cacheConfig tconfig;
2314 tst = ADMRXCONNNULL;
2315 goto fail_util_CMClientConfig;
2318 if (config == NULL) {
2319 tst = ADMCLIENTCMCELLNAMENULL;
2320 goto fail_util_CMClientConfig;
2323 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2324 tconfig.cacheConfig_val = NULL;
2325 tconfig.cacheConfig_len = 0;
2327 RXAFSCB_GetCacheConfig(conn, config->clientVersion,
2328 &config->serverVersion, &allocbytes, &tconfig);
2331 goto fail_util_CMClientConfig;
2334 UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
2337 free(tconfig.cacheConfig_val);
2339 fail_util_CMClientConfig:
2348 * util_RXDebugVersion - Get the rxdebug version string.
2352 * IN handle - an rxdebug handle for the process to be queried.
2354 * OUT version - the rxdebug version string.
2358 * No locks are obtained or released by this function
2362 * Returns != 0 upon successful completion.
2367 util_RXDebugVersion(rxdebugHandle_p handle, rxdebugVersion_p version,
2371 afs_status_t tst = 0;
2374 if (handle == NULL) {
2375 tst = ADMRXDEBUGHANDLENULL;
2376 goto fail_util_RXDebugVersion;
2379 if (version == NULL) {
2380 tst = ADMRXDEBUGVERSIONNULL;
2381 goto fail_util_RXDebugVersion;
2385 rx_GetServerVersion(handle->sock, handle->ipAddr, handle->udpPort,
2386 UTIL_MAX_RXDEBUG_VERSION_LEN, version);
2388 tst = ADMCLIENTRXDEBUGTIMEOUT;
2389 goto fail_util_RXDebugVersion;
2394 fail_util_RXDebugVersion:
2403 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2408 * IN handle - an rxdebug handle for the process to be queried.
2410 * OUT supportedStats - bit mask with supported rxstats.
2414 * No locks are obtained or released by this function
2418 * Returns != 0 upon successful completion.
2423 util_RXDebugSupportedStats(rxdebugHandle_p handle,
2424 afs_uint32 * supportedStats, afs_status_p st)
2427 afs_status_t tst = 0;
2428 struct rx_debugStats tstats;
2430 if (handle == NULL) {
2431 tst = ADMRXDEBUGHANDLENULL;
2432 goto fail_util_RXDebugSupportedStats;
2435 if (supportedStats == NULL) {
2436 tst = ADMRXDEBUGSTATSNULL;
2437 goto fail_util_RXDebugSupportedStats;
2440 if (handle->firstFlag) {
2441 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2443 goto fail_util_RXDebugSupportedStats;
2447 *supportedStats = handle->supportedStats;
2450 fail_util_RXDebugSupportedStats:
2460 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2464 * IN handle - an rxdebug handle for the process to be queried.
2466 * OUT stats - Basic rxdebug statistics for the process.
2470 * No locks are obtained or released by this function
2474 * Returns != 0 upon successful completion.
2479 util_RXDebugBasicStats(rxdebugHandle_p handle, struct rx_debugStats *stats,
2483 afs_status_t tst = 0;
2486 if (handle == NULL) {
2487 tst = ADMRXDEBUGHANDLENULL;
2488 goto fail_util_RXDebugBasicStats;
2491 if (stats == NULL) {
2492 tst = ADMRXDEBUGSTATSNULL;
2493 goto fail_util_RXDebugBasicStats;
2497 rx_GetServerDebug(handle->sock, handle->ipAddr, handle->udpPort,
2498 stats, &handle->supportedStats);
2500 tst = ADMCLIENTRXDEBUGTIMEOUT;
2501 goto fail_util_RXDebugBasicStats;
2504 handle->firstFlag = 0;
2507 fail_util_RXDebugBasicStats:
2517 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2521 * IN handle - an rxdebug handle for the process to be queried.
2523 * OUT stats - Detailed rxdebug statistics for the process.
2527 * No locks are obtained or released by this function
2531 * Returns != 0 upon successful completion.
2536 util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_statistics *stats,
2537 afs_uint32 * supportedValues, afs_status_p st)
2541 afs_status_t tst = 0;
2543 afs_uint32 tsupported;
2545 if (handle == NULL) {
2546 tst = ADMRXDEBUGHANDLENULL;
2547 goto fail_util_RXDebugRxStats;
2550 if (supportedValues == NULL) {
2551 tst = ADMRXDEBUGSTATSNULL;
2552 goto fail_util_RXDebugRxStats;
2555 if (stats == NULL) {
2556 tst = ADMRXDEBUGSTATSNULL;
2557 goto fail_util_RXDebugRxStats;
2560 if (handle->firstFlag) {
2561 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2564 goto fail_util_RXDebugRxStats;
2568 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2569 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2570 goto fail_util_RXDebugRxStats;
2574 rx_GetServerStats(handle->sock, handle->ipAddr, handle->udpPort,
2575 stats, &handle->supportedStats);
2577 tst = ADMCLIENTRXDEBUGTIMEOUT;
2578 goto fail_util_RXDebugRxStats;
2583 fail_util_RXDebugRxStats:
2592 * The iterator for listing RXDebug connections
2595 typedef struct rxdebug_conn_item {
2596 struct rx_debugConn conn;
2597 afs_uint32 supportedValues;
2598 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2600 typedef struct rxdebug_conn_get {
2602 rxdebugHandle_p handle;
2604 rxdebug_conn_item_t items[CACHED_ITEMS];
2605 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2608 RXDebugConnsFromServer(void *rpc_specific, int slot, int *last_item,
2609 int *last_item_contains_data, afs_status_p st)
2613 afs_status_t tst = 0;
2614 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2617 * Get the next entry the list of connections
2620 rx_GetServerConnections(t->handle->sock, t->handle->ipAddr,
2621 t->handle->udpPort, &t->index, t->allconns,
2622 t->handle->supportedStats,
2623 &t->items[slot].conn,
2624 &t->items[slot].supportedValues);
2626 tst = ADMCLIENTRXDEBUGTIMEOUT;
2627 goto fail_ListCellsRPC;
2631 * See if we've processed all the entries
2633 if (t->items[slot].conn.cid == 0xffffffff) {
2635 *last_item_contains_data = 0;
2648 RXDebugConnsFromCache(void *rpc_specific, int slot, void *dest,
2652 afs_status_t tst = 0;
2653 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2655 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_conn_item_t));
2665 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2670 * IN handle - an rxdebug handle for the process to be queried
2672 * IN allcons - non-zero to list all connections. If zero, only
2673 * "interesting" connections will be listed.
2675 * OUT iterationIdP - an iteration id that can be passed to
2676 * util_RXDebugConnectionsNext.
2680 * No locks are obtained or released by this function
2684 * Returns != 0 upon successful completion.
2689 util_RXDebugConnectionsBegin(rxdebugHandle_p handle, int allconns,
2690 void **iterationIdP, afs_status_p st)
2694 afs_uint32 tsupported;
2695 afs_status_t tst = 0;
2696 afs_admin_iterator_p iter;
2697 rxdebug_conn_get_p t;
2699 if (handle == NULL) {
2700 tst = ADMRXDEBUGHANDLENULL;
2701 goto fail_util_RXDebugConnectionsBegin;
2704 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2707 goto fail_util_RXDebugConnectionsBegin;
2710 if (handle->firstFlag) {
2711 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2714 goto fail_util_RXDebugConnectionsBegin;
2718 if (allconns && !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2719 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2720 goto fail_util_RXDebugConnectionsBegin;
2723 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2727 goto fail_util_RXDebugConnectionsBegin;
2730 t->allconns = allconns;
2734 (iter, (void *)t, RXDebugConnsFromServer, RXDebugConnsFromCache, NULL,
2736 goto fail_util_RXDebugConnectionsBegin;
2738 *iterationIdP = (void *)iter;
2741 fail_util_RXDebugConnectionsBegin:
2751 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2756 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2758 * OUT conn - Rxdebug information for the next connection.
2760 * OUT supportedValues - Bit mask of supported rxdebug values.
2764 * No locks are obtained or released by this function
2768 * Returns != 0 upon successful completion.
2773 util_RXDebugConnectionsNext(const void *iterationId,
2774 struct rx_debugConn *conn,
2775 afs_uint32 * supportedValues, afs_status_p st)
2778 afs_status_t tst = 0;
2779 rxdebug_conn_item_t item;
2780 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2782 if (iterationId == NULL) {
2783 tst = ADMITERATIONIDPNULL;
2784 goto fail_util_RXDebugConnectionsNext;
2788 tst = ADMRXDEBUGHANDLENULL;
2789 goto fail_util_RXDebugConnectionsNext;
2792 if (supportedValues == NULL) {
2793 tst = ADMRXDEBUGHANDLENULL;
2794 goto fail_util_RXDebugConnectionsNext;
2797 rc = IteratorNext(iter, (void *)&item, &tst);
2799 goto fail_util_RXDebugConnectionsNext;
2803 *supportedValues = item.supportedValues;
2805 fail_util_RXDebugConnectionsNext:
2815 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2819 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2823 * No locks are obtained or released by this function
2827 * Returns != 0 upon successful completion.
2832 util_RXDebugConnectionsDone(const void *iterationId, afs_status_p st)
2835 afs_status_t tst = 0;
2836 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2839 * Validate parameters
2843 tst = ADMITERATORNULL;
2844 goto fail_util_RXDebugConnectionsDone;
2847 rc = IteratorDone(iter, &tst);
2849 fail_util_RXDebugConnectionsDone:
2859 * The iterator for listing RXDebug peer
2862 typedef struct rxdebug_peer_item {
2863 struct rx_debugPeer peer;
2864 afs_uint32 supportedValues;
2865 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2867 typedef struct rxdebug_peer_get {
2868 rxdebugHandle_p handle;
2870 rxdebug_peer_item_t items[CACHED_ITEMS];
2871 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2874 RXDebugPeersFromServer(void *rpc_specific, int slot, int *last_item,
2875 int *last_item_contains_data, afs_status_p st)
2879 afs_status_t tst = 0;
2880 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2883 * Get the next entry the list of peers
2886 rx_GetServerPeers(t->handle->sock, t->handle->ipAddr,
2887 t->handle->udpPort, &t->index,
2888 t->handle->supportedStats, &t->items[slot].peer,
2889 &t->items[slot].supportedValues);
2891 tst = ADMCLIENTRXDEBUGTIMEOUT;
2892 goto fail_ListCellsRPC;
2896 * See if we've processed all the entries
2898 if (t->items[slot].peer.host == 0xffffffff) {
2900 *last_item_contains_data = 0;
2913 RXDebugPeersFromCache(void *rpc_specific, int slot, void *dest,
2917 afs_status_t tst = 0;
2918 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2920 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_peer_item_t));
2931 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
2936 * IN handle - an rxdebug handle for the process to be queried
2938 * OUT iterationIdP - an iteration id that can be passed to
2939 * util_RXDebugPeersNext.
2943 * No locks are obtained or released by this function
2947 * Returns != 0 upon successful completion.
2952 util_RXDebugPeersBegin(rxdebugHandle_p handle, void **iterationIdP,
2957 afs_uint32 tsupported;
2958 afs_status_t tst = 0;
2959 afs_admin_iterator_p iter;
2960 rxdebug_peer_get_p t;
2962 if (handle == NULL) {
2963 tst = ADMRXDEBUGHANDLENULL;
2964 goto fail_util_RXDebugPeersBegin;
2967 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2970 goto fail_util_RXDebugPeersBegin;
2973 if (handle->firstFlag) {
2974 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2977 goto fail_util_RXDebugPeersBegin;
2981 if (!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
2982 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2983 goto fail_util_RXDebugPeersBegin;
2986 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
2990 goto fail_util_RXDebugPeersBegin;
2996 (iter, (void *)t, RXDebugPeersFromServer, RXDebugPeersFromCache, NULL,
2998 goto fail_util_RXDebugPeersBegin;
3000 *iterationIdP = (void *)iter;
3003 fail_util_RXDebugPeersBegin:
3012 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3016 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3018 * OUT peer - Rxdebug information for the next peer.
3020 * OUT supportedValues - Bit mask of supported rxdebug values.
3024 * No locks are obtained or released by this function
3028 * Returns != 0 upon successful completion.
3032 util_RXDebugPeersNext(const void *iterationId, struct rx_debugPeer *peer,
3033 afs_uint32 * supportedValues, afs_status_p st)
3036 afs_status_t tst = 0;
3037 rxdebug_peer_item_t item;
3038 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3040 if (iterationId == NULL) {
3041 tst = ADMITERATIONIDPNULL;
3042 goto fail_util_RXDebugPeersNext;
3046 tst = ADMRXDEBUGHANDLENULL;
3047 goto fail_util_RXDebugPeersNext;
3050 if (supportedValues == NULL) {
3051 tst = ADMRXDEBUGHANDLENULL;
3052 goto fail_util_RXDebugPeersNext;
3055 rc = IteratorNext(iter, (void *)&item, &tst);
3057 goto fail_util_RXDebugPeersNext;
3061 *supportedValues = item.supportedValues;
3063 fail_util_RXDebugPeersNext:
3072 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3076 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3080 * No locks are obtained or released by this function
3084 * Returns != 0 upon successful completion.
3089 util_RXDebugPeersDone(const void *iterationId, afs_status_p st)
3092 afs_status_t tst = 0;
3093 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3096 * Validate parameters
3100 tst = ADMITERATORNULL;
3101 goto fail_util_RXDebugPeersDone;
3104 rc = IteratorDone(iter, &tst);
3106 fail_util_RXDebugPeersDone: