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 <afs/afs_Admin.h>
20 #include <afs/afs_Admin.h>
21 #include "afs_AdminInternal.h"
22 #include "afs_utilAdmin.h"
23 #include <afs/pthread_glock.h>
24 #include <afs/cellconfig.h>
25 #include <afs/dirpath.h>
26 #include <afs/com_err.h>
27 #include <afs/kautils.h>
29 #include <afs/vlserver.h>
30 #include <afs/pterror.h>
31 #include <afs/bnode.h>
32 #include <afs/volser.h>
33 #include <afs/afsint.h>
35 #include <rx/rxstat.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.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();
88 util_AdminErrorCodeTranslate(afs_status_t errorCode, int langId,
89 const char **errorTextP, afs_status_p st)
95 if (errorTextP == NULL) {
96 tst = ADMUTILERRORTEXTPNULL;
97 goto fail_util_AdminErrorCodeTranslate;
101 * Translate the error
104 if (!error_init_done)
105 pthread_once(&error_init_once, init_once);
106 code = (afs_int32) errorCode;
107 *errorTextP = error_message(code);
110 fail_util_AdminErrorCodeTranslate:
119 * The iterator functions and data for the database server retrieval functions.
122 typedef struct database_server_get {
125 struct afsconf_dir *conf;
126 struct afsconf_cell cell;
127 util_databaseServerEntry_t server[CACHED_ITEMS];
128 } database_server_get_t, *database_server_get_p;
131 GetDatabaseServerRPC(void *rpc_specific, int slot, int *last_item,
132 int *last_item_contains_data, afs_status_p st)
135 afs_status_t tst = 0;
136 database_server_get_p serv = (database_server_get_p) rpc_specific;
138 serv->server[slot].serverAddress =
139 ntohl(serv->cell.hostAddr[serv->index].sin_addr.s_addr);
140 strcpy(serv->server[slot].serverName, serv->cell.hostName[serv->index]);
144 * See if we've processed all the entries
147 if (serv->index == serv->total) {
149 *last_item_contains_data = 1;
160 GetDatabaseServerFromCache(void *rpc_specific, int slot, void *dest,
164 afs_status_t tst = 0;
165 database_server_get_p serv = (database_server_get_p) rpc_specific;
167 memcpy(dest, (const void *)&serv->server[slot],
168 sizeof(util_databaseServerEntry_t));
178 DestroyDatabaseServer(void *rpc_specific, afs_status_p st)
181 afs_status_t tst = 0;
182 database_server_get_p serv = (database_server_get_p) rpc_specific;
184 afsconf_Close(serv->conf);
194 * util_DatabaseServerGetBegin - begin iterating over the database
195 * server machines in a cell.
199 * IN cellName - the cell where database servers reside.
201 * OUT iterationIdP - upon successful completion contains an iterator that
202 * can be passed to util_DatabaseServerGetNext.
206 * No locks are obtained or released by this function
214 * Returns != 0 upon successful completion.
218 util_DatabaseServerGetBegin(const char *cellName, void **iterationIdP,
222 afs_status_t tst = 0;
223 afs_admin_iterator_p iter =
224 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
225 database_server_get_p serv =
226 (database_server_get_p) calloc(1, sizeof(database_server_get_t));
227 char copyCell[MAXCELLCHARS];
233 if ((cellName == NULL) || (*cellName == 0)) {
234 tst = ADMUTILCELLNAMENULL;
235 goto fail_util_DatabaseServerGetBegin;
238 if (iterationIdP == NULL) {
239 goto fail_util_DatabaseServerGetBegin;
242 if ((iter == NULL) || (serv == NULL)) {
244 goto fail_util_DatabaseServerGetBegin;
248 * Fill in the serv structure
251 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
252 if (serv->conf == NULL) {
253 tst = ADMUTILCANTOPENCELLSERVDB;
254 goto fail_util_DatabaseServerGetBegin;
258 * We must copy the cellname because afsconf_GetCellInfo
259 * actually writes over the cell name it is passed.
261 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
263 afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
266 goto fail_util_DatabaseServerGetBegin;
269 serv->total = serv->cell.numServers;
271 (iter, (void *)serv, GetDatabaseServerRPC, GetDatabaseServerFromCache,
272 NULL, DestroyDatabaseServer, &tst)) {
273 *iterationIdP = (void *)iter;
275 goto fail_util_DatabaseServerGetBegin;
279 fail_util_DatabaseServerGetBegin:
297 * util_DatabaseServerGetNext - get the next server address.
301 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
303 * OUT serverAddressP - upon successful completion contains the next
304 * server address in the cell.
308 * This function locks the iterator for the duration of its processing.
316 * Returns != 0 upon successful completion.
321 util_DatabaseServerGetNext(const void *iterationId,
322 util_databaseServerEntry_p serverP,
326 afs_status_t tst = 0;
327 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
330 tst = ADMITERATORNULL;
331 goto fail_util_DatabaseServerGetNext;
334 if (serverP == NULL) {
335 tst = ADMUTILSERVERADDRESSPNULL;
336 goto fail_util_DatabaseServerGetNext;
339 rc = IteratorNext(iter, (void *)serverP, &tst);
341 fail_util_DatabaseServerGetNext:
350 * util_DatabaseServerGetDone - stop using a database iterator.
354 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
358 * This function locks the iterator for the duration of its processing.
359 * And then destroys it before returning.
367 * Returns != 0 upon successful completion.
371 util_DatabaseServerGetDone(const void *iterationId, afs_status_p st)
374 afs_status_t tst = 0;
375 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
378 * Validate parameters
382 tst = ADMITERATORNULL;
383 goto fail_util_DatabaseServerGetDone;
386 rc = IteratorDone(iter, &tst);
388 fail_util_DatabaseServerGetDone:
397 * GetServerAddressFromName - translate a character string server name
398 * to an integer representation of an IP address.
402 * IN serverName - the character string server name in either foo.com
403 * format, or 123.12.1.1 format.
405 * OUT serverAddress - an integer that is filled with the correct address
406 * in host byte order upon successful completion.
410 * No locks are obtained or released by this function
414 * On many platforms, gethostbyname is not thread safe. Since we are
415 * only working under NT for now I'll use it directly. In future UNIX
416 * ports, a wrapper function should be written to call the correct function
417 * on the particular platform.
421 * Returns != 0 upon successful completion.
425 util_AdminServerAddressGetFromName(const char *serverName, int *serverAddress,
429 afs_status_t tst = 0;
430 struct hostent *server;
431 int part1, part2, part3, part4;
434 if ((serverName == NULL) || (*serverName == 0)) {
435 tst = ADMUTILSERVERNAMENULL;
436 goto fail_util_AdminServerAddressGetFromName;
439 if (serverAddress == NULL) {
440 tst = ADMUTILSERVERADDRESSNULL;
441 goto fail_util_AdminServerAddressGetFromName;
445 sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
446 if (num_converted == 4) {
447 *serverAddress = (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
450 server = gethostbyname(serverName);
451 if (server != NULL) {
452 memcpy((void *)serverAddress, (const void *)server->h_addr,
454 *serverAddress = ntohl(*serverAddress);
456 tst = ADMUTILCANTGETSERVERNAME;
458 goto fail_util_AdminServerAddressGetFromName;
464 fail_util_AdminServerAddressGetFromName:
474 * This file contains functions that can be used to create iterator
475 * functions within the api. I have attempted to make these functions
476 * generic so that they can be used across the admin components.
478 * The functions in this file are a generalized producer/consumer
479 * implementation. They manage access to a queue of data. The only
480 * assumption these functions make about this data is that it is
481 * stored in a queue which is implemented via an array. These functions
482 * know about the index into the array, but they know nothing about
483 * the contents of the array.
485 * The data specific functions you implement will have to create some
486 * data specific storage structure that will have an array
487 * of size CACHED_ITEMS data items. This structure will also need to
488 * store any necessary parameters/state variables you need to issue the
489 * rpc to retrieve the next item.
491 * In order to use the generic functions, you must implement four functions
492 * for each type of data you wish to retrieve. The functions are:
494 * validate_specific_data_func - this function is handed a void pointer
495 * that points to the rpc specific data you've allocated. The function
496 * should examine the data for validity and return an appropriate error.
497 * This function is called every time the iterator is validated.
499 * destroy_specific_data_func - this function is handed a void pointer
500 * that points to the rpc specific data you've allocated. It should
501 * destroy any components of the specific data as required and then
502 * return. The void pointer is free'd by the generic functions.
504 * get_cached_data_func - this function is handed a void pointer
505 * that points to the rpc specific data you've allocated, an index
506 * into the cache of the item to be copied to the caller, and a void
507 * pointer where the cache item should be copied.
509 * make_rpc_func - this function is handed a void pointer that points
510 * to the rpc specific data you've allocated, an index into the cache
511 * of the item to be filled with the next retrieved item, and an int
512 * pointer that should be set to 1 if there are no more items to be
513 * retrieved. The assumption made by the generic functions is that
514 * the last_item status requires an individual rpc - the data isn't
515 * piggybacked on the last data item.
519 * IteratorDelete - delete an iterator.
523 * IN interator - the iterator to delete.
527 * No locks are held by this function.
531 * Returns != 0 upon successful completion.
535 IteratorDelete(afs_admin_iterator_p iter, afs_status_p st)
538 afs_status_t tst = 0;
540 if (pthread_mutex_destroy(&iter->mutex)) {
541 tst = ADMMUTEXDESTROY;
542 goto fail_IteratorDelete;
544 if (pthread_cond_destroy(&iter->add_item)) {
545 tst = ADMCONDDESTROY;
546 goto fail_IteratorDelete;
548 if (pthread_cond_destroy(&iter->remove_item)) {
549 tst = ADMCONDDESTROY;
550 goto fail_IteratorDelete;
553 if (iter->destroy_specific != NULL) {
554 iter->destroy_specific(iter->rpc_specific, &tst);
556 free(iter->rpc_specific);
569 * DataGet - the background thread that is spawned for every
570 * IteratorBegin call that is successful. This thread tries
571 * to fetch the data from the server ahead of the
572 * IteratorNext calls.
576 * IN arg - the address of the iterator structure to be used for this
581 * The iterator mutex is used by this function to protect elements
582 * of the iterator structure.
586 * Returns != 0 upon successful completion.
592 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
594 afs_status_t tst = 0;
595 int mutex_locked = 0;
597 int last_item_contains_data = 0;
599 if (pthread_mutex_lock(&iter->mutex)) {
600 iter->st = ADMMUTEXLOCK;
609 * Check to see if there's room for this datum. If not, wait
610 * on the consumer to free up another slot.
613 while (iter->cache_slots_used == CACHED_ITEMS) {
614 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
615 iter->st = ADMCONDWAIT;
621 * Check to see if someone called Done and terminated the request.
622 * We could have gone to sleep above when the buffer was full and
623 * instead of being awoken because another slot is open, we were
624 * awoken because the request was terminated.
627 if (iter->request_terminated) {
631 if (pthread_mutex_unlock(&iter->mutex)) {
632 iter->st = ADMMUTEXUNLOCK;
639 * Make an rpc without holding the iter mutex
640 * We reference an item in the principal cache here without
641 * holding the mutex. This is safe because:
642 * 1. The iter structure is ref counted and won't be deleted
643 * from underneath us.
644 * 2. cache_queue_tail is always one item ahead of the consumer
645 * thread so we are the only thread accessing this member.
648 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail, &last_item,
649 &last_item_contains_data, &tst);
651 if (pthread_mutex_lock(&iter->mutex)) {
652 iter->st = ADMMUTEXLOCK;
659 * Check to see if someone called Done and terminated the request
662 if (iter->request_terminated) {
667 * Check the rc of the rpc, and see if there are no more items
677 * Check to see if this is the last item produced by the rpc.
678 * If it isn't, add the item to the cache and proceed.
679 * If it is, check to see if the last item contains valid data.
680 * If it contains valid data, we need to add it to our cache.
681 * If it doesn't, we mark the iterator as complete.
684 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
685 iter->cache_queue_tail =
686 (iter->cache_queue_tail + 1) % CACHED_ITEMS;
687 iter->cache_slots_used++;
690 iter->st = ADMITERATORDONE;
691 iter->done_iterating = 1;
693 * There's a small chance that the consumer emptied the
694 * cache queue while we were making the last rpc and has
695 * since gone to sleep waiting for more data. In this case
696 * there will never be more data so we signal him here.
698 pthread_cond_signal(&iter->add_item);
704 * If the cache was empty and we just added another item, signal
708 if (iter->cache_slots_used == 1) {
709 if (pthread_cond_signal(&iter->add_item)) {
710 iter->st = ADMCONDSIGNAL;
720 * If we are exiting with an error, signal the consumer in the event
721 * they were waiting for us to produce more data
725 pthread_cond_signal(&iter->add_item);
729 pthread_mutex_unlock(&iter->mutex);
736 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
740 * IN interator - the interator to be verified.
744 * We assume the iter->mutex lock is already held.
748 * Returns != 0 upon successful completion.
752 IsValidIterator(const afs_admin_iterator_p iterator, afs_status_p st)
755 afs_status_t tst = 0;
758 * Validate input parameters
761 if (iterator == NULL) {
762 tst = ADMITERATORNULL;
763 goto fail_IsValidIterator;
766 if ((iterator->begin_magic != BEGIN_MAGIC)
767 || (iterator->end_magic != END_MAGIC)) {
768 tst = ADMITERATORBADMAGICNULL;
769 goto fail_IsValidIterator;
772 if (iterator->is_valid == 0) {
773 tst = ADMITERATORINVALID;
774 goto fail_IsValidIterator;
778 * Call the iterator specific validation function
781 if (iterator->validate_specific != NULL) {
782 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
783 goto fail_IsValidIterator;
788 fail_IsValidIterator:
797 * IteratorNext - return the next datum in an interator.
801 * IN interator - the iterator containing the data.
803 * IN dest - the address where the data should be copied.
807 * Lock the iterator upon entry, and hold it during the duration of this
812 * Returns != 0 upon successful completion.
816 IteratorNext(afs_admin_iterator_p iter, void *dest, afs_status_p st)
819 afs_status_t tst = 0;
823 * We have to lock the iterator before we validate it
826 if (pthread_mutex_lock(&iter->mutex)) {
828 goto fail_IteratorNext;
833 if (!IsValidIterator(iter, &tst)) {
834 goto fail_IteratorNext;
837 if (iter->request_terminated == 1) {
838 tst = ADMITERATORTERMINATED;
839 goto fail_IteratorNext;
842 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
844 goto fail_IteratorNext;
848 * Check to see if there are any queue'd items. If not, wait here
849 * until signalled by the producer.
852 while (iter->cache_slots_used == 0) {
855 * Maybe the producer experienced an rpc failure.
858 if ((!iter->done_iterating) && (iter->st != 0)) {
860 goto fail_IteratorNext;
864 * Maybe there are no queue'd items because the producer is done
867 if (iter->done_iterating) {
869 goto fail_IteratorNext;
872 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
874 goto fail_IteratorNext;
879 * Copy the next cached item and update the cached item count
880 * and the index into the cache array
884 get_cached_data(iter->rpc_specific, iter->cache_queue_head, dest,
886 goto fail_IteratorNext;
889 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
890 iter->cache_slots_used--;
893 * If the cache was full before we removed the item above, the
894 * producer may have been waiting for us to remove an item.
895 * Signal the producer letting him know that we've opened a slot
899 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
900 if (pthread_cond_signal(&iter->remove_item)) {
902 goto fail_IteratorNext;
910 if (locked_iter == 1) {
911 pthread_mutex_unlock(&iter->mutex);
921 * IteratorDone - mark the iterator done.
925 * IN interator - the iterator to mark done.
929 * Lock the iterator upon entry, and hold it during the duration of this
934 * Returns != 0 upon successful completion.
938 IteratorDone(afs_admin_iterator_p iter, afs_status_p st)
941 afs_status_t tst = 0;
942 int mutex_locked = 1;
944 if (pthread_mutex_lock(&iter->mutex)) {
946 goto fail_IteratorDone;
952 if (!IsValidIterator(iter, &tst)) {
953 goto fail_IteratorDone;
958 * Depending upon the status of the background worker thread,
959 * we can either join with him immediately (if we know he has
960 * terminated), or we need to tell him the request has been
961 * terminated and then join with him.
964 if (!iter->done_iterating) {
965 iter->request_terminated = 1;
966 iter->cache_slots_used = 0;
967 pthread_cond_signal(&iter->remove_item);
971 * We have to unlock the mutex to allow the background thread to
975 if (pthread_mutex_unlock(&iter->mutex)) {
976 tst = ADMMUTEXUNLOCK;
977 goto fail_IteratorDone;
980 if (iter->make_rpc != NULL) {
981 if (pthread_join(iter->bg_worker, (void **)0)) {
983 goto fail_IteratorDone;
988 * We don't relock the mutex here since we are the only thread
989 * that has access to the iter now
992 rc = IteratorDelete(iter, &tst);
998 pthread_mutex_unlock(&iter->mutex);
1008 * IteratorInit - initialize an iterator.
1012 * IN interator - the iterator to initialize.
1016 * No locks are held by this function.
1020 * Returns != 0 upon successful completion.
1024 IteratorInit(afs_admin_iterator_p iter, void *rpc_specific,
1025 make_rpc_func make_rpc, get_cached_data_func get_cached_data,
1026 validate_specific_data_func validate_specific_data,
1027 destroy_specific_data_func destroy_specific_data,
1031 afs_status_t tst = 0;
1032 int mutex_inited = 0;
1033 int add_item_cond_inited = 0;
1034 int remove_item_cond_inited = 0;
1037 tst = ADMITERATORNULL;
1038 goto fail_IteratorInit;
1041 if (rpc_specific == NULL) {
1042 tst = ADMITERATORRPCSPECIFICNULL;
1043 goto fail_IteratorInit;
1047 * Initialize the iterator structure
1049 iter->begin_magic = BEGIN_MAGIC;
1050 iter->end_magic = END_MAGIC;
1052 iter->cache_slots_used = 0;
1053 iter->done_iterating = 0;
1054 iter->request_terminated = 0;
1055 iter->st = AFS_STATUS_OK;
1056 iter->cache_queue_head = 0;
1057 iter->cache_queue_tail = 0;
1058 iter->cache_slots_used = 0;
1059 iter->rpc_specific = rpc_specific;
1060 iter->make_rpc = make_rpc;
1061 iter->get_cached_data = get_cached_data;
1062 iter->validate_specific = validate_specific_data;
1063 iter->destroy_specific = destroy_specific_data;
1065 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *)0)) {
1067 goto fail_IteratorInit;
1072 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *)0)) {
1074 goto fail_IteratorInit;
1076 add_item_cond_inited = 1;
1079 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *)0)) {
1081 goto fail_IteratorInit;
1083 remove_item_cond_inited = 1;
1087 * Create a worker thread that will begin to query the server
1088 * and cache responses.
1091 if (iter->make_rpc != NULL) {
1092 pthread_attr_t tattr;
1094 if (pthread_attr_init(&tattr)) {
1095 tst = ADMTHREADATTRINIT;
1096 goto fail_IteratorInit;
1099 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1100 tst = ADMTHREADATTRSETDETACHSTATE;
1101 goto fail_IteratorInit;
1104 if (pthread_create(&iter->bg_worker, &tattr, DataGet, (void *)iter)) {
1105 tst = ADMTHREADCREATE;
1106 goto fail_IteratorInit;
1115 pthread_mutex_destroy(&iter->mutex);
1117 if (remove_item_cond_inited) {
1118 pthread_cond_destroy(&iter->remove_item);
1120 if (add_item_cond_inited) {
1121 pthread_cond_destroy(&iter->add_item);
1132 CellHandleIsValid(const void *cellHandle, afs_status_p st)
1135 afs_status_t tst = 0;
1136 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1139 * Validate input parameters
1142 if (c_handle == NULL) {
1143 tst = ADMCLIENTCELLHANDLENULL;
1144 goto fail_CellHandleIsValid;
1147 if ((c_handle->begin_magic != BEGIN_MAGIC)
1148 || (c_handle->end_magic != END_MAGIC)) {
1149 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1150 goto fail_CellHandleIsValid;
1153 if (c_handle->is_valid == 0) {
1154 tst = ADMCLIENTCELLINVALID;
1155 goto fail_CellHandleIsValid;
1159 fail_CellHandleIsValid:
1168 * The iterator functions and data for the rpc statistic retrieval functions
1171 typedef struct rpc_stat_get {
1172 afs_uint32 clock_sec;
1173 afs_uint32 clock_usec;
1176 afs_uint32 clientVersion;
1177 afs_uint32 serverVersion;
1178 struct rpcStats stat_list;
1179 afs_RPCStats_t stats[CACHED_ITEMS];
1180 afs_uint32 *pointer;
1181 } rpc_stat_get_t, *rpc_stat_get_p;
1184 UnmarshallRPCStats(afs_uint32 serverVersion, afs_uint32 ** ptrP,
1188 unsigned int hi, lo;
1191 * Server must always match lower versions. We are version 1.
1194 s->stats_v1.remote_peer = *(ptr++);
1195 s->stats_v1.remote_port = *(ptr++);
1196 s->stats_v1.remote_is_server = *(ptr++);
1197 s->stats_v1.interfaceId = *(ptr++);
1198 s->stats_v1.func_total = *(ptr++);
1199 s->stats_v1.func_index = *(ptr++);
1202 hset64(s->stats_v1.invocations, hi, lo);
1205 hset64(s->stats_v1.bytes_sent, hi, lo);
1208 hset64(s->stats_v1.bytes_rcvd, hi, lo);
1209 s->stats_v1.queue_time_sum.sec = *(ptr++);
1210 s->stats_v1.queue_time_sum.usec = *(ptr++);
1211 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1212 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1213 s->stats_v1.queue_time_min.sec = *(ptr++);
1214 s->stats_v1.queue_time_min.usec = *(ptr++);
1215 s->stats_v1.queue_time_max.sec = *(ptr++);
1216 s->stats_v1.queue_time_max.usec = *(ptr++);
1217 s->stats_v1.execution_time_sum.sec = *(ptr++);
1218 s->stats_v1.execution_time_sum.usec = *(ptr++);
1219 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1220 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1221 s->stats_v1.execution_time_min.sec = *(ptr++);
1222 s->stats_v1.execution_time_min.usec = *(ptr++);
1223 s->stats_v1.execution_time_max.sec = *(ptr++);
1224 s->stats_v1.execution_time_max.usec = *(ptr++);
1229 GetRPCStatsRPC(void *rpc_specific, int slot, int *last_item,
1230 int *last_item_contains_data, afs_status_p st)
1233 afs_status_t tst = 0;
1234 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1236 t->stats[slot].clientVersion = t->clientVersion;
1237 t->stats[slot].serverVersion = t->serverVersion;
1238 t->stats[slot].statCount = t->total;
1241 * If the server stat version is greater than or equal to my version
1242 * number, it is required to return the values in the client's current
1246 UnmarshallRPCStats(t->serverVersion, &t->pointer, &t->stats[slot].s);
1251 * See if we've processed all the entries
1254 if (t->index == t->total) {
1256 *last_item_contains_data = 1;
1267 GetRPCStatsFromCache(void *rpc_specific, int slot, void *dest,
1271 afs_status_t tst = 0;
1272 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1274 memcpy(dest, (const void *)&stat->stats[slot], sizeof(afs_RPCStats_t));
1284 DestroyRPCStats(void *rpc_specific, afs_status_p st)
1287 afs_status_t tst = 0;
1288 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1290 if (stat->stat_list.rpcStats_val != NULL) {
1291 free(stat->stat_list.rpcStats_val);
1302 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1306 * IN conn - an rx connection to the process to be queried
1308 * IN rpc - the function to call to make the actual rpc
1310 * OUT iterationIdP - an iteration id that can be passed to
1311 * util_RPCStatsGetNext to get the next rpc stat
1315 * No locks are obtained or released by this function
1319 * Returns != 0 upon successful completion.
1324 util_RPCStatsGetBegin(struct rx_connection *conn, int (*rpc) (),
1325 void **iterationIdP, afs_status_p st)
1328 afs_status_t tst = 0;
1329 afs_admin_iterator_p iter =
1330 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1331 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1334 tst = ADMRXCONNNULL;
1335 goto fail_util_RPCStatsGetBegin;
1339 tst = ADMRPCPTRNULL;
1340 goto fail_util_RPCStatsGetBegin;
1343 if (iterationIdP == NULL) {
1344 tst = ADMITERATIONIDPNULL;
1345 goto fail_util_RPCStatsGetBegin;
1348 if ((iter == NULL) || (stat == NULL)) {
1350 goto fail_util_RPCStatsGetBegin;
1353 stat->stat_list.rpcStats_len = 0;
1354 stat->stat_list.rpcStats_val = 0;
1356 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1359 (*rpc) (conn, stat->clientVersion, &stat->serverVersion,
1360 &stat->clock_sec, &stat->clock_usec, &stat->total,
1364 goto fail_util_RPCStatsGetBegin;
1368 * If there are no statistics, just mark the iterator done and
1372 if (stat->stat_list.rpcStats_len == 0) {
1373 stat->pointer = NULL;
1374 if (!IteratorInit(iter, (void *)stat, NULL, NULL, NULL, NULL, &tst)) {
1375 goto fail_util_RPCStatsGetBegin;
1377 iter->done_iterating = 1;
1378 iter->st = ADMITERATORDONE;
1380 stat->pointer = stat->stat_list.rpcStats_val;
1382 (iter, (void *)stat, GetRPCStatsRPC, GetRPCStatsFromCache, NULL,
1383 DestroyRPCStats, &tst)) {
1384 goto fail_util_RPCStatsGetBegin;
1387 *iterationIdP = (void *)iter;
1390 fail_util_RPCStatsGetBegin:
1408 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1412 * IN iterationId - an iterator previously returned by
1413 * util_RPCStatsGetBegin.
1415 * OUT stats - upon successful completion contains the next set of stats
1420 * No locks are obtained or released by this function
1424 * Returns != 0 upon successful completion.
1429 util_RPCStatsGetNext(const void *iterationId, afs_RPCStats_p stats,
1433 afs_status_t tst = 0;
1434 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1436 if (iterationId == NULL) {
1437 tst = ADMITERATIONIDPNULL;
1438 goto fail_util_RPCStatsGetNext;
1441 if (stats == NULL) {
1442 tst = ADMUTILRPCSTATSNULL;
1443 goto fail_util_RPCStatsGetNext;
1446 rc = IteratorNext(iter, (void *)stats, &tst);
1448 fail_util_RPCStatsGetNext:
1457 * util_RPCStatsGetDone - finish using a stats iterator
1461 * IN iterationId - an iterator previously returned by
1462 * util_RPCStatsGetBegin.
1466 * No locks are obtained or released by this function
1470 * Returns != 0 upon successful completion.
1475 util_RPCStatsGetDone(const void *iterationId, afs_status_p st)
1478 afs_status_t tst = 0;
1479 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1481 if (iterationId == NULL) {
1482 tst = ADMITERATIONIDPNULL;
1483 goto fail_util_RPCStatsGetDone;
1486 rc = IteratorDone(iter, &tst);
1488 fail_util_RPCStatsGetDone:
1497 * util_RPCStatsStateGet - get the current state of rpc stat collection
1501 * IN conn - an rx connection to the process to be queried
1503 * IN rpc - the function to call to make the actual rpc
1505 * OUT state - the rpc stat collection state.
1509 * No locks are obtained or released by this function
1513 * Returns != 0 upon successful completion.
1518 util_RPCStatsStateGet(struct rx_connection *conn, int (*rpc) (),
1519 afs_RPCStatsState_p state, afs_status_p st)
1522 afs_status_t tst = 0;
1525 tst = ADMRXCONNNULL;
1526 goto fail_util_RPCStatsStateGet;
1530 tst = ADMRPCPTRNULL;
1531 goto fail_util_RPCStatsStateGet;
1534 if (state == NULL) {
1535 tst = ADMRPCSTATENULL;
1536 goto fail_util_RPCStatsStateGet;
1539 tst = (*rpc) (conn, state);
1545 fail_util_RPCStatsStateGet:
1554 * util_RPCStatsStateEnable - enable rpc stat collection
1559 * IN conn - an rx connection to the process to be modified
1561 * IN rpc - the function to call to make the actual rpc
1565 * No locks are obtained or released by this function
1569 * Returns != 0 upon successful completion.
1574 util_RPCStatsStateEnable(struct rx_connection *conn, int (*rpc) (),
1578 afs_status_t tst = 0;
1581 tst = ADMRXCONNNULL;
1582 goto fail_util_RPCStatsStateEnable;
1586 tst = ADMRPCPTRNULL;
1587 goto fail_util_RPCStatsStateEnable;
1590 tst = (*rpc) (conn);
1596 fail_util_RPCStatsStateEnable:
1605 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1610 * IN conn - an rx connection to the process to be modified
1612 * IN rpc - the function to call to make the actual rpc
1616 * No locks are obtained or released by this function
1620 * Returns != 0 upon successful completion.
1625 util_RPCStatsStateDisable(struct rx_connection *conn, int (*rpc) (),
1629 afs_status_t tst = 0;
1632 tst = ADMRXCONNNULL;
1633 goto fail_util_RPCStatsStateDisable;
1637 tst = ADMRPCPTRNULL;
1638 goto fail_util_RPCStatsStateDisable;
1641 tst = (*rpc) (conn);
1647 fail_util_RPCStatsStateDisable:
1656 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1657 * collection at a server
1661 * IN conn - an rx connection to the process to be modified
1663 * IN rpc - the function to call to make the actual rpc
1665 * IN flag - a flag containing the fields to be cleared
1670 * No locks are obtained or released by this function
1674 * Returns != 0 upon successful completion.
1679 util_RPCStatsClear(struct rx_connection *conn, int (*rpc) (),
1680 afs_RPCStatsClearFlag_t flag, afs_status_p st)
1683 afs_status_t tst = 0;
1686 tst = ADMRXCONNNULL;
1687 goto fail_util_RPCStatsClear;
1691 tst = ADMRPCPTRNULL;
1692 goto fail_util_RPCStatsClear;
1695 tst = (*rpc) (conn, flag);
1701 fail_util_RPCStatsClear:
1710 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1714 * IN conn - an rx connection to the process to be modified
1716 * OUT version - the version of rpc stat collection at the remote process
1720 * No locks are obtained or released by this function
1724 * Returns != 0 upon successful completion.
1729 util_RPCStatsVersionGet(struct rx_connection *conn,
1730 afs_RPCStatsVersion_p version, afs_status_p st)
1733 afs_status_t tst = 0;
1736 tst = ADMRXCONNNULL;
1737 goto fail_util_RPCStatsVersionGet;
1740 if (version == NULL) {
1741 tst = ADMRPCVERSIONNULL;
1742 goto fail_util_RPCStatsVersionGet;
1745 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1751 fail_util_RPCStatsVersionGet:
1760 * The iterator for listing CM server preferences
1763 typedef struct cm_srvr_pref_get {
1764 struct rx_connection *conn;
1766 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1767 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1770 GetServerPrefsRPC(void *rpc_specific, int slot, int *last_item,
1771 int *last_item_contains_data, afs_status_p st)
1774 afs_status_t tst = 0;
1775 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1778 * Get the next entry in the list of server preferences.
1781 RXAFSCB_GetServerPrefs(t->conn, t->index, &t->srvrPrefs[slot].ipAddr,
1782 &t->srvrPrefs[slot].ipRank);
1784 goto fail_GetServerPrefsRPC;
1788 * See if we've processed all the entries
1790 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1792 *last_item_contains_data = 0;
1798 fail_GetServerPrefsRPC:
1807 GetServerPrefsFromCache(void *rpc_specific, int slot, void *dest,
1811 afs_status_t tst = 0;
1812 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1814 memcpy(dest, (const void *)&prefs->srvrPrefs[slot],
1815 sizeof(afs_CMServerPref_t));
1825 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1829 * IN conn - an rx connection to the process to be queried
1831 * OUT iterationIdP - an iteration id that can be passed to
1832 * util_CMGetServerPrefsNext to get the next server preference
1836 * No locks are obtained or released by this function
1840 * Returns != 0 upon successful completion.
1845 util_CMGetServerPrefsBegin(struct rx_connection *conn, void **iterationIdP,
1849 afs_status_t tst = 0;
1850 afs_admin_iterator_p iter;
1851 cm_srvr_pref_get_p pref;
1854 tst = ADMRXCONNNULL;
1855 goto fail_util_CMGetServerPrefsBegin;
1858 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1861 goto fail_util_CMGetServerPrefsBegin;
1864 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1868 goto fail_util_CMGetServerPrefsBegin;
1874 (iter, (void *)pref, GetServerPrefsRPC, GetServerPrefsFromCache, NULL,
1878 goto fail_util_CMGetServerPrefsBegin;
1880 *iterationIdP = (void *)iter;
1883 fail_util_CMGetServerPrefsBegin:
1892 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1897 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1899 * OUT prefs - Next entry in cache manager server preferences.
1903 * No locks are obtained or released by this function
1907 * Returns != 0 upon successful completion.
1912 util_CMGetServerPrefsNext(const void *iterationId, afs_CMServerPref_p prefs,
1916 afs_status_t tst = 0;
1917 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1919 if (iterationId == NULL) {
1920 tst = ADMITERATIONIDPNULL;
1921 goto fail_util_CMGetServerPrefsNext;
1924 rc = IteratorNext(iter, (void *)prefs, &tst);
1926 fail_util_CMGetServerPrefsNext:
1935 * util_CMGetServerPrefsDone - Finish listing cache manager server
1940 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1944 * No locks are obtained or released by this function
1948 * Returns != 0 upon successful completion.
1953 util_CMGetServerPrefsDone(const void *iterationId, afs_status_p st)
1956 afs_status_t tst = 0;
1957 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1959 if (iterationId == NULL) {
1960 tst = ADMITERATIONIDPNULL;
1961 goto fail_util_CMGetServerPrefsDone;
1964 rc = IteratorDone(iter, &tst);
1967 fail_util_CMGetServerPrefsDone:
1976 * The iterator for listing CM CellServDB
1979 typedef struct cm_list_cell_get {
1980 struct rx_connection *conn;
1982 afs_CMListCell_t cell[CACHED_ITEMS];
1983 } cm_list_cell_get_t, *cm_list_cell_get_p;
1986 ListCellsRPC(void *rpc_specific, int slot, int *last_item,
1987 int *last_item_contains_data, afs_status_p st)
1990 afs_status_t tst = 0;
1991 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
1995 * Get the next entry in the CellServDB.
1997 name = t->cell[slot].cellname;
1999 RXAFSCB_GetCellServDB(t->conn, t->index, &name,
2000 t->cell[slot].serverAddr);
2002 goto fail_ListCellsRPC;
2004 strcpy(t->cell[slot].cellname, name);
2007 * See if we've processed all the entries
2009 if (strlen(t->cell[slot].cellname) == 0) {
2011 *last_item_contains_data = 0;
2026 ListCellsFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2029 afs_status_t tst = 0;
2030 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2032 memcpy(dest, (const void *)&cell->cell[slot], sizeof(afs_CMListCell_t));
2042 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2046 * IN conn - an rx connection to the process to be queried
2048 * OUT iterationIdP - an iteration id that can be passed to
2049 * util_CMListCellsNext to get the next cell
2053 * No locks are obtained or released by this function
2057 * Returns != 0 upon successful completion.
2062 util_CMListCellsBegin(struct rx_connection *conn, void **iterationIdP,
2066 afs_status_t tst = 0;
2067 afs_admin_iterator_p iter;
2068 cm_list_cell_get_p cell;
2071 tst = ADMRXCONNNULL;
2072 goto fail_util_CMListCellsBegin;
2075 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2078 goto fail_util_CMListCellsBegin;
2081 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2085 goto fail_util_CMListCellsBegin;
2091 (iter, (void *)cell, ListCellsRPC, ListCellsFromCache, NULL, NULL,
2095 goto fail_util_CMListCellsBegin;
2097 *iterationIdP = (void *)iter;
2100 fail_util_CMListCellsBegin:
2109 * util_CMListCellsNext - Get next entry in cache manager cells
2113 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2115 * OUT cell - Next entry in cache manager cells.
2119 * No locks are obtained or released by this function
2123 * Returns != 0 upon successful completion.
2128 util_CMListCellsNext(const void *iterationId, afs_CMListCell_p cell,
2132 afs_status_t tst = 0;
2133 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2135 if (iterationId == NULL) {
2136 tst = ADMITERATIONIDPNULL;
2137 goto fail_util_CMListCellsNext;
2140 rc = IteratorNext(iter, (void *)cell, &tst);
2142 fail_util_CMListCellsNext:
2151 * util_CMListCellsDone - Finish listing cache manager cells
2155 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2159 * No locks are obtained or released by this function
2163 * Returns != 0 upon successful completion.
2168 util_CMListCellsDone(const void *iterationId, afs_status_p st)
2171 afs_status_t tst = 0;
2172 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2174 if (iterationId == NULL) {
2175 tst = ADMITERATIONIDPNULL;
2176 goto fail_util_CMListCellsDone;
2179 rc = IteratorDone(iter, &tst);
2182 fail_util_CMListCellsDone:
2191 * util_CMLocalCell - Get the name of the cache manager's local cell.
2195 * IN conn - an rx connection to the process to be queried
2197 * OUT cellName - the name of the cache manager's local cell.
2201 * No locks are obtained or released by this function
2205 * Returns != 0 upon successful completion.
2210 util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
2214 afs_status_t tst = 0;
2215 afs_CMCellName_p name;
2218 tst = ADMRXCONNNULL;
2219 goto fail_util_CMLocalCell;
2222 if (cellName == NULL) {
2223 tst = ADMCLIENTCMCELLNAMENULL;
2224 goto fail_util_CMLocalCell;
2228 tst = RXAFSCB_GetLocalCell(conn, &name);
2234 fail_util_CMLocalCell:
2243 UnmarshallCMClientConfig(afs_uint32 serverVersion, afs_uint32 * ptr,
2244 afs_ClientConfigUnion_p config)
2247 * We currently only support version 1.
2249 config->config_v1.nChunkFiles = *(ptr++);
2250 config->config_v1.nStatCaches = *(ptr++);
2251 config->config_v1.nDataCaches = *(ptr++);
2252 config->config_v1.nVolumeCaches = *(ptr++);
2253 config->config_v1.firstChunkSize = *(ptr++);
2254 config->config_v1.otherChunkSize = *(ptr++);
2255 config->config_v1.cacheSize = *(ptr++);
2256 config->config_v1.setTime = *(ptr++);
2257 config->config_v1.memCache = *(ptr++);
2261 * util_CMClientConfig - Get the cache manager's configuration parameters.
2265 * IN conn - an rx connection to the process to be queried
2267 * OUT config - the cache manager's configuration parameters.
2271 * No locks are obtained or released by this function
2275 * Returns != 0 upon successful completion.
2280 util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
2284 afs_status_t tst = 0;
2285 afs_int32 allocbytes;
2286 struct cacheConfig tconfig;
2289 tst = ADMRXCONNNULL;
2290 goto fail_util_CMClientConfig;
2293 if (config == NULL) {
2294 tst = ADMCLIENTCMCELLNAMENULL;
2295 goto fail_util_CMClientConfig;
2298 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2299 tconfig.cacheConfig_val = NULL;
2300 tconfig.cacheConfig_len = 0;
2302 RXAFSCB_GetCacheConfig(conn, config->clientVersion,
2303 &config->serverVersion, &allocbytes, &tconfig);
2306 goto fail_util_CMClientConfig;
2309 UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
2312 free(tconfig.cacheConfig_val);
2314 fail_util_CMClientConfig:
2323 * util_RXDebugVersion - Get the rxdebug version string.
2327 * IN handle - an rxdebug handle for the process to be queried.
2329 * OUT version - the rxdebug version string.
2333 * No locks are obtained or released by this function
2337 * Returns != 0 upon successful completion.
2342 util_RXDebugVersion(rxdebugHandle_p handle, rxdebugVersion_p version,
2346 afs_status_t tst = 0;
2349 if (handle == NULL) {
2350 tst = ADMRXDEBUGHANDLENULL;
2351 goto fail_util_RXDebugVersion;
2354 if (version == NULL) {
2355 tst = ADMRXDEBUGVERSIONNULL;
2356 goto fail_util_RXDebugVersion;
2360 rx_GetServerVersion(handle->sock, handle->ipAddr, handle->udpPort,
2361 UTIL_MAX_RXDEBUG_VERSION_LEN, version);
2363 tst = ADMCLIENTRXDEBUGTIMEOUT;
2364 goto fail_util_RXDebugVersion;
2369 fail_util_RXDebugVersion:
2378 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2383 * IN handle - an rxdebug handle for the process to be queried.
2385 * OUT supportedStats - bit mask with supported rxstats.
2389 * No locks are obtained or released by this function
2393 * Returns != 0 upon successful completion.
2398 util_RXDebugSupportedStats(rxdebugHandle_p handle,
2399 afs_uint32 * supportedStats, afs_status_p st)
2402 afs_status_t tst = 0;
2403 struct rx_debugStats tstats;
2405 if (handle == NULL) {
2406 tst = ADMRXDEBUGHANDLENULL;
2407 goto fail_util_RXDebugSupportedStats;
2410 if (supportedStats == NULL) {
2411 tst = ADMRXDEBUGSTATSNULL;
2412 goto fail_util_RXDebugSupportedStats;
2415 if (handle->firstFlag) {
2416 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2418 goto fail_util_RXDebugSupportedStats;
2422 *supportedStats = handle->supportedStats;
2425 fail_util_RXDebugSupportedStats:
2435 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2439 * IN handle - an rxdebug handle for the process to be queried.
2441 * OUT stats - Basic rxdebug statistics for the process.
2445 * No locks are obtained or released by this function
2449 * Returns != 0 upon successful completion.
2454 util_RXDebugBasicStats(rxdebugHandle_p handle, struct rx_debugStats *stats,
2458 afs_status_t tst = 0;
2461 if (handle == NULL) {
2462 tst = ADMRXDEBUGHANDLENULL;
2463 goto fail_util_RXDebugBasicStats;
2466 if (stats == NULL) {
2467 tst = ADMRXDEBUGSTATSNULL;
2468 goto fail_util_RXDebugBasicStats;
2472 rx_GetServerDebug(handle->sock, handle->ipAddr, handle->udpPort,
2473 stats, &handle->supportedStats);
2475 tst = ADMCLIENTRXDEBUGTIMEOUT;
2476 goto fail_util_RXDebugBasicStats;
2479 handle->firstFlag = 0;
2482 fail_util_RXDebugBasicStats:
2492 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2496 * IN handle - an rxdebug handle for the process to be queried.
2498 * OUT stats - Detailed rxdebug statistics for the process.
2502 * No locks are obtained or released by this function
2506 * Returns != 0 upon successful completion.
2511 util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_stats *stats,
2512 afs_uint32 * supportedValues, afs_status_p st)
2516 afs_status_t tst = 0;
2518 afs_uint32 tsupported;
2520 if (handle == NULL) {
2521 tst = ADMRXDEBUGHANDLENULL;
2522 goto fail_util_RXDebugRxStats;
2525 if (supportedValues == NULL) {
2526 tst = ADMRXDEBUGSTATSNULL;
2527 goto fail_util_RXDebugRxStats;
2530 if (stats == NULL) {
2531 tst = ADMRXDEBUGSTATSNULL;
2532 goto fail_util_RXDebugRxStats;
2535 if (handle->firstFlag) {
2536 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2539 goto fail_util_RXDebugRxStats;
2543 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2544 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2545 goto fail_util_RXDebugRxStats;
2549 rx_GetServerStats(handle->sock, handle->ipAddr, handle->udpPort,
2550 stats, &handle->supportedStats);
2552 tst = ADMCLIENTRXDEBUGTIMEOUT;
2553 goto fail_util_RXDebugRxStats;
2558 fail_util_RXDebugRxStats:
2567 * The iterator for listing RXDebug connections
2570 typedef struct rxdebug_conn_item {
2571 struct rx_debugConn conn;
2572 afs_uint32 supportedValues;
2573 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2575 typedef struct rxdebug_conn_get {
2577 rxdebugHandle_p handle;
2579 rxdebug_conn_item_t items[CACHED_ITEMS];
2580 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2583 RXDebugConnsFromServer(void *rpc_specific, int slot, int *last_item,
2584 int *last_item_contains_data, afs_status_p st)
2588 afs_status_t tst = 0;
2589 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2592 * Get the next entry the list of connections
2595 rx_GetServerConnections(t->handle->sock, t->handle->ipAddr,
2596 t->handle->udpPort, &t->index, t->allconns,
2597 t->handle->supportedStats,
2598 &t->items[slot].conn,
2599 &t->items[slot].supportedValues);
2601 tst = ADMCLIENTRXDEBUGTIMEOUT;
2602 goto fail_ListCellsRPC;
2606 * See if we've processed all the entries
2608 if (t->items[slot].conn.cid == 0xffffffff) {
2610 *last_item_contains_data = 0;
2623 RXDebugConnsFromCache(void *rpc_specific, int slot, void *dest,
2627 afs_status_t tst = 0;
2628 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2630 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_conn_item_t));
2640 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2645 * IN handle - an rxdebug handle for the process to be queried
2647 * IN allcons - non-zero to list all connections. If zero, only
2648 * "interesting" connections will be listed.
2650 * OUT iterationIdP - an iteration id that can be passed to
2651 * util_RXDebugConnectionsNext.
2655 * No locks are obtained or released by this function
2659 * Returns != 0 upon successful completion.
2664 util_RXDebugConnectionsBegin(rxdebugHandle_p handle, int allconns,
2665 void **iterationIdP, afs_status_p st)
2669 afs_uint32 tsupported;
2670 afs_status_t tst = 0;
2671 afs_admin_iterator_p iter;
2672 rxdebug_conn_get_p t;
2674 if (handle == NULL) {
2675 tst = ADMRXDEBUGHANDLENULL;
2676 goto fail_util_RXDebugConnectionsBegin;
2679 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2682 goto fail_util_RXDebugConnectionsBegin;
2685 if (handle->firstFlag) {
2686 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2689 goto fail_util_RXDebugConnectionsBegin;
2693 if (allconns && !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2694 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2695 goto fail_util_RXDebugConnectionsBegin;
2698 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2702 goto fail_util_RXDebugConnectionsBegin;
2705 t->allconns = allconns;
2709 (iter, (void *)t, RXDebugConnsFromServer, RXDebugConnsFromCache, NULL,
2711 goto fail_util_RXDebugConnectionsBegin;
2713 *iterationIdP = (void *)iter;
2716 fail_util_RXDebugConnectionsBegin:
2726 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2731 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2733 * OUT conn - Rxdebug information for the next connection.
2735 * OUT supportedValues - Bit mask of supported rxdebug values.
2739 * No locks are obtained or released by this function
2743 * Returns != 0 upon successful completion.
2748 util_RXDebugConnectionsNext(const void *iterationId,
2749 struct rx_debugConn *conn,
2750 afs_uint32 * supportedValues, afs_status_p st)
2753 afs_status_t tst = 0;
2754 rxdebug_conn_item_t item;
2755 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2757 if (iterationId == NULL) {
2758 tst = ADMITERATIONIDPNULL;
2759 goto fail_util_RXDebugConnectionsNext;
2763 tst = ADMRXDEBUGHANDLENULL;
2764 goto fail_util_RXDebugConnectionsNext;
2767 if (supportedValues == NULL) {
2768 tst = ADMRXDEBUGHANDLENULL;
2769 goto fail_util_RXDebugConnectionsNext;
2772 rc = IteratorNext(iter, (void *)&item, &tst);
2774 goto fail_util_RXDebugConnectionsNext;
2778 *supportedValues = item.supportedValues;
2780 fail_util_RXDebugConnectionsNext:
2790 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2794 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2798 * No locks are obtained or released by this function
2802 * Returns != 0 upon successful completion.
2807 util_RXDebugConnectionsDone(const void *iterationId, afs_status_p st)
2810 afs_status_t tst = 0;
2811 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2814 * Validate parameters
2818 tst = ADMITERATORNULL;
2819 goto fail_util_RXDebugConnectionsDone;
2822 rc = IteratorDone(iter, &tst);
2824 fail_util_RXDebugConnectionsDone:
2834 * The iterator for listing RXDebug peer
2837 typedef struct rxdebug_peer_item {
2838 struct rx_debugPeer peer;
2839 afs_uint32 supportedValues;
2840 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2842 typedef struct rxdebug_peer_get {
2843 rxdebugHandle_p handle;
2845 rxdebug_peer_item_t items[CACHED_ITEMS];
2846 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2849 RXDebugPeersFromServer(void *rpc_specific, int slot, int *last_item,
2850 int *last_item_contains_data, afs_status_p st)
2854 afs_status_t tst = 0;
2855 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2858 * Get the next entry the list of peers
2861 rx_GetServerPeers(t->handle->sock, t->handle->ipAddr,
2862 t->handle->udpPort, &t->index,
2863 t->handle->supportedStats, &t->items[slot].peer,
2864 &t->items[slot].supportedValues);
2866 tst = ADMCLIENTRXDEBUGTIMEOUT;
2867 goto fail_ListCellsRPC;
2871 * See if we've processed all the entries
2873 if (t->items[slot].peer.host == 0xffffffff) {
2875 *last_item_contains_data = 0;
2888 RXDebugPeersFromCache(void *rpc_specific, int slot, void *dest,
2892 afs_status_t tst = 0;
2893 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2895 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_peer_item_t));
2906 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
2911 * IN handle - an rxdebug handle for the process to be queried
2913 * OUT iterationIdP - an iteration id that can be passed to
2914 * util_RXDebugPeersNext.
2918 * No locks are obtained or released by this function
2922 * Returns != 0 upon successful completion.
2927 util_RXDebugPeersBegin(rxdebugHandle_p handle, void **iterationIdP,
2932 afs_uint32 tsupported;
2933 afs_status_t tst = 0;
2934 afs_admin_iterator_p iter;
2935 rxdebug_peer_get_p t;
2937 if (handle == NULL) {
2938 tst = ADMRXDEBUGHANDLENULL;
2939 goto fail_util_RXDebugPeersBegin;
2942 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2945 goto fail_util_RXDebugPeersBegin;
2948 if (handle->firstFlag) {
2949 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2952 goto fail_util_RXDebugPeersBegin;
2956 if (!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
2957 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2958 goto fail_util_RXDebugPeersBegin;
2961 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
2965 goto fail_util_RXDebugPeersBegin;
2971 (iter, (void *)t, RXDebugPeersFromServer, RXDebugPeersFromCache, NULL,
2973 goto fail_util_RXDebugPeersBegin;
2975 *iterationIdP = (void *)iter;
2978 fail_util_RXDebugPeersBegin:
2987 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
2991 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
2993 * OUT peer - Rxdebug information for the next peer.
2995 * OUT supportedValues - Bit mask of supported rxdebug values.
2999 * No locks are obtained or released by this function
3003 * Returns != 0 upon successful completion.
3007 util_RXDebugPeersNext(const void *iterationId, struct rx_debugPeer *peer,
3008 afs_uint32 * supportedValues, afs_status_p st)
3011 afs_status_t tst = 0;
3012 rxdebug_peer_item_t item;
3013 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3015 if (iterationId == NULL) {
3016 tst = ADMITERATIONIDPNULL;
3017 goto fail_util_RXDebugPeersNext;
3021 tst = ADMRXDEBUGHANDLENULL;
3022 goto fail_util_RXDebugPeersNext;
3025 if (supportedValues == NULL) {
3026 tst = ADMRXDEBUGHANDLENULL;
3027 goto fail_util_RXDebugPeersNext;
3030 rc = IteratorNext(iter, (void *)&item, &tst);
3032 goto fail_util_RXDebugPeersNext;
3036 *supportedValues = item.supportedValues;
3038 fail_util_RXDebugPeersNext:
3047 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3051 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3055 * No locks are obtained or released by this function
3059 * Returns != 0 upon successful completion.
3064 util_RXDebugPeersDone(const void *iterationId, afs_status_p st)
3067 afs_status_t tst = 0;
3068 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3071 * Validate parameters
3075 tst = ADMITERATORNULL;
3076 goto fail_util_RXDebugPeersDone;
3079 rc = IteratorDone(iter, &tst);
3081 fail_util_RXDebugPeersDone: