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>
16 #include <afs/afs_Admin.h>
19 #include <afs/afs_Admin.h>
20 #include "afs_AdminInternal.h"
21 #include <afs/pthread_glock.h>
22 #include <afs/cellconfig.h>
23 #include <afs/dirpath.h>
24 #include <afs/com_err.h>
25 #include <afs/kautils.h>
27 #include <afs/vlserver.h>
28 #include <afs/pterror.h>
29 #include <afs/bnode.h>
30 #include <afs/volser.h>
31 #include <afs/afscbint.h>
33 #include <rx/rxstat.h>
35 # include <winsock2.h>
36 # include <afs/krb5_nt.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.h>
44 #include "afs_utilAdmin.h"
47 * AIX 4.2 has PTHREAD_CREATE_UNDETACHED and not PTHREAD_CREATE_JOINABLE
49 * This fix should be done more centrally, but there's no time right now.
51 #if defined(AFS_AIX_ENV)
52 # if !defined(PTHREAD_CREATE_JOINABLE) && defined(PTHREAD_CREATE_UNDETACHED)
53 # define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
57 #define ERRCODE_RANGE 8
58 static pthread_once_t error_init_once = PTHREAD_ONCE_INIT;
59 static int error_init_done;
65 initialize_KA_error_table();
66 initialize_RXK_error_table();
67 initialize_KTC_error_table();
68 initialize_ACFG_error_table();
69 initialize_CMD_error_table();
70 initialize_VL_error_table();
71 initialize_PT_error_table();
72 initialize_BZ_error_table();
73 initialize_U_error_table();
74 initialize_AB_error_table();
75 initialize_AF_error_table();
76 initialize_AL_error_table();
77 initialize_AC_error_table();
78 initialize_AK_error_table();
79 initialize_AM_error_table();
80 initialize_AP_error_table();
81 initialize_AU_error_table();
82 initialize_AV_error_table();
83 initialize_VOLS_error_table();
84 #ifdef AFS_KRB5_ERROR_ENV
91 util_AdminErrorCodeTranslate(afs_status_t errorCode, int langId,
92 const char **errorTextP, afs_status_p st)
98 if (errorTextP == NULL) {
99 tst = ADMUTILERRORTEXTPNULL;
100 goto fail_util_AdminErrorCodeTranslate;
104 * Translate the error
107 if (!error_init_done)
108 pthread_once(&error_init_once, init_once);
109 code = (afs_int32) errorCode;
110 *errorTextP = afs_error_message(code);
111 #ifdef AFS_KRB5_ERROR_ENV
112 if (strncmp(*errorTextP, "unknown", strlen("unknown")) == 0) {
113 const char *msg = fetch_krb5_error_message(NULL, code);
114 *errorTextP = msg ? msg : error_message(code);
119 fail_util_AdminErrorCodeTranslate:
128 * The iterator functions and data for the database server retrieval functions.
131 typedef struct database_server_get {
134 struct afsconf_dir *conf;
135 struct afsconf_cell cell;
136 util_databaseServerEntry_t server[CACHED_ITEMS];
137 } database_server_get_t, *database_server_get_p;
140 GetDatabaseServerRPC(void *rpc_specific, int slot, int *last_item,
141 int *last_item_contains_data, afs_status_p st)
144 afs_status_t tst = 0;
145 database_server_get_p serv = (database_server_get_p) rpc_specific;
147 serv->server[slot].serverAddress =
148 ntohl(serv->cell.hostAddr[serv->index].sin_addr.s_addr);
149 strcpy(serv->server[slot].serverName, serv->cell.hostName[serv->index]);
153 * See if we've processed all the entries
156 if (serv->index == serv->total) {
158 *last_item_contains_data = 1;
169 GetDatabaseServerFromCache(void *rpc_specific, int slot, void *dest,
173 afs_status_t tst = 0;
174 database_server_get_p serv = (database_server_get_p) rpc_specific;
176 memcpy(dest, (const void *)&serv->server[slot],
177 sizeof(util_databaseServerEntry_t));
187 DestroyDatabaseServer(void *rpc_specific, afs_status_p st)
190 afs_status_t tst = 0;
191 database_server_get_p serv = (database_server_get_p) rpc_specific;
193 afsconf_Close(serv->conf);
203 * util_DatabaseServerGetBegin - begin iterating over the database
204 * server machines in a cell.
208 * IN cellName - the cell where database servers reside.
210 * OUT iterationIdP - upon successful completion contains an iterator that
211 * can be passed to util_DatabaseServerGetNext.
215 * No locks are obtained or released by this function
223 * Returns != 0 upon successful completion.
227 util_DatabaseServerGetBegin(const char *cellName, void **iterationIdP,
231 afs_status_t tst = 0;
232 afs_admin_iterator_p iter =
233 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
234 database_server_get_p serv =
235 (database_server_get_p) calloc(1, sizeof(database_server_get_t));
236 char copyCell[MAXCELLCHARS];
242 if ((cellName == NULL) || (*cellName == 0)) {
243 tst = ADMUTILCELLNAMENULL;
244 goto fail_util_DatabaseServerGetBegin;
247 if (iterationIdP == NULL) {
248 goto fail_util_DatabaseServerGetBegin;
251 if ((iter == NULL) || (serv == NULL)) {
253 goto fail_util_DatabaseServerGetBegin;
257 * Fill in the serv structure
260 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
261 if (serv->conf == NULL) {
262 tst = ADMUTILCANTOPENCELLSERVDB;
263 goto fail_util_DatabaseServerGetBegin;
267 * We must copy the cellname because afsconf_GetCellInfo
268 * actually writes over the cell name it is passed.
270 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
272 afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
275 goto fail_util_DatabaseServerGetBegin;
278 serv->total = serv->cell.numServers;
280 (iter, (void *)serv, GetDatabaseServerRPC, GetDatabaseServerFromCache,
281 NULL, DestroyDatabaseServer, &tst)) {
282 *iterationIdP = (void *)iter;
284 goto fail_util_DatabaseServerGetBegin;
288 fail_util_DatabaseServerGetBegin:
306 * util_DatabaseServerGetNext - get the next server address.
310 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
312 * OUT serverAddressP - upon successful completion contains the next
313 * server address in the cell.
317 * This function locks the iterator for the duration of its processing.
325 * Returns != 0 upon successful completion.
330 util_DatabaseServerGetNext(const void *iterationId,
331 util_databaseServerEntry_p serverP,
335 afs_status_t tst = 0;
336 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
339 tst = ADMITERATORNULL;
340 goto fail_util_DatabaseServerGetNext;
343 if (serverP == NULL) {
344 tst = ADMUTILSERVERADDRESSPNULL;
345 goto fail_util_DatabaseServerGetNext;
348 rc = IteratorNext(iter, (void *)serverP, &tst);
350 fail_util_DatabaseServerGetNext:
359 * util_DatabaseServerGetDone - stop using a database iterator.
363 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
367 * This function locks the iterator for the duration of its processing.
368 * And then destroys it before returning.
376 * Returns != 0 upon successful completion.
380 util_DatabaseServerGetDone(const void *iterationId, afs_status_p st)
383 afs_status_t tst = 0;
384 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
387 * Validate parameters
391 tst = ADMITERATORNULL;
392 goto fail_util_DatabaseServerGetDone;
395 rc = IteratorDone(iter, &tst);
397 fail_util_DatabaseServerGetDone:
406 * GetServerAddressFromName - translate a character string server name
407 * to an integer representation of an IP address.
411 * IN serverName - the character string server name in either foo.com
412 * format, or 123.12.1.1 format.
414 * OUT serverAddress - an integer that is filled with the correct address
415 * in host byte order upon successful completion.
419 * No locks are obtained or released by this function
423 * On many platforms, gethostbyname is not thread safe. Since we are
424 * only working under NT for now I'll use it directly. In future UNIX
425 * ports, a wrapper function should be written to call the correct function
426 * on the particular platform.
430 * Returns != 0 upon successful completion.
434 util_AdminServerAddressGetFromName(const char *serverName, int *serverAddress,
438 afs_status_t tst = 0;
439 struct hostent *server;
440 int part1, part2, part3, part4;
443 if ((serverName == NULL) || (*serverName == 0)) {
444 tst = ADMUTILSERVERNAMENULL;
445 goto fail_util_AdminServerAddressGetFromName;
448 if (serverAddress == NULL) {
449 tst = ADMUTILSERVERADDRESSNULL;
450 goto fail_util_AdminServerAddressGetFromName;
454 sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
455 if (num_converted == 4) {
456 *serverAddress = (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
459 server = gethostbyname(serverName);
460 if (server != NULL) {
461 memcpy((void *)serverAddress, (const void *)server->h_addr,
463 *serverAddress = ntohl(*serverAddress);
465 tst = ADMUTILCANTGETSERVERNAME;
467 goto fail_util_AdminServerAddressGetFromName;
473 fail_util_AdminServerAddressGetFromName:
483 * This file contains functions that can be used to create iterator
484 * functions within the api. I have attempted to make these functions
485 * generic so that they can be used across the admin components.
487 * The functions in this file are a generalized producer/consumer
488 * implementation. They manage access to a queue of data. The only
489 * assumption these functions make about this data is that it is
490 * stored in a queue which is implemented via an array. These functions
491 * know about the index into the array, but they know nothing about
492 * the contents of the array.
494 * The data specific functions you implement will have to create some
495 * data specific storage structure that will have an array
496 * of size CACHED_ITEMS data items. This structure will also need to
497 * store any necessary parameters/state variables you need to issue the
498 * rpc to retrieve the next item.
500 * In order to use the generic functions, you must implement four functions
501 * for each type of data you wish to retrieve. The functions are:
503 * validate_specific_data_func - this function is handed a void pointer
504 * that points to the rpc specific data you've allocated. The function
505 * should examine the data for validity and return an appropriate error.
506 * This function is called every time the iterator is validated.
508 * destroy_specific_data_func - this function is handed a void pointer
509 * that points to the rpc specific data you've allocated. It should
510 * destroy any components of the specific data as required and then
511 * return. The void pointer is free'd by the generic functions.
513 * get_cached_data_func - this function is handed a void pointer
514 * that points to the rpc specific data you've allocated, an index
515 * into the cache of the item to be copied to the caller, and a void
516 * pointer where the cache item should be copied.
518 * make_rpc_func - this function is handed a void pointer that points
519 * to the rpc specific data you've allocated, an index into the cache
520 * of the item to be filled with the next retrieved item, and an int
521 * pointer that should be set to 1 if there are no more items to be
522 * retrieved. The assumption made by the generic functions is that
523 * the last_item status requires an individual rpc - the data isn't
524 * piggybacked on the last data item.
528 * IteratorDelete - delete an iterator.
532 * IN interator - the iterator to delete.
536 * No locks are held by this function.
540 * Returns != 0 upon successful completion.
544 IteratorDelete(afs_admin_iterator_p iter, afs_status_p st)
547 afs_status_t tst = 0;
549 if (pthread_mutex_destroy(&iter->mutex)) {
550 tst = ADMMUTEXDESTROY;
551 goto fail_IteratorDelete;
553 if (pthread_cond_destroy(&iter->add_item)) {
554 tst = ADMCONDDESTROY;
555 goto fail_IteratorDelete;
557 if (pthread_cond_destroy(&iter->remove_item)) {
558 tst = ADMCONDDESTROY;
559 goto fail_IteratorDelete;
562 if (iter->destroy_specific != NULL) {
563 iter->destroy_specific(iter->rpc_specific, &tst);
565 free(iter->rpc_specific);
578 * DataGet - the background thread that is spawned for every
579 * IteratorBegin call that is successful. This thread tries
580 * to fetch the data from the server ahead of the
581 * IteratorNext calls.
585 * IN arg - the address of the iterator structure to be used for this
590 * The iterator mutex is used by this function to protect elements
591 * of the iterator structure.
595 * Returns != 0 upon successful completion.
601 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
603 afs_status_t tst = 0;
604 int mutex_locked = 0;
606 int last_item_contains_data = 0;
608 if (pthread_mutex_lock(&iter->mutex)) {
609 iter->st = ADMMUTEXLOCK;
618 * Check to see if there's room for this datum. If not, wait
619 * on the consumer to free up another slot.
622 while (iter->cache_slots_used == CACHED_ITEMS) {
623 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
624 iter->st = ADMCONDWAIT;
630 * Check to see if someone called Done and terminated the request.
631 * We could have gone to sleep above when the buffer was full and
632 * instead of being awoken because another slot is open, we were
633 * awoken because the request was terminated.
636 if (iter->request_terminated) {
640 if (pthread_mutex_unlock(&iter->mutex)) {
641 iter->st = ADMMUTEXUNLOCK;
648 * Make an rpc without holding the iter mutex
649 * We reference an item in the principal cache here without
650 * holding the mutex. This is safe because:
651 * 1. The iter structure is ref counted and won't be deleted
652 * from underneath us.
653 * 2. cache_queue_tail is always one item ahead of the consumer
654 * thread so we are the only thread accessing this member.
657 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail, &last_item,
658 &last_item_contains_data, &tst);
660 if (pthread_mutex_lock(&iter->mutex)) {
661 iter->st = ADMMUTEXLOCK;
668 * Check to see if someone called Done and terminated the request
671 if (iter->request_terminated) {
676 * Check the rc of the rpc, and see if there are no more items
686 * Check to see if this is the last item produced by the rpc.
687 * If it isn't, add the item to the cache and proceed.
688 * If it is, check to see if the last item contains valid data.
689 * If it contains valid data, we need to add it to our cache.
690 * If it doesn't, we mark the iterator as complete.
693 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
694 iter->cache_queue_tail =
695 (iter->cache_queue_tail + 1) % CACHED_ITEMS;
696 iter->cache_slots_used++;
699 iter->st = ADMITERATORDONE;
700 iter->done_iterating = 1;
702 * There's a small chance that the consumer emptied the
703 * cache queue while we were making the last rpc and has
704 * since gone to sleep waiting for more data. In this case
705 * there will never be more data so we signal him here.
707 pthread_cond_signal(&iter->add_item);
713 * If the cache was empty and we just added another item, signal
717 if (iter->cache_slots_used == 1) {
718 if (pthread_cond_signal(&iter->add_item)) {
719 iter->st = ADMCONDSIGNAL;
729 * If we are exiting with an error, signal the consumer in the event
730 * they were waiting for us to produce more data
734 pthread_cond_signal(&iter->add_item);
738 pthread_mutex_unlock(&iter->mutex);
745 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
749 * IN interator - the interator to be verified.
753 * We assume the iter->mutex lock is already held.
757 * Returns != 0 upon successful completion.
761 IsValidIterator(const afs_admin_iterator_p iterator, afs_status_p st)
764 afs_status_t tst = 0;
767 * Validate input parameters
770 if (iterator == NULL) {
771 tst = ADMITERATORNULL;
772 goto fail_IsValidIterator;
775 if ((iterator->begin_magic != BEGIN_MAGIC)
776 || (iterator->end_magic != END_MAGIC)) {
777 tst = ADMITERATORBADMAGICNULL;
778 goto fail_IsValidIterator;
781 if (iterator->is_valid == 0) {
782 tst = ADMITERATORINVALID;
783 goto fail_IsValidIterator;
787 * Call the iterator specific validation function
790 if (iterator->validate_specific != NULL) {
791 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
792 goto fail_IsValidIterator;
797 fail_IsValidIterator:
806 * IteratorNext - return the next datum in an interator.
810 * IN interator - the iterator containing the data.
812 * IN dest - the address where the data should be copied.
816 * Lock the iterator upon entry, and hold it during the duration of this
821 * Returns != 0 upon successful completion.
825 IteratorNext(afs_admin_iterator_p iter, void *dest, afs_status_p st)
828 afs_status_t tst = 0;
832 * We have to lock the iterator before we validate it
835 if (pthread_mutex_lock(&iter->mutex)) {
837 goto fail_IteratorNext;
842 if (!IsValidIterator(iter, &tst)) {
843 goto fail_IteratorNext;
846 if (iter->request_terminated == 1) {
847 tst = ADMITERATORTERMINATED;
848 goto fail_IteratorNext;
851 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
853 goto fail_IteratorNext;
857 * Check to see if there are any queue'd items. If not, wait here
858 * until signalled by the producer.
861 while (iter->cache_slots_used == 0) {
864 * Maybe the producer experienced an rpc failure.
867 if ((!iter->done_iterating) && (iter->st != 0)) {
869 goto fail_IteratorNext;
873 * Maybe there are no queue'd items because the producer is done
876 if (iter->done_iterating) {
878 goto fail_IteratorNext;
881 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
883 goto fail_IteratorNext;
888 * Copy the next cached item and update the cached item count
889 * and the index into the cache array
893 get_cached_data(iter->rpc_specific, iter->cache_queue_head, dest,
895 goto fail_IteratorNext;
898 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
899 iter->cache_slots_used--;
902 * If the cache was full before we removed the item above, the
903 * producer may have been waiting for us to remove an item.
904 * Signal the producer letting him know that we've opened a slot
908 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
909 if (pthread_cond_signal(&iter->remove_item)) {
911 goto fail_IteratorNext;
919 if (locked_iter == 1) {
920 pthread_mutex_unlock(&iter->mutex);
930 * IteratorDone - mark the iterator done.
934 * IN interator - the iterator to mark done.
938 * Lock the iterator upon entry, and hold it during the duration of this
943 * Returns != 0 upon successful completion.
947 IteratorDone(afs_admin_iterator_p iter, afs_status_p st)
950 afs_status_t tst = 0;
951 int mutex_locked = 1;
953 if (pthread_mutex_lock(&iter->mutex)) {
955 goto fail_IteratorDone;
961 if (!IsValidIterator(iter, &tst)) {
962 goto fail_IteratorDone;
967 * Depending upon the status of the background worker thread,
968 * we can either join with him immediately (if we know he has
969 * terminated), or we need to tell him the request has been
970 * terminated and then join with him.
973 if (!iter->done_iterating) {
974 iter->request_terminated = 1;
975 iter->cache_slots_used = 0;
976 pthread_cond_signal(&iter->remove_item);
980 * We have to unlock the mutex to allow the background thread to
984 if (pthread_mutex_unlock(&iter->mutex)) {
985 tst = ADMMUTEXUNLOCK;
986 goto fail_IteratorDone;
989 if (iter->make_rpc != NULL) {
990 if (pthread_join(iter->bg_worker, (void **)0)) {
992 goto fail_IteratorDone;
997 * We don't relock the mutex here since we are the only thread
998 * that has access to the iter now
1001 rc = IteratorDelete(iter, &tst);
1007 pthread_mutex_unlock(&iter->mutex);
1017 * IteratorInit - initialize an iterator.
1021 * IN interator - the iterator to initialize.
1025 * No locks are held by this function.
1029 * Returns != 0 upon successful completion.
1033 IteratorInit(afs_admin_iterator_p iter, void *rpc_specific,
1034 make_rpc_func make_rpc, get_cached_data_func get_cached_data,
1035 validate_specific_data_func validate_specific_data,
1036 destroy_specific_data_func destroy_specific_data,
1040 afs_status_t tst = 0;
1041 int mutex_inited = 0;
1042 int add_item_cond_inited = 0;
1043 int remove_item_cond_inited = 0;
1046 tst = ADMITERATORNULL;
1047 goto fail_IteratorInit;
1050 if (rpc_specific == NULL) {
1051 tst = ADMITERATORRPCSPECIFICNULL;
1052 goto fail_IteratorInit;
1056 * Initialize the iterator structure
1058 iter->begin_magic = BEGIN_MAGIC;
1059 iter->end_magic = END_MAGIC;
1061 iter->cache_slots_used = 0;
1062 iter->done_iterating = 0;
1063 iter->request_terminated = 0;
1064 iter->st = AFS_STATUS_OK;
1065 iter->cache_queue_head = 0;
1066 iter->cache_queue_tail = 0;
1067 iter->cache_slots_used = 0;
1068 iter->rpc_specific = rpc_specific;
1069 iter->make_rpc = make_rpc;
1070 iter->get_cached_data = get_cached_data;
1071 iter->validate_specific = validate_specific_data;
1072 iter->destroy_specific = destroy_specific_data;
1074 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *)0)) {
1076 goto fail_IteratorInit;
1081 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *)0)) {
1083 goto fail_IteratorInit;
1085 add_item_cond_inited = 1;
1088 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *)0)) {
1090 goto fail_IteratorInit;
1092 remove_item_cond_inited = 1;
1096 * Create a worker thread that will begin to query the server
1097 * and cache responses.
1100 if (iter->make_rpc != NULL) {
1101 pthread_attr_t tattr;
1103 if (pthread_attr_init(&tattr)) {
1104 tst = ADMTHREADATTRINIT;
1105 goto fail_IteratorInit;
1108 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1109 tst = ADMTHREADATTRSETDETACHSTATE;
1110 goto fail_IteratorInit;
1113 if (pthread_create(&iter->bg_worker, &tattr, DataGet, (void *)iter)) {
1114 tst = ADMTHREADCREATE;
1115 goto fail_IteratorInit;
1124 pthread_mutex_destroy(&iter->mutex);
1126 if (remove_item_cond_inited) {
1127 pthread_cond_destroy(&iter->remove_item);
1129 if (add_item_cond_inited) {
1130 pthread_cond_destroy(&iter->add_item);
1141 CellHandleIsValid(const void *cellHandle, afs_status_p st)
1144 afs_status_t tst = 0;
1145 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1148 * Validate input parameters
1151 if (c_handle == NULL) {
1152 tst = ADMCLIENTCELLHANDLENULL;
1153 goto fail_CellHandleIsValid;
1156 if ((c_handle->begin_magic != BEGIN_MAGIC)
1157 || (c_handle->end_magic != END_MAGIC)) {
1158 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1159 goto fail_CellHandleIsValid;
1162 if (c_handle->is_valid == 0) {
1163 tst = ADMCLIENTCELLINVALID;
1164 goto fail_CellHandleIsValid;
1168 fail_CellHandleIsValid:
1177 * The iterator functions and data for the rpc statistic retrieval functions
1180 typedef struct rpc_stat_get {
1181 afs_uint32 clock_sec;
1182 afs_uint32 clock_usec;
1185 afs_uint32 clientVersion;
1186 afs_uint32 serverVersion;
1187 struct rpcStats stat_list;
1188 afs_RPCStats_t stats[CACHED_ITEMS];
1189 afs_uint32 *pointer;
1190 } rpc_stat_get_t, *rpc_stat_get_p;
1193 UnmarshallRPCStats(afs_uint32 serverVersion, afs_uint32 ** ptrP,
1197 unsigned int hi, lo;
1200 * Server must always match lower versions. We are version 1.
1203 s->stats_v1.remote_peer = *(ptr++);
1204 s->stats_v1.remote_port = *(ptr++);
1205 s->stats_v1.remote_is_server = *(ptr++);
1206 s->stats_v1.interfaceId = *(ptr++);
1207 s->stats_v1.func_total = *(ptr++);
1208 s->stats_v1.func_index = *(ptr++);
1211 hset64(s->stats_v1.invocations, hi, lo);
1214 hset64(s->stats_v1.bytes_sent, hi, lo);
1217 hset64(s->stats_v1.bytes_rcvd, hi, lo);
1218 s->stats_v1.queue_time_sum.sec = *(ptr++);
1219 s->stats_v1.queue_time_sum.usec = *(ptr++);
1220 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1221 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1222 s->stats_v1.queue_time_min.sec = *(ptr++);
1223 s->stats_v1.queue_time_min.usec = *(ptr++);
1224 s->stats_v1.queue_time_max.sec = *(ptr++);
1225 s->stats_v1.queue_time_max.usec = *(ptr++);
1226 s->stats_v1.execution_time_sum.sec = *(ptr++);
1227 s->stats_v1.execution_time_sum.usec = *(ptr++);
1228 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1229 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1230 s->stats_v1.execution_time_min.sec = *(ptr++);
1231 s->stats_v1.execution_time_min.usec = *(ptr++);
1232 s->stats_v1.execution_time_max.sec = *(ptr++);
1233 s->stats_v1.execution_time_max.usec = *(ptr++);
1238 GetRPCStatsRPC(void *rpc_specific, int slot, int *last_item,
1239 int *last_item_contains_data, afs_status_p st)
1242 afs_status_t tst = 0;
1243 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1245 t->stats[slot].clientVersion = t->clientVersion;
1246 t->stats[slot].serverVersion = t->serverVersion;
1247 t->stats[slot].statCount = t->total;
1250 * If the server stat version is greater than or equal to my version
1251 * number, it is required to return the values in the client's current
1255 UnmarshallRPCStats(t->serverVersion, &t->pointer, &t->stats[slot].s);
1260 * See if we've processed all the entries
1263 if (t->index == t->total) {
1265 *last_item_contains_data = 1;
1276 GetRPCStatsFromCache(void *rpc_specific, int slot, void *dest,
1280 afs_status_t tst = 0;
1281 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1283 memcpy(dest, (const void *)&stat->stats[slot], sizeof(afs_RPCStats_t));
1293 DestroyRPCStats(void *rpc_specific, afs_status_p st)
1296 afs_status_t tst = 0;
1297 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1299 if (stat->stat_list.rpcStats_val != NULL) {
1300 free(stat->stat_list.rpcStats_val);
1311 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1315 * IN conn - an rx connection to the process to be queried
1317 * IN rpc - the function to call to make the actual rpc
1319 * OUT iterationIdP - an iteration id that can be passed to
1320 * util_RPCStatsGetNext to get the next rpc stat
1324 * No locks are obtained or released by this function
1328 * Returns != 0 upon successful completion.
1333 util_RPCStatsGetBegin(struct rx_connection *conn,
1334 int (*rpc) (struct rx_connection *,
1335 afs_uint32, afs_uint32 *,
1336 afs_uint32 *, afs_uint32 *,
1337 afs_uint32 *, struct rpcStats *),
1338 void **iterationIdP, afs_status_p st)
1341 afs_status_t tst = 0;
1342 afs_admin_iterator_p iter =
1343 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1344 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1347 tst = ADMRXCONNNULL;
1348 goto fail_util_RPCStatsGetBegin;
1352 tst = ADMRPCPTRNULL;
1353 goto fail_util_RPCStatsGetBegin;
1356 if (iterationIdP == NULL) {
1357 tst = ADMITERATIONIDPNULL;
1358 goto fail_util_RPCStatsGetBegin;
1361 if ((iter == NULL) || (stat == NULL)) {
1363 goto fail_util_RPCStatsGetBegin;
1366 stat->stat_list.rpcStats_len = 0;
1367 stat->stat_list.rpcStats_val = 0;
1369 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1372 (*rpc) (conn, stat->clientVersion, &stat->serverVersion,
1373 &stat->clock_sec, &stat->clock_usec, &stat->total,
1377 goto fail_util_RPCStatsGetBegin;
1381 * If there are no statistics, just mark the iterator done and
1385 if (stat->stat_list.rpcStats_len == 0) {
1386 stat->pointer = NULL;
1387 if (!IteratorInit(iter, (void *)stat, NULL, NULL, NULL, NULL, &tst)) {
1388 goto fail_util_RPCStatsGetBegin;
1390 iter->done_iterating = 1;
1391 iter->st = ADMITERATORDONE;
1393 stat->pointer = stat->stat_list.rpcStats_val;
1395 (iter, (void *)stat, GetRPCStatsRPC, GetRPCStatsFromCache, NULL,
1396 DestroyRPCStats, &tst)) {
1397 goto fail_util_RPCStatsGetBegin;
1400 *iterationIdP = (void *)iter;
1403 fail_util_RPCStatsGetBegin:
1421 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1425 * IN iterationId - an iterator previously returned by
1426 * util_RPCStatsGetBegin.
1428 * OUT stats - upon successful completion contains the next set of stats
1433 * No locks are obtained or released by this function
1437 * Returns != 0 upon successful completion.
1442 util_RPCStatsGetNext(const void *iterationId, afs_RPCStats_p stats,
1446 afs_status_t tst = 0;
1447 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1449 if (iterationId == NULL) {
1450 tst = ADMITERATIONIDPNULL;
1451 goto fail_util_RPCStatsGetNext;
1454 if (stats == NULL) {
1455 tst = ADMUTILRPCSTATSNULL;
1456 goto fail_util_RPCStatsGetNext;
1459 rc = IteratorNext(iter, (void *)stats, &tst);
1461 fail_util_RPCStatsGetNext:
1470 * util_RPCStatsGetDone - finish using a stats iterator
1474 * IN iterationId - an iterator previously returned by
1475 * util_RPCStatsGetBegin.
1479 * No locks are obtained or released by this function
1483 * Returns != 0 upon successful completion.
1488 util_RPCStatsGetDone(const void *iterationId, afs_status_p st)
1491 afs_status_t tst = 0;
1492 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1494 if (iterationId == NULL) {
1495 tst = ADMITERATIONIDPNULL;
1496 goto fail_util_RPCStatsGetDone;
1499 rc = IteratorDone(iter, &tst);
1501 fail_util_RPCStatsGetDone:
1510 * util_RPCStatsStateGet - get the current state of rpc stat collection
1514 * IN conn - an rx connection to the process to be queried
1516 * IN rpc - the function to call to make the actual rpc
1518 * OUT state - the rpc stat collection state.
1522 * No locks are obtained or released by this function
1526 * Returns != 0 upon successful completion.
1531 util_RPCStatsStateGet(struct rx_connection *conn,
1532 int (*rpc) (struct rx_connection *,
1533 afs_RPCStatsState_p),
1534 afs_RPCStatsState_p state, afs_status_p st)
1537 afs_status_t tst = 0;
1540 tst = ADMRXCONNNULL;
1541 goto fail_util_RPCStatsStateGet;
1545 tst = ADMRPCPTRNULL;
1546 goto fail_util_RPCStatsStateGet;
1549 if (state == NULL) {
1550 tst = ADMRPCSTATENULL;
1551 goto fail_util_RPCStatsStateGet;
1554 tst = (*rpc) (conn, state);
1560 fail_util_RPCStatsStateGet:
1569 * util_RPCStatsStateEnable - enable rpc stat collection
1574 * IN conn - an rx connection to the process to be modified
1576 * IN rpc - the function to call to make the actual rpc
1580 * No locks are obtained or released by this function
1584 * Returns != 0 upon successful completion.
1589 util_RPCStatsStateEnable(struct rx_connection *conn,
1590 int (*rpc) (struct rx_connection *),
1594 afs_status_t tst = 0;
1597 tst = ADMRXCONNNULL;
1598 goto fail_util_RPCStatsStateEnable;
1602 tst = ADMRPCPTRNULL;
1603 goto fail_util_RPCStatsStateEnable;
1606 tst = (*rpc) (conn);
1612 fail_util_RPCStatsStateEnable:
1621 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1626 * IN conn - an rx connection to the process to be modified
1628 * IN rpc - the function to call to make the actual rpc
1632 * No locks are obtained or released by this function
1636 * Returns != 0 upon successful completion.
1641 util_RPCStatsStateDisable(struct rx_connection *conn,
1642 int (*rpc) (struct rx_connection *),
1646 afs_status_t tst = 0;
1649 tst = ADMRXCONNNULL;
1650 goto fail_util_RPCStatsStateDisable;
1654 tst = ADMRPCPTRNULL;
1655 goto fail_util_RPCStatsStateDisable;
1658 tst = (*rpc) (conn);
1664 fail_util_RPCStatsStateDisable:
1673 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1674 * collection at a server
1678 * IN conn - an rx connection to the process to be modified
1680 * IN rpc - the function to call to make the actual rpc
1682 * IN flag - a flag containing the fields to be cleared
1687 * No locks are obtained or released by this function
1691 * Returns != 0 upon successful completion.
1696 util_RPCStatsClear(struct rx_connection *conn,
1697 int (*rpc) (struct rx_connection *,
1698 afs_RPCStatsClearFlag_t),
1699 afs_RPCStatsClearFlag_t flag, afs_status_p st)
1702 afs_status_t tst = 0;
1705 tst = ADMRXCONNNULL;
1706 goto fail_util_RPCStatsClear;
1710 tst = ADMRPCPTRNULL;
1711 goto fail_util_RPCStatsClear;
1714 tst = (*rpc) (conn, flag);
1720 fail_util_RPCStatsClear:
1729 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1733 * IN conn - an rx connection to the process to be modified
1735 * OUT version - the version of rpc stat collection at the remote process
1739 * No locks are obtained or released by this function
1743 * Returns != 0 upon successful completion.
1748 util_RPCStatsVersionGet(struct rx_connection *conn,
1749 afs_RPCStatsVersion_p version, afs_status_p st)
1752 afs_status_t tst = 0;
1755 tst = ADMRXCONNNULL;
1756 goto fail_util_RPCStatsVersionGet;
1759 if (version == NULL) {
1760 tst = ADMRPCVERSIONNULL;
1761 goto fail_util_RPCStatsVersionGet;
1764 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1770 fail_util_RPCStatsVersionGet:
1779 * The iterator for listing CM server preferences
1782 typedef struct cm_srvr_pref_get {
1783 struct rx_connection *conn;
1785 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1786 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1789 GetServerPrefsRPC(void *rpc_specific, int slot, int *last_item,
1790 int *last_item_contains_data, afs_status_p st)
1793 afs_status_t tst = 0;
1794 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1797 * Get the next entry in the list of server preferences.
1800 RXAFSCB_GetServerPrefs(t->conn, t->index, &t->srvrPrefs[slot].ipAddr,
1801 &t->srvrPrefs[slot].ipRank);
1803 goto fail_GetServerPrefsRPC;
1807 * See if we've processed all the entries
1809 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1811 *last_item_contains_data = 0;
1817 fail_GetServerPrefsRPC:
1826 GetServerPrefsFromCache(void *rpc_specific, int slot, void *dest,
1830 afs_status_t tst = 0;
1831 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1833 memcpy(dest, (const void *)&prefs->srvrPrefs[slot],
1834 sizeof(afs_CMServerPref_t));
1844 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1848 * IN conn - an rx connection to the process to be queried
1850 * OUT iterationIdP - an iteration id that can be passed to
1851 * util_CMGetServerPrefsNext to get the next server preference
1855 * No locks are obtained or released by this function
1859 * Returns != 0 upon successful completion.
1864 util_CMGetServerPrefsBegin(struct rx_connection *conn, void **iterationIdP,
1868 afs_status_t tst = 0;
1869 afs_admin_iterator_p iter;
1870 cm_srvr_pref_get_p pref;
1873 tst = ADMRXCONNNULL;
1874 goto fail_util_CMGetServerPrefsBegin;
1877 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1880 goto fail_util_CMGetServerPrefsBegin;
1883 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1887 goto fail_util_CMGetServerPrefsBegin;
1893 (iter, (void *)pref, GetServerPrefsRPC, GetServerPrefsFromCache, NULL,
1897 goto fail_util_CMGetServerPrefsBegin;
1899 *iterationIdP = (void *)iter;
1902 fail_util_CMGetServerPrefsBegin:
1911 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1916 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1918 * OUT prefs - Next entry in cache manager server preferences.
1922 * No locks are obtained or released by this function
1926 * Returns != 0 upon successful completion.
1931 util_CMGetServerPrefsNext(const void *iterationId, afs_CMServerPref_p prefs,
1935 afs_status_t tst = 0;
1936 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1938 if (iterationId == NULL) {
1939 tst = ADMITERATIONIDPNULL;
1940 goto fail_util_CMGetServerPrefsNext;
1943 rc = IteratorNext(iter, (void *)prefs, &tst);
1945 fail_util_CMGetServerPrefsNext:
1954 * util_CMGetServerPrefsDone - Finish listing cache manager server
1959 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1963 * No locks are obtained or released by this function
1967 * Returns != 0 upon successful completion.
1972 util_CMGetServerPrefsDone(const void *iterationId, afs_status_p st)
1975 afs_status_t tst = 0;
1976 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1978 if (iterationId == NULL) {
1979 tst = ADMITERATIONIDPNULL;
1980 goto fail_util_CMGetServerPrefsDone;
1983 rc = IteratorDone(iter, &tst);
1986 fail_util_CMGetServerPrefsDone:
1995 * The iterator for listing CM CellServDB
1998 typedef struct cm_list_cell_get {
1999 struct rx_connection *conn;
2001 afs_CMListCell_t cell[CACHED_ITEMS];
2002 } cm_list_cell_get_t, *cm_list_cell_get_p;
2005 ListCellsRPC(void *rpc_specific, int slot, int *last_item,
2006 int *last_item_contains_data, afs_status_p st)
2009 afs_status_t tst = 0;
2010 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2016 * Get the next entry in the CellServDB.
2018 name = t->cell[slot].cellname;
2019 sl.serverList_len = 0;
2020 sl.serverList_val = NULL;
2021 memset(t->cell[slot].serverAddr, 0, sizeof(afs_int32)*UTIL_MAX_CELL_HOSTS);
2023 RXAFSCB_GetCellServDB(t->conn, t->index, &name, &sl);
2025 goto fail_ListCellsRPC;
2027 strcpy(t->cell[slot].cellname, name);
2028 if (sl.serverList_val) {
2029 for (n=0; n<sl.serverList_len && n<UTIL_MAX_CELL_HOSTS; n++) {
2030 t->cell[slot].serverAddr[n] = sl.serverList_val[n];
2032 xdr_free((xdrproc_t) xdr_serverList, &sl);
2036 * See if we've processed all the entries
2038 if (strlen(t->cell[slot].cellname) == 0) {
2040 *last_item_contains_data = 0;
2055 ListCellsFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2058 afs_status_t tst = 0;
2059 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2061 memcpy(dest, (const void *)&cell->cell[slot], sizeof(afs_CMListCell_t));
2071 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2075 * IN conn - an rx connection to the process to be queried
2077 * OUT iterationIdP - an iteration id that can be passed to
2078 * util_CMListCellsNext to get the next cell
2082 * No locks are obtained or released by this function
2086 * Returns != 0 upon successful completion.
2091 util_CMListCellsBegin(struct rx_connection *conn, void **iterationIdP,
2095 afs_status_t tst = 0;
2096 afs_admin_iterator_p iter;
2097 cm_list_cell_get_p cell;
2100 tst = ADMRXCONNNULL;
2101 goto fail_util_CMListCellsBegin;
2104 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2107 goto fail_util_CMListCellsBegin;
2110 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2114 goto fail_util_CMListCellsBegin;
2120 (iter, (void *)cell, ListCellsRPC, ListCellsFromCache, NULL, NULL,
2124 goto fail_util_CMListCellsBegin;
2126 *iterationIdP = (void *)iter;
2129 fail_util_CMListCellsBegin:
2138 * util_CMListCellsNext - Get next entry in cache manager cells
2142 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2144 * OUT cell - Next entry in cache manager cells.
2148 * No locks are obtained or released by this function
2152 * Returns != 0 upon successful completion.
2157 util_CMListCellsNext(const void *iterationId, afs_CMListCell_p cell,
2161 afs_status_t tst = 0;
2162 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2164 if (iterationId == NULL) {
2165 tst = ADMITERATIONIDPNULL;
2166 goto fail_util_CMListCellsNext;
2169 rc = IteratorNext(iter, (void *)cell, &tst);
2171 fail_util_CMListCellsNext:
2180 * util_CMListCellsDone - Finish listing cache manager cells
2184 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2188 * No locks are obtained or released by this function
2192 * Returns != 0 upon successful completion.
2197 util_CMListCellsDone(const void *iterationId, afs_status_p st)
2200 afs_status_t tst = 0;
2201 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2203 if (iterationId == NULL) {
2204 tst = ADMITERATIONIDPNULL;
2205 goto fail_util_CMListCellsDone;
2208 rc = IteratorDone(iter, &tst);
2211 fail_util_CMListCellsDone:
2220 * util_CMLocalCell - Get the name of the cache manager's local cell.
2224 * IN conn - an rx connection to the process to be queried
2226 * OUT cellName - the name of the cache manager's local cell.
2230 * No locks are obtained or released by this function
2234 * Returns != 0 upon successful completion.
2239 util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
2243 afs_status_t tst = 0;
2244 afs_CMCellName_p name;
2247 tst = ADMRXCONNNULL;
2248 goto fail_util_CMLocalCell;
2251 if (cellName == NULL) {
2252 tst = ADMCLIENTCMCELLNAMENULL;
2253 goto fail_util_CMLocalCell;
2257 tst = RXAFSCB_GetLocalCell(conn, &name);
2263 fail_util_CMLocalCell:
2272 UnmarshallCMClientConfig(afs_uint32 serverVersion, afs_uint32 * ptr,
2273 afs_ClientConfigUnion_p config)
2276 * We currently only support version 1.
2278 config->config_v1.nChunkFiles = *(ptr++);
2279 config->config_v1.nStatCaches = *(ptr++);
2280 config->config_v1.nDataCaches = *(ptr++);
2281 config->config_v1.nVolumeCaches = *(ptr++);
2282 config->config_v1.firstChunkSize = *(ptr++);
2283 config->config_v1.otherChunkSize = *(ptr++);
2284 config->config_v1.cacheSize = *(ptr++);
2285 config->config_v1.setTime = *(ptr++);
2286 config->config_v1.memCache = *(ptr++);
2290 * util_CMClientConfig - Get the cache manager's configuration parameters.
2294 * IN conn - an rx connection to the process to be queried
2296 * OUT config - the cache manager's configuration parameters.
2300 * No locks are obtained or released by this function
2304 * Returns != 0 upon successful completion.
2309 util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
2313 afs_status_t tst = 0;
2314 afs_uint32 allocbytes;
2315 struct cacheConfig tconfig;
2318 tst = ADMRXCONNNULL;
2319 goto fail_util_CMClientConfig;
2322 if (config == NULL) {
2323 tst = ADMCLIENTCMCELLNAMENULL;
2324 goto fail_util_CMClientConfig;
2327 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2328 tconfig.cacheConfig_val = NULL;
2329 tconfig.cacheConfig_len = 0;
2331 RXAFSCB_GetCacheConfig(conn, config->clientVersion,
2332 &config->serverVersion, &allocbytes, &tconfig);
2335 goto fail_util_CMClientConfig;
2338 UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
2341 free(tconfig.cacheConfig_val);
2343 fail_util_CMClientConfig:
2352 * util_RXDebugVersion - Get the rxdebug version string.
2356 * IN handle - an rxdebug handle for the process to be queried.
2358 * OUT version - the rxdebug version string.
2362 * No locks are obtained or released by this function
2366 * Returns != 0 upon successful completion.
2371 util_RXDebugVersion(rxdebugHandle_p handle, rxdebugVersion_p version,
2375 afs_status_t tst = 0;
2378 if (handle == NULL) {
2379 tst = ADMRXDEBUGHANDLENULL;
2380 goto fail_util_RXDebugVersion;
2383 if (version == NULL) {
2384 tst = ADMRXDEBUGVERSIONNULL;
2385 goto fail_util_RXDebugVersion;
2389 rx_GetServerVersion(handle->sock, handle->ipAddr, handle->udpPort,
2390 UTIL_MAX_RXDEBUG_VERSION_LEN, version);
2392 tst = ADMCLIENTRXDEBUGTIMEOUT;
2393 goto fail_util_RXDebugVersion;
2398 fail_util_RXDebugVersion:
2407 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2412 * IN handle - an rxdebug handle for the process to be queried.
2414 * OUT supportedStats - bit mask with supported rxstats.
2418 * No locks are obtained or released by this function
2422 * Returns != 0 upon successful completion.
2427 util_RXDebugSupportedStats(rxdebugHandle_p handle,
2428 afs_uint32 * supportedStats, afs_status_p st)
2431 afs_status_t tst = 0;
2432 struct rx_debugStats tstats;
2434 if (handle == NULL) {
2435 tst = ADMRXDEBUGHANDLENULL;
2436 goto fail_util_RXDebugSupportedStats;
2439 if (supportedStats == NULL) {
2440 tst = ADMRXDEBUGSTATSNULL;
2441 goto fail_util_RXDebugSupportedStats;
2444 if (handle->firstFlag) {
2445 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2447 goto fail_util_RXDebugSupportedStats;
2451 *supportedStats = handle->supportedStats;
2454 fail_util_RXDebugSupportedStats:
2464 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2468 * IN handle - an rxdebug handle for the process to be queried.
2470 * OUT stats - Basic rxdebug statistics for the process.
2474 * No locks are obtained or released by this function
2478 * Returns != 0 upon successful completion.
2483 util_RXDebugBasicStats(rxdebugHandle_p handle, struct rx_debugStats *stats,
2487 afs_status_t tst = 0;
2490 if (handle == NULL) {
2491 tst = ADMRXDEBUGHANDLENULL;
2492 goto fail_util_RXDebugBasicStats;
2495 if (stats == NULL) {
2496 tst = ADMRXDEBUGSTATSNULL;
2497 goto fail_util_RXDebugBasicStats;
2501 rx_GetServerDebug(handle->sock, handle->ipAddr, handle->udpPort,
2502 stats, &handle->supportedStats);
2504 tst = ADMCLIENTRXDEBUGTIMEOUT;
2505 goto fail_util_RXDebugBasicStats;
2508 handle->firstFlag = 0;
2511 fail_util_RXDebugBasicStats:
2521 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2525 * IN handle - an rxdebug handle for the process to be queried.
2527 * OUT stats - Detailed rxdebug statistics for the process.
2531 * No locks are obtained or released by this function
2535 * Returns != 0 upon successful completion.
2540 util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_statistics *stats,
2541 afs_uint32 * supportedValues, afs_status_p st)
2545 afs_status_t tst = 0;
2547 afs_uint32 tsupported;
2549 if (handle == NULL) {
2550 tst = ADMRXDEBUGHANDLENULL;
2551 goto fail_util_RXDebugRxStats;
2554 if (supportedValues == NULL) {
2555 tst = ADMRXDEBUGSTATSNULL;
2556 goto fail_util_RXDebugRxStats;
2559 if (stats == NULL) {
2560 tst = ADMRXDEBUGSTATSNULL;
2561 goto fail_util_RXDebugRxStats;
2564 if (handle->firstFlag) {
2565 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2568 goto fail_util_RXDebugRxStats;
2572 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2573 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2574 goto fail_util_RXDebugRxStats;
2578 rx_GetServerStats(handle->sock, handle->ipAddr, handle->udpPort,
2579 stats, &handle->supportedStats);
2581 tst = ADMCLIENTRXDEBUGTIMEOUT;
2582 goto fail_util_RXDebugRxStats;
2587 fail_util_RXDebugRxStats:
2596 * The iterator for listing RXDebug connections
2599 typedef struct rxdebug_conn_item {
2600 struct rx_debugConn conn;
2601 afs_uint32 supportedValues;
2602 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2604 typedef struct rxdebug_conn_get {
2606 rxdebugHandle_p handle;
2608 rxdebug_conn_item_t items[CACHED_ITEMS];
2609 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2612 RXDebugConnsFromServer(void *rpc_specific, int slot, int *last_item,
2613 int *last_item_contains_data, afs_status_p st)
2617 afs_status_t tst = 0;
2618 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2621 * Get the next entry the list of connections
2624 rx_GetServerConnections(t->handle->sock, t->handle->ipAddr,
2625 t->handle->udpPort, &t->index, t->allconns,
2626 t->handle->supportedStats,
2627 &t->items[slot].conn,
2628 &t->items[slot].supportedValues);
2630 tst = ADMCLIENTRXDEBUGTIMEOUT;
2631 goto fail_ListCellsRPC;
2635 * See if we've processed all the entries
2637 if (t->items[slot].conn.cid == 0xffffffff) {
2639 *last_item_contains_data = 0;
2652 RXDebugConnsFromCache(void *rpc_specific, int slot, void *dest,
2656 afs_status_t tst = 0;
2657 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2659 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_conn_item_t));
2669 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2674 * IN handle - an rxdebug handle for the process to be queried
2676 * IN allcons - non-zero to list all connections. If zero, only
2677 * "interesting" connections will be listed.
2679 * OUT iterationIdP - an iteration id that can be passed to
2680 * util_RXDebugConnectionsNext.
2684 * No locks are obtained or released by this function
2688 * Returns != 0 upon successful completion.
2693 util_RXDebugConnectionsBegin(rxdebugHandle_p handle, int allconns,
2694 void **iterationIdP, afs_status_p st)
2698 afs_uint32 tsupported;
2699 afs_status_t tst = 0;
2700 afs_admin_iterator_p iter;
2701 rxdebug_conn_get_p t;
2703 if (handle == NULL) {
2704 tst = ADMRXDEBUGHANDLENULL;
2705 goto fail_util_RXDebugConnectionsBegin;
2708 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2711 goto fail_util_RXDebugConnectionsBegin;
2714 if (handle->firstFlag) {
2715 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2718 goto fail_util_RXDebugConnectionsBegin;
2722 if (allconns && !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2723 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2724 goto fail_util_RXDebugConnectionsBegin;
2727 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2731 goto fail_util_RXDebugConnectionsBegin;
2734 t->allconns = allconns;
2738 (iter, (void *)t, RXDebugConnsFromServer, RXDebugConnsFromCache, NULL,
2740 goto fail_util_RXDebugConnectionsBegin;
2742 *iterationIdP = (void *)iter;
2745 fail_util_RXDebugConnectionsBegin:
2755 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2760 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2762 * OUT conn - Rxdebug information for the next connection.
2764 * OUT supportedValues - Bit mask of supported rxdebug values.
2768 * No locks are obtained or released by this function
2772 * Returns != 0 upon successful completion.
2777 util_RXDebugConnectionsNext(const void *iterationId,
2778 struct rx_debugConn *conn,
2779 afs_uint32 * supportedValues, afs_status_p st)
2782 afs_status_t tst = 0;
2783 rxdebug_conn_item_t item;
2784 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2786 if (iterationId == NULL) {
2787 tst = ADMITERATIONIDPNULL;
2788 goto fail_util_RXDebugConnectionsNext;
2792 tst = ADMRXDEBUGHANDLENULL;
2793 goto fail_util_RXDebugConnectionsNext;
2796 if (supportedValues == NULL) {
2797 tst = ADMRXDEBUGHANDLENULL;
2798 goto fail_util_RXDebugConnectionsNext;
2801 rc = IteratorNext(iter, (void *)&item, &tst);
2803 goto fail_util_RXDebugConnectionsNext;
2807 *supportedValues = item.supportedValues;
2809 fail_util_RXDebugConnectionsNext:
2819 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2823 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2827 * No locks are obtained or released by this function
2831 * Returns != 0 upon successful completion.
2836 util_RXDebugConnectionsDone(const void *iterationId, afs_status_p st)
2839 afs_status_t tst = 0;
2840 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2843 * Validate parameters
2847 tst = ADMITERATORNULL;
2848 goto fail_util_RXDebugConnectionsDone;
2851 rc = IteratorDone(iter, &tst);
2853 fail_util_RXDebugConnectionsDone:
2863 * The iterator for listing RXDebug peer
2866 typedef struct rxdebug_peer_item {
2867 struct rx_debugPeer peer;
2868 afs_uint32 supportedValues;
2869 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2871 typedef struct rxdebug_peer_get {
2872 rxdebugHandle_p handle;
2874 rxdebug_peer_item_t items[CACHED_ITEMS];
2875 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2878 RXDebugPeersFromServer(void *rpc_specific, int slot, int *last_item,
2879 int *last_item_contains_data, afs_status_p st)
2883 afs_status_t tst = 0;
2884 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2887 * Get the next entry the list of peers
2890 rx_GetServerPeers(t->handle->sock, t->handle->ipAddr,
2891 t->handle->udpPort, &t->index,
2892 t->handle->supportedStats, &t->items[slot].peer,
2893 &t->items[slot].supportedValues);
2895 tst = ADMCLIENTRXDEBUGTIMEOUT;
2896 goto fail_ListCellsRPC;
2900 * See if we've processed all the entries
2902 if (t->items[slot].peer.host == 0xffffffff) {
2904 *last_item_contains_data = 0;
2917 RXDebugPeersFromCache(void *rpc_specific, int slot, void *dest,
2921 afs_status_t tst = 0;
2922 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2924 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_peer_item_t));
2935 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
2940 * IN handle - an rxdebug handle for the process to be queried
2942 * OUT iterationIdP - an iteration id that can be passed to
2943 * util_RXDebugPeersNext.
2947 * No locks are obtained or released by this function
2951 * Returns != 0 upon successful completion.
2956 util_RXDebugPeersBegin(rxdebugHandle_p handle, void **iterationIdP,
2961 afs_uint32 tsupported;
2962 afs_status_t tst = 0;
2963 afs_admin_iterator_p iter;
2964 rxdebug_peer_get_p t;
2966 if (handle == NULL) {
2967 tst = ADMRXDEBUGHANDLENULL;
2968 goto fail_util_RXDebugPeersBegin;
2971 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2974 goto fail_util_RXDebugPeersBegin;
2977 if (handle->firstFlag) {
2978 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2981 goto fail_util_RXDebugPeersBegin;
2985 if (!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
2986 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2987 goto fail_util_RXDebugPeersBegin;
2990 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
2994 goto fail_util_RXDebugPeersBegin;
3000 (iter, (void *)t, RXDebugPeersFromServer, RXDebugPeersFromCache, NULL,
3002 goto fail_util_RXDebugPeersBegin;
3004 *iterationIdP = (void *)iter;
3007 fail_util_RXDebugPeersBegin:
3016 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3020 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3022 * OUT peer - Rxdebug information for the next peer.
3024 * OUT supportedValues - Bit mask of supported rxdebug values.
3028 * No locks are obtained or released by this function
3032 * Returns != 0 upon successful completion.
3036 util_RXDebugPeersNext(const void *iterationId, struct rx_debugPeer *peer,
3037 afs_uint32 * supportedValues, afs_status_p st)
3040 afs_status_t tst = 0;
3041 rxdebug_peer_item_t item;
3042 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3044 if (iterationId == NULL) {
3045 tst = ADMITERATIONIDPNULL;
3046 goto fail_util_RXDebugPeersNext;
3050 tst = ADMRXDEBUGHANDLENULL;
3051 goto fail_util_RXDebugPeersNext;
3054 if (supportedValues == NULL) {
3055 tst = ADMRXDEBUGHANDLENULL;
3056 goto fail_util_RXDebugPeersNext;
3059 rc = IteratorNext(iter, (void *)&item, &tst);
3061 goto fail_util_RXDebugPeersNext;
3065 *supportedValues = item.supportedValues;
3067 fail_util_RXDebugPeersNext:
3076 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3080 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3084 * No locks are obtained or released by this function
3088 * Returns != 0 upon successful completion.
3093 util_RXDebugPeersDone(const void *iterationId, afs_status_p st)
3096 afs_status_t tst = 0;
3097 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3100 * Validate parameters
3104 tst = ADMITERATORNULL;
3105 goto fail_util_RXDebugPeersDone;
3108 rc = IteratorDone(iter, &tst);
3110 fail_util_RXDebugPeersDone: