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>
15 #include <afs/afs_Admin.h>
18 #include <afs/afs_Admin.h>
19 #include "afs_AdminInternal.h"
20 #include <afs/pthread_glock.h>
21 #include <afs/cellconfig.h>
22 #include <afs/dirpath.h>
23 #include <afs/com_err.h>
24 #include <afs/kautils.h>
26 #include <afs/vlserver.h>
27 #include <afs/pterror.h>
28 #include <afs/bnode.h>
29 #include <afs/volser.h>
30 #include <afs/afscbint.h>
32 #include <rx/rxstat.h>
34 # include <winsock2.h>
35 # include <afs/krb5_nt.h>
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
43 #include "afs_utilAdmin.h"
46 * AIX 4.2 has PTHREAD_CREATE_UNDETACHED and not PTHREAD_CREATE_JOINABLE
48 * This fix should be done more centrally, but there's no time right now.
50 #if defined(AFS_AIX_ENV)
51 # if !defined(PTHREAD_CREATE_JOINABLE) && defined(PTHREAD_CREATE_UNDETACHED)
52 # define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
56 #define ERRCODE_RANGE 8
57 static pthread_once_t error_init_once = PTHREAD_ONCE_INIT;
58 static int error_init_done;
64 initialize_KA_error_table();
65 initialize_RXK_error_table();
66 initialize_KTC_error_table();
67 initialize_ACFG_error_table();
68 initialize_CMD_error_table();
69 initialize_VL_error_table();
70 initialize_PT_error_table();
71 initialize_BZ_error_table();
72 initialize_U_error_table();
73 initialize_AB_error_table();
74 initialize_AF_error_table();
75 initialize_AL_error_table();
76 initialize_AC_error_table();
77 initialize_AK_error_table();
78 initialize_AM_error_table();
79 initialize_AP_error_table();
80 initialize_AU_error_table();
81 initialize_AV_error_table();
82 initialize_VOLS_error_table();
83 #ifdef AFS_KRB5_ERROR_ENV
90 util_AdminErrorCodeTranslate(afs_status_t errorCode, int langId,
91 const char **errorTextP, afs_status_p st)
97 if (errorTextP == NULL) {
98 tst = ADMUTILERRORTEXTPNULL;
99 goto fail_util_AdminErrorCodeTranslate;
103 * Translate the error
106 if (!error_init_done)
107 pthread_once(&error_init_once, init_once);
108 code = (afs_int32) errorCode;
109 *errorTextP = afs_error_message(code);
110 #ifdef AFS_KRB5_ERROR_ENV
111 if (strncmp(*errorTextP, "unknown", strlen("unknown")) == 0) {
112 const char *msg = fetch_krb5_error_message(NULL, code);
113 *errorTextP = msg ? msg : error_message(code);
118 fail_util_AdminErrorCodeTranslate:
127 * The iterator functions and data for the database server retrieval functions.
130 typedef struct database_server_get {
133 struct afsconf_dir *conf;
134 struct afsconf_cell cell;
135 util_databaseServerEntry_t server[CACHED_ITEMS];
136 } database_server_get_t, *database_server_get_p;
139 GetDatabaseServerRPC(void *rpc_specific, int slot, int *last_item,
140 int *last_item_contains_data, afs_status_p st)
143 afs_status_t tst = 0;
144 database_server_get_p serv = (database_server_get_p) rpc_specific;
146 serv->server[slot].serverAddress =
147 ntohl(serv->cell.hostAddr[serv->index].sin_addr.s_addr);
148 strcpy(serv->server[slot].serverName, serv->cell.hostName[serv->index]);
152 * See if we've processed all the entries
155 if (serv->index == serv->total) {
157 *last_item_contains_data = 1;
168 GetDatabaseServerFromCache(void *rpc_specific, int slot, void *dest,
172 afs_status_t tst = 0;
173 database_server_get_p serv = (database_server_get_p) rpc_specific;
175 memcpy(dest, (const void *)&serv->server[slot],
176 sizeof(util_databaseServerEntry_t));
186 DestroyDatabaseServer(void *rpc_specific, afs_status_p st)
189 afs_status_t tst = 0;
190 database_server_get_p serv = (database_server_get_p) rpc_specific;
192 afsconf_Close(serv->conf);
202 * util_DatabaseServerGetBegin - begin iterating over the database
203 * server machines in a cell.
207 * IN cellName - the cell where database servers reside.
209 * OUT iterationIdP - upon successful completion contains an iterator that
210 * can be passed to util_DatabaseServerGetNext.
214 * No locks are obtained or released by this function
222 * Returns != 0 upon successful completion.
226 util_DatabaseServerGetBegin(const char *cellName, void **iterationIdP,
230 afs_status_t tst = 0;
231 afs_admin_iterator_p iter =
232 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
233 database_server_get_p serv =
234 (database_server_get_p) calloc(1, sizeof(database_server_get_t));
235 char copyCell[MAXCELLCHARS];
241 if ((cellName == NULL) || (*cellName == 0)) {
242 tst = ADMUTILCELLNAMENULL;
243 goto fail_util_DatabaseServerGetBegin;
246 if (iterationIdP == NULL) {
247 goto fail_util_DatabaseServerGetBegin;
250 if ((iter == NULL) || (serv == NULL)) {
252 goto fail_util_DatabaseServerGetBegin;
256 * Fill in the serv structure
259 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
260 if (serv->conf == NULL) {
261 tst = ADMUTILCANTOPENCELLSERVDB;
262 goto fail_util_DatabaseServerGetBegin;
266 * We must copy the cellname because afsconf_GetCellInfo
267 * actually writes over the cell name it is passed.
269 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
271 afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
274 goto fail_util_DatabaseServerGetBegin;
277 serv->total = serv->cell.numServers;
279 (iter, (void *)serv, GetDatabaseServerRPC, GetDatabaseServerFromCache,
280 NULL, DestroyDatabaseServer, &tst)) {
281 *iterationIdP = (void *)iter;
283 goto fail_util_DatabaseServerGetBegin;
287 fail_util_DatabaseServerGetBegin:
305 * util_DatabaseServerGetNext - get the next server address.
309 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
311 * OUT serverAddressP - upon successful completion contains the next
312 * server address in the cell.
316 * This function locks the iterator for the duration of its processing.
324 * Returns != 0 upon successful completion.
329 util_DatabaseServerGetNext(const void *iterationId,
330 util_databaseServerEntry_p serverP,
334 afs_status_t tst = 0;
335 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
338 tst = ADMITERATORNULL;
339 goto fail_util_DatabaseServerGetNext;
342 if (serverP == NULL) {
343 tst = ADMUTILSERVERADDRESSPNULL;
344 goto fail_util_DatabaseServerGetNext;
347 rc = IteratorNext(iter, (void *)serverP, &tst);
349 fail_util_DatabaseServerGetNext:
358 * util_DatabaseServerGetDone - stop using a database iterator.
362 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
366 * This function locks the iterator for the duration of its processing.
367 * And then destroys it before returning.
375 * Returns != 0 upon successful completion.
379 util_DatabaseServerGetDone(const void *iterationId, afs_status_p st)
382 afs_status_t tst = 0;
383 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
386 * Validate parameters
390 tst = ADMITERATORNULL;
391 goto fail_util_DatabaseServerGetDone;
394 rc = IteratorDone(iter, &tst);
396 fail_util_DatabaseServerGetDone:
405 * GetServerAddressFromName - translate a character string server name
406 * to an integer representation of an IP address.
410 * IN serverName - the character string server name in either foo.com
411 * format, or 123.12.1.1 format.
413 * OUT serverAddress - an integer that is filled with the correct address
414 * in host byte order upon successful completion.
418 * No locks are obtained or released by this function
422 * On many platforms, gethostbyname is not thread safe. Since we are
423 * only working under NT for now I'll use it directly. In future UNIX
424 * ports, a wrapper function should be written to call the correct function
425 * on the particular platform.
429 * Returns != 0 upon successful completion.
433 util_AdminServerAddressGetFromName(const char *serverName, int *serverAddress,
437 afs_status_t tst = 0;
438 struct hostent *server;
439 int part1, part2, part3, part4;
442 if ((serverName == NULL) || (*serverName == 0)) {
443 tst = ADMUTILSERVERNAMENULL;
444 goto fail_util_AdminServerAddressGetFromName;
447 if (serverAddress == NULL) {
448 tst = ADMUTILSERVERADDRESSNULL;
449 goto fail_util_AdminServerAddressGetFromName;
453 sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
454 if (num_converted == 4) {
455 *serverAddress = (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
458 server = gethostbyname(serverName);
459 if (server != NULL) {
460 memcpy((void *)serverAddress, (const void *)server->h_addr,
462 *serverAddress = ntohl(*serverAddress);
464 tst = ADMUTILCANTGETSERVERNAME;
466 goto fail_util_AdminServerAddressGetFromName;
472 fail_util_AdminServerAddressGetFromName:
482 * This file contains functions that can be used to create iterator
483 * functions within the api. I have attempted to make these functions
484 * generic so that they can be used across the admin components.
486 * The functions in this file are a generalized producer/consumer
487 * implementation. They manage access to a queue of data. The only
488 * assumption these functions make about this data is that it is
489 * stored in a queue which is implemented via an array. These functions
490 * know about the index into the array, but they know nothing about
491 * the contents of the array.
493 * The data specific functions you implement will have to create some
494 * data specific storage structure that will have an array
495 * of size CACHED_ITEMS data items. This structure will also need to
496 * store any necessary parameters/state variables you need to issue the
497 * rpc to retrieve the next item.
499 * In order to use the generic functions, you must implement four functions
500 * for each type of data you wish to retrieve. The functions are:
502 * validate_specific_data_func - this function is handed a void pointer
503 * that points to the rpc specific data you've allocated. The function
504 * should examine the data for validity and return an appropriate error.
505 * This function is called every time the iterator is validated.
507 * destroy_specific_data_func - this function is handed a void pointer
508 * that points to the rpc specific data you've allocated. It should
509 * destroy any components of the specific data as required and then
510 * return. The void pointer is free'd by the generic functions.
512 * get_cached_data_func - this function is handed a void pointer
513 * that points to the rpc specific data you've allocated, an index
514 * into the cache of the item to be copied to the caller, and a void
515 * pointer where the cache item should be copied.
517 * make_rpc_func - this function is handed a void pointer that points
518 * to the rpc specific data you've allocated, an index into the cache
519 * of the item to be filled with the next retrieved item, and an int
520 * pointer that should be set to 1 if there are no more items to be
521 * retrieved. The assumption made by the generic functions is that
522 * the last_item status requires an individual rpc - the data isn't
523 * piggybacked on the last data item.
527 * IteratorDelete - delete an iterator.
531 * IN interator - the iterator to delete.
535 * No locks are held by this function.
539 * Returns != 0 upon successful completion.
543 IteratorDelete(afs_admin_iterator_p iter, afs_status_p st)
546 afs_status_t tst = 0;
548 if (pthread_mutex_destroy(&iter->mutex)) {
549 tst = ADMMUTEXDESTROY;
550 goto fail_IteratorDelete;
552 if (pthread_cond_destroy(&iter->add_item)) {
553 tst = ADMCONDDESTROY;
554 goto fail_IteratorDelete;
556 if (pthread_cond_destroy(&iter->remove_item)) {
557 tst = ADMCONDDESTROY;
558 goto fail_IteratorDelete;
561 if (iter->destroy_specific != NULL) {
562 iter->destroy_specific(iter->rpc_specific, &tst);
564 free(iter->rpc_specific);
577 * DataGet - the background thread that is spawned for every
578 * IteratorBegin call that is successful. This thread tries
579 * to fetch the data from the server ahead of the
580 * IteratorNext calls.
584 * IN arg - the address of the iterator structure to be used for this
589 * The iterator mutex is used by this function to protect elements
590 * of the iterator structure.
594 * Returns != 0 upon successful completion.
600 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
602 afs_status_t tst = 0;
603 int mutex_locked = 0;
605 int last_item_contains_data = 0;
607 if (pthread_mutex_lock(&iter->mutex)) {
608 iter->st = ADMMUTEXLOCK;
617 * Check to see if there's room for this datum. If not, wait
618 * on the consumer to free up another slot.
621 while (iter->cache_slots_used == CACHED_ITEMS) {
622 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
623 iter->st = ADMCONDWAIT;
629 * Check to see if someone called Done and terminated the request.
630 * We could have gone to sleep above when the buffer was full and
631 * instead of being awoken because another slot is open, we were
632 * awoken because the request was terminated.
635 if (iter->request_terminated) {
639 if (pthread_mutex_unlock(&iter->mutex)) {
640 iter->st = ADMMUTEXUNLOCK;
647 * Make an rpc without holding the iter mutex
648 * We reference an item in the principal cache here without
649 * holding the mutex. This is safe because:
650 * 1. The iter structure is ref counted and won't be deleted
651 * from underneath us.
652 * 2. cache_queue_tail is always one item ahead of the consumer
653 * thread so we are the only thread accessing this member.
656 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail, &last_item,
657 &last_item_contains_data, &tst);
659 if (pthread_mutex_lock(&iter->mutex)) {
660 iter->st = ADMMUTEXLOCK;
667 * Check to see if someone called Done and terminated the request
670 if (iter->request_terminated) {
675 * Check the rc of the rpc, and see if there are no more items
685 * Check to see if this is the last item produced by the rpc.
686 * If it isn't, add the item to the cache and proceed.
687 * If it is, check to see if the last item contains valid data.
688 * If it contains valid data, we need to add it to our cache.
689 * If it doesn't, we mark the iterator as complete.
692 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
693 iter->cache_queue_tail =
694 (iter->cache_queue_tail + 1) % CACHED_ITEMS;
695 iter->cache_slots_used++;
698 iter->st = ADMITERATORDONE;
699 iter->done_iterating = 1;
701 * There's a small chance that the consumer emptied the
702 * cache queue while we were making the last rpc and has
703 * since gone to sleep waiting for more data. In this case
704 * there will never be more data so we signal him here.
706 pthread_cond_signal(&iter->add_item);
712 * If the cache was empty and we just added another item, signal
716 if (iter->cache_slots_used == 1) {
717 if (pthread_cond_signal(&iter->add_item)) {
718 iter->st = ADMCONDSIGNAL;
728 * If we are exiting with an error, signal the consumer in the event
729 * they were waiting for us to produce more data
733 pthread_cond_signal(&iter->add_item);
737 pthread_mutex_unlock(&iter->mutex);
744 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
748 * IN interator - the interator to be verified.
752 * We assume the iter->mutex lock is already held.
756 * Returns != 0 upon successful completion.
760 IsValidIterator(const afs_admin_iterator_p iterator, afs_status_p st)
763 afs_status_t tst = 0;
766 * Validate input parameters
769 if (iterator == NULL) {
770 tst = ADMITERATORNULL;
771 goto fail_IsValidIterator;
774 if ((iterator->begin_magic != BEGIN_MAGIC)
775 || (iterator->end_magic != END_MAGIC)) {
776 tst = ADMITERATORBADMAGICNULL;
777 goto fail_IsValidIterator;
780 if (iterator->is_valid == 0) {
781 tst = ADMITERATORINVALID;
782 goto fail_IsValidIterator;
786 * Call the iterator specific validation function
789 if (iterator->validate_specific != NULL) {
790 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
791 goto fail_IsValidIterator;
796 fail_IsValidIterator:
805 * IteratorNext - return the next datum in an interator.
809 * IN interator - the iterator containing the data.
811 * IN dest - the address where the data should be copied.
815 * Lock the iterator upon entry, and hold it during the duration of this
820 * Returns != 0 upon successful completion.
824 IteratorNext(afs_admin_iterator_p iter, void *dest, afs_status_p st)
827 afs_status_t tst = 0;
831 * We have to lock the iterator before we validate it
834 if (pthread_mutex_lock(&iter->mutex)) {
836 goto fail_IteratorNext;
841 if (!IsValidIterator(iter, &tst)) {
842 goto fail_IteratorNext;
845 if (iter->request_terminated == 1) {
846 tst = ADMITERATORTERMINATED;
847 goto fail_IteratorNext;
850 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
852 goto fail_IteratorNext;
856 * Check to see if there are any queue'd items. If not, wait here
857 * until signalled by the producer.
860 while (iter->cache_slots_used == 0) {
863 * Maybe the producer experienced an rpc failure.
866 if ((!iter->done_iterating) && (iter->st != 0)) {
868 goto fail_IteratorNext;
872 * Maybe there are no queue'd items because the producer is done
875 if (iter->done_iterating) {
877 goto fail_IteratorNext;
880 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
882 goto fail_IteratorNext;
887 * Copy the next cached item and update the cached item count
888 * and the index into the cache array
892 get_cached_data(iter->rpc_specific, iter->cache_queue_head, dest,
894 goto fail_IteratorNext;
897 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
898 iter->cache_slots_used--;
901 * If the cache was full before we removed the item above, the
902 * producer may have been waiting for us to remove an item.
903 * Signal the producer letting him know that we've opened a slot
907 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
908 if (pthread_cond_signal(&iter->remove_item)) {
910 goto fail_IteratorNext;
918 if (locked_iter == 1) {
919 pthread_mutex_unlock(&iter->mutex);
929 * IteratorDone - mark the iterator done.
933 * IN interator - the iterator to mark done.
937 * Lock the iterator upon entry, and hold it during the duration of this
942 * Returns != 0 upon successful completion.
946 IteratorDone(afs_admin_iterator_p iter, afs_status_p st)
949 afs_status_t tst = 0;
950 int mutex_locked = 1;
952 if (pthread_mutex_lock(&iter->mutex)) {
954 goto fail_IteratorDone;
960 if (!IsValidIterator(iter, &tst)) {
961 goto fail_IteratorDone;
966 * Depending upon the status of the background worker thread,
967 * we can either join with him immediately (if we know he has
968 * terminated), or we need to tell him the request has been
969 * terminated and then join with him.
972 if (!iter->done_iterating) {
973 iter->request_terminated = 1;
974 iter->cache_slots_used = 0;
975 pthread_cond_signal(&iter->remove_item);
979 * We have to unlock the mutex to allow the background thread to
983 if (pthread_mutex_unlock(&iter->mutex)) {
984 tst = ADMMUTEXUNLOCK;
985 goto fail_IteratorDone;
988 if (iter->make_rpc != NULL) {
989 if (pthread_join(iter->bg_worker, (void **)0)) {
991 goto fail_IteratorDone;
996 * We don't relock the mutex here since we are the only thread
997 * that has access to the iter now
1000 rc = IteratorDelete(iter, &tst);
1006 pthread_mutex_unlock(&iter->mutex);
1016 * IteratorInit - initialize an iterator.
1020 * IN interator - the iterator to initialize.
1024 * No locks are held by this function.
1028 * Returns != 0 upon successful completion.
1032 IteratorInit(afs_admin_iterator_p iter, void *rpc_specific,
1033 make_rpc_func make_rpc, get_cached_data_func get_cached_data,
1034 validate_specific_data_func validate_specific_data,
1035 destroy_specific_data_func destroy_specific_data,
1039 afs_status_t tst = 0;
1040 int mutex_inited = 0;
1041 int add_item_cond_inited = 0;
1042 int remove_item_cond_inited = 0;
1045 tst = ADMITERATORNULL;
1046 goto fail_IteratorInit;
1049 if (rpc_specific == NULL) {
1050 tst = ADMITERATORRPCSPECIFICNULL;
1051 goto fail_IteratorInit;
1055 * Initialize the iterator structure
1057 iter->begin_magic = BEGIN_MAGIC;
1058 iter->end_magic = END_MAGIC;
1060 iter->cache_slots_used = 0;
1061 iter->done_iterating = 0;
1062 iter->request_terminated = 0;
1063 iter->st = AFS_STATUS_OK;
1064 iter->cache_queue_head = 0;
1065 iter->cache_queue_tail = 0;
1066 iter->cache_slots_used = 0;
1067 iter->rpc_specific = rpc_specific;
1068 iter->make_rpc = make_rpc;
1069 iter->get_cached_data = get_cached_data;
1070 iter->validate_specific = validate_specific_data;
1071 iter->destroy_specific = destroy_specific_data;
1073 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *)0)) {
1075 goto fail_IteratorInit;
1080 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *)0)) {
1082 goto fail_IteratorInit;
1084 add_item_cond_inited = 1;
1087 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *)0)) {
1089 goto fail_IteratorInit;
1091 remove_item_cond_inited = 1;
1095 * Create a worker thread that will begin to query the server
1096 * and cache responses.
1099 if (iter->make_rpc != NULL) {
1100 pthread_attr_t tattr;
1102 if (pthread_attr_init(&tattr)) {
1103 tst = ADMTHREADATTRINIT;
1104 goto fail_IteratorInit;
1107 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1108 tst = ADMTHREADATTRSETDETACHSTATE;
1109 goto fail_IteratorInit;
1112 if (pthread_create(&iter->bg_worker, &tattr, DataGet, (void *)iter)) {
1113 tst = ADMTHREADCREATE;
1114 goto fail_IteratorInit;
1123 pthread_mutex_destroy(&iter->mutex);
1125 if (remove_item_cond_inited) {
1126 pthread_cond_destroy(&iter->remove_item);
1128 if (add_item_cond_inited) {
1129 pthread_cond_destroy(&iter->add_item);
1140 CellHandleIsValid(const void *cellHandle, afs_status_p st)
1143 afs_status_t tst = 0;
1144 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1147 * Validate input parameters
1150 if (c_handle == NULL) {
1151 tst = ADMCLIENTCELLHANDLENULL;
1152 goto fail_CellHandleIsValid;
1155 if ((c_handle->begin_magic != BEGIN_MAGIC)
1156 || (c_handle->end_magic != END_MAGIC)) {
1157 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1158 goto fail_CellHandleIsValid;
1161 if (c_handle->is_valid == 0) {
1162 tst = ADMCLIENTCELLINVALID;
1163 goto fail_CellHandleIsValid;
1167 fail_CellHandleIsValid:
1176 * The iterator functions and data for the rpc statistic retrieval functions
1179 typedef struct rpc_stat_get {
1180 afs_uint32 clock_sec;
1181 afs_uint32 clock_usec;
1184 afs_uint32 clientVersion;
1185 afs_uint32 serverVersion;
1186 struct rpcStats stat_list;
1187 afs_RPCStats_t stats[CACHED_ITEMS];
1188 afs_uint32 *pointer;
1189 } rpc_stat_get_t, *rpc_stat_get_p;
1192 UnmarshallRPCStats(afs_uint32 serverVersion, afs_uint32 ** ptrP,
1196 unsigned int hi, lo;
1199 * Server must always match lower versions. We are version 1.
1202 s->stats_v1.remote_peer = *(ptr++);
1203 s->stats_v1.remote_port = *(ptr++);
1204 s->stats_v1.remote_is_server = *(ptr++);
1205 s->stats_v1.interfaceId = *(ptr++);
1206 s->stats_v1.func_total = *(ptr++);
1207 s->stats_v1.func_index = *(ptr++);
1210 hset64(s->stats_v1.invocations, hi, lo);
1213 hset64(s->stats_v1.bytes_sent, hi, lo);
1216 hset64(s->stats_v1.bytes_rcvd, hi, lo);
1217 s->stats_v1.queue_time_sum.sec = *(ptr++);
1218 s->stats_v1.queue_time_sum.usec = *(ptr++);
1219 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1220 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1221 s->stats_v1.queue_time_min.sec = *(ptr++);
1222 s->stats_v1.queue_time_min.usec = *(ptr++);
1223 s->stats_v1.queue_time_max.sec = *(ptr++);
1224 s->stats_v1.queue_time_max.usec = *(ptr++);
1225 s->stats_v1.execution_time_sum.sec = *(ptr++);
1226 s->stats_v1.execution_time_sum.usec = *(ptr++);
1227 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1228 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1229 s->stats_v1.execution_time_min.sec = *(ptr++);
1230 s->stats_v1.execution_time_min.usec = *(ptr++);
1231 s->stats_v1.execution_time_max.sec = *(ptr++);
1232 s->stats_v1.execution_time_max.usec = *(ptr++);
1237 GetRPCStatsRPC(void *rpc_specific, int slot, int *last_item,
1238 int *last_item_contains_data, afs_status_p st)
1241 afs_status_t tst = 0;
1242 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1244 t->stats[slot].clientVersion = t->clientVersion;
1245 t->stats[slot].serverVersion = t->serverVersion;
1246 t->stats[slot].statCount = t->total;
1249 * If the server stat version is greater than or equal to my version
1250 * number, it is required to return the values in the client's current
1254 UnmarshallRPCStats(t->serverVersion, &t->pointer, &t->stats[slot].s);
1259 * See if we've processed all the entries
1262 if (t->index == t->total) {
1264 *last_item_contains_data = 1;
1275 GetRPCStatsFromCache(void *rpc_specific, int slot, void *dest,
1279 afs_status_t tst = 0;
1280 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1282 memcpy(dest, (const void *)&stat->stats[slot], sizeof(afs_RPCStats_t));
1292 DestroyRPCStats(void *rpc_specific, afs_status_p st)
1295 afs_status_t tst = 0;
1296 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1298 if (stat->stat_list.rpcStats_val != NULL) {
1299 free(stat->stat_list.rpcStats_val);
1310 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1314 * IN conn - an rx connection to the process to be queried
1316 * IN rpc - the function to call to make the actual rpc
1318 * OUT iterationIdP - an iteration id that can be passed to
1319 * util_RPCStatsGetNext to get the next rpc stat
1323 * No locks are obtained or released by this function
1327 * Returns != 0 upon successful completion.
1332 util_RPCStatsGetBegin(struct rx_connection *conn,
1333 int (*rpc) (struct rx_connection *,
1334 afs_uint32, afs_uint32 *,
1335 afs_uint32 *, afs_uint32 *,
1336 afs_uint32 *, struct rpcStats *),
1337 void **iterationIdP, afs_status_p st)
1340 afs_status_t tst = 0;
1341 afs_admin_iterator_p iter =
1342 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1343 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1346 tst = ADMRXCONNNULL;
1347 goto fail_util_RPCStatsGetBegin;
1351 tst = ADMRPCPTRNULL;
1352 goto fail_util_RPCStatsGetBegin;
1355 if (iterationIdP == NULL) {
1356 tst = ADMITERATIONIDPNULL;
1357 goto fail_util_RPCStatsGetBegin;
1360 if ((iter == NULL) || (stat == NULL)) {
1362 goto fail_util_RPCStatsGetBegin;
1365 stat->stat_list.rpcStats_len = 0;
1366 stat->stat_list.rpcStats_val = 0;
1368 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1371 (*rpc) (conn, stat->clientVersion, &stat->serverVersion,
1372 &stat->clock_sec, &stat->clock_usec, &stat->total,
1376 goto fail_util_RPCStatsGetBegin;
1380 * If there are no statistics, just mark the iterator done and
1384 if (stat->stat_list.rpcStats_len == 0) {
1385 stat->pointer = NULL;
1386 if (!IteratorInit(iter, (void *)stat, NULL, NULL, NULL, NULL, &tst)) {
1387 goto fail_util_RPCStatsGetBegin;
1389 iter->done_iterating = 1;
1390 iter->st = ADMITERATORDONE;
1392 stat->pointer = stat->stat_list.rpcStats_val;
1394 (iter, (void *)stat, GetRPCStatsRPC, GetRPCStatsFromCache, NULL,
1395 DestroyRPCStats, &tst)) {
1396 goto fail_util_RPCStatsGetBegin;
1399 *iterationIdP = (void *)iter;
1402 fail_util_RPCStatsGetBegin:
1420 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1424 * IN iterationId - an iterator previously returned by
1425 * util_RPCStatsGetBegin.
1427 * OUT stats - upon successful completion contains the next set of stats
1432 * No locks are obtained or released by this function
1436 * Returns != 0 upon successful completion.
1441 util_RPCStatsGetNext(const void *iterationId, afs_RPCStats_p stats,
1445 afs_status_t tst = 0;
1446 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1448 if (iterationId == NULL) {
1449 tst = ADMITERATIONIDPNULL;
1450 goto fail_util_RPCStatsGetNext;
1453 if (stats == NULL) {
1454 tst = ADMUTILRPCSTATSNULL;
1455 goto fail_util_RPCStatsGetNext;
1458 rc = IteratorNext(iter, (void *)stats, &tst);
1460 fail_util_RPCStatsGetNext:
1469 * util_RPCStatsGetDone - finish using a stats iterator
1473 * IN iterationId - an iterator previously returned by
1474 * util_RPCStatsGetBegin.
1478 * No locks are obtained or released by this function
1482 * Returns != 0 upon successful completion.
1487 util_RPCStatsGetDone(const void *iterationId, afs_status_p st)
1490 afs_status_t tst = 0;
1491 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1493 if (iterationId == NULL) {
1494 tst = ADMITERATIONIDPNULL;
1495 goto fail_util_RPCStatsGetDone;
1498 rc = IteratorDone(iter, &tst);
1500 fail_util_RPCStatsGetDone:
1509 * util_RPCStatsStateGet - get the current state of rpc stat collection
1513 * IN conn - an rx connection to the process to be queried
1515 * IN rpc - the function to call to make the actual rpc
1517 * OUT state - the rpc stat collection state.
1521 * No locks are obtained or released by this function
1525 * Returns != 0 upon successful completion.
1530 util_RPCStatsStateGet(struct rx_connection *conn,
1531 int (*rpc) (struct rx_connection *,
1532 afs_RPCStatsState_p),
1533 afs_RPCStatsState_p state, afs_status_p st)
1536 afs_status_t tst = 0;
1539 tst = ADMRXCONNNULL;
1540 goto fail_util_RPCStatsStateGet;
1544 tst = ADMRPCPTRNULL;
1545 goto fail_util_RPCStatsStateGet;
1548 if (state == NULL) {
1549 tst = ADMRPCSTATENULL;
1550 goto fail_util_RPCStatsStateGet;
1553 tst = (*rpc) (conn, state);
1559 fail_util_RPCStatsStateGet:
1568 * util_RPCStatsStateEnable - enable rpc stat collection
1573 * IN conn - an rx connection to the process to be modified
1575 * IN rpc - the function to call to make the actual rpc
1579 * No locks are obtained or released by this function
1583 * Returns != 0 upon successful completion.
1588 util_RPCStatsStateEnable(struct rx_connection *conn,
1589 int (*rpc) (struct rx_connection *),
1593 afs_status_t tst = 0;
1596 tst = ADMRXCONNNULL;
1597 goto fail_util_RPCStatsStateEnable;
1601 tst = ADMRPCPTRNULL;
1602 goto fail_util_RPCStatsStateEnable;
1605 tst = (*rpc) (conn);
1611 fail_util_RPCStatsStateEnable:
1620 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1625 * IN conn - an rx connection to the process to be modified
1627 * IN rpc - the function to call to make the actual rpc
1631 * No locks are obtained or released by this function
1635 * Returns != 0 upon successful completion.
1640 util_RPCStatsStateDisable(struct rx_connection *conn,
1641 int (*rpc) (struct rx_connection *),
1645 afs_status_t tst = 0;
1648 tst = ADMRXCONNNULL;
1649 goto fail_util_RPCStatsStateDisable;
1653 tst = ADMRPCPTRNULL;
1654 goto fail_util_RPCStatsStateDisable;
1657 tst = (*rpc) (conn);
1663 fail_util_RPCStatsStateDisable:
1672 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1673 * collection at a server
1677 * IN conn - an rx connection to the process to be modified
1679 * IN rpc - the function to call to make the actual rpc
1681 * IN flag - a flag containing the fields to be cleared
1686 * No locks are obtained or released by this function
1690 * Returns != 0 upon successful completion.
1695 util_RPCStatsClear(struct rx_connection *conn,
1696 int (*rpc) (struct rx_connection *,
1697 afs_RPCStatsClearFlag_t),
1698 afs_RPCStatsClearFlag_t flag, afs_status_p st)
1701 afs_status_t tst = 0;
1704 tst = ADMRXCONNNULL;
1705 goto fail_util_RPCStatsClear;
1709 tst = ADMRPCPTRNULL;
1710 goto fail_util_RPCStatsClear;
1713 tst = (*rpc) (conn, flag);
1719 fail_util_RPCStatsClear:
1728 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1732 * IN conn - an rx connection to the process to be modified
1734 * OUT version - the version of rpc stat collection at the remote process
1738 * No locks are obtained or released by this function
1742 * Returns != 0 upon successful completion.
1747 util_RPCStatsVersionGet(struct rx_connection *conn,
1748 afs_RPCStatsVersion_p version, afs_status_p st)
1751 afs_status_t tst = 0;
1754 tst = ADMRXCONNNULL;
1755 goto fail_util_RPCStatsVersionGet;
1758 if (version == NULL) {
1759 tst = ADMRPCVERSIONNULL;
1760 goto fail_util_RPCStatsVersionGet;
1763 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1769 fail_util_RPCStatsVersionGet:
1778 * The iterator for listing CM server preferences
1781 typedef struct cm_srvr_pref_get {
1782 struct rx_connection *conn;
1784 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1785 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1788 GetServerPrefsRPC(void *rpc_specific, int slot, int *last_item,
1789 int *last_item_contains_data, afs_status_p st)
1792 afs_status_t tst = 0;
1793 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1796 * Get the next entry in the list of server preferences.
1799 RXAFSCB_GetServerPrefs(t->conn, t->index, &t->srvrPrefs[slot].ipAddr,
1800 &t->srvrPrefs[slot].ipRank);
1802 goto fail_GetServerPrefsRPC;
1806 * See if we've processed all the entries
1808 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1810 *last_item_contains_data = 0;
1816 fail_GetServerPrefsRPC:
1825 GetServerPrefsFromCache(void *rpc_specific, int slot, void *dest,
1829 afs_status_t tst = 0;
1830 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1832 memcpy(dest, (const void *)&prefs->srvrPrefs[slot],
1833 sizeof(afs_CMServerPref_t));
1843 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1847 * IN conn - an rx connection to the process to be queried
1849 * OUT iterationIdP - an iteration id that can be passed to
1850 * util_CMGetServerPrefsNext to get the next server preference
1854 * No locks are obtained or released by this function
1858 * Returns != 0 upon successful completion.
1863 util_CMGetServerPrefsBegin(struct rx_connection *conn, void **iterationIdP,
1867 afs_status_t tst = 0;
1868 afs_admin_iterator_p iter;
1869 cm_srvr_pref_get_p pref;
1872 tst = ADMRXCONNNULL;
1873 goto fail_util_CMGetServerPrefsBegin;
1876 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1879 goto fail_util_CMGetServerPrefsBegin;
1882 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1886 goto fail_util_CMGetServerPrefsBegin;
1892 (iter, (void *)pref, GetServerPrefsRPC, GetServerPrefsFromCache, NULL,
1896 goto fail_util_CMGetServerPrefsBegin;
1898 *iterationIdP = (void *)iter;
1901 fail_util_CMGetServerPrefsBegin:
1910 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1915 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1917 * OUT prefs - Next entry in cache manager server preferences.
1921 * No locks are obtained or released by this function
1925 * Returns != 0 upon successful completion.
1930 util_CMGetServerPrefsNext(const void *iterationId, afs_CMServerPref_p prefs,
1934 afs_status_t tst = 0;
1935 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1937 if (iterationId == NULL) {
1938 tst = ADMITERATIONIDPNULL;
1939 goto fail_util_CMGetServerPrefsNext;
1942 rc = IteratorNext(iter, (void *)prefs, &tst);
1944 fail_util_CMGetServerPrefsNext:
1953 * util_CMGetServerPrefsDone - Finish listing cache manager server
1958 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1962 * No locks are obtained or released by this function
1966 * Returns != 0 upon successful completion.
1971 util_CMGetServerPrefsDone(const void *iterationId, afs_status_p st)
1974 afs_status_t tst = 0;
1975 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1977 if (iterationId == NULL) {
1978 tst = ADMITERATIONIDPNULL;
1979 goto fail_util_CMGetServerPrefsDone;
1982 rc = IteratorDone(iter, &tst);
1985 fail_util_CMGetServerPrefsDone:
1994 * The iterator for listing CM CellServDB
1997 typedef struct cm_list_cell_get {
1998 struct rx_connection *conn;
2000 afs_CMListCell_t cell[CACHED_ITEMS];
2001 } cm_list_cell_get_t, *cm_list_cell_get_p;
2004 ListCellsRPC(void *rpc_specific, int slot, int *last_item,
2005 int *last_item_contains_data, afs_status_p st)
2008 afs_status_t tst = 0;
2009 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2015 * Get the next entry in the CellServDB.
2017 name = t->cell[slot].cellname;
2018 sl.serverList_len = 0;
2019 sl.serverList_val = NULL;
2020 memset(t->cell[slot].serverAddr, 0, sizeof(afs_int32)*UTIL_MAX_CELL_HOSTS);
2022 RXAFSCB_GetCellServDB(t->conn, t->index, &name, &sl);
2024 goto fail_ListCellsRPC;
2026 strcpy(t->cell[slot].cellname, name);
2027 if (sl.serverList_val) {
2028 for (n=0; n<sl.serverList_len && n<UTIL_MAX_CELL_HOSTS; n++) {
2029 t->cell[slot].serverAddr[n] = sl.serverList_val[n];
2031 xdr_free((xdrproc_t) xdr_serverList, &sl);
2035 * See if we've processed all the entries
2037 if (strlen(t->cell[slot].cellname) == 0) {
2039 *last_item_contains_data = 0;
2054 ListCellsFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2057 afs_status_t tst = 0;
2058 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2060 memcpy(dest, (const void *)&cell->cell[slot], sizeof(afs_CMListCell_t));
2070 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2074 * IN conn - an rx connection to the process to be queried
2076 * OUT iterationIdP - an iteration id that can be passed to
2077 * util_CMListCellsNext to get the next cell
2081 * No locks are obtained or released by this function
2085 * Returns != 0 upon successful completion.
2090 util_CMListCellsBegin(struct rx_connection *conn, void **iterationIdP,
2094 afs_status_t tst = 0;
2095 afs_admin_iterator_p iter;
2096 cm_list_cell_get_p cell;
2099 tst = ADMRXCONNNULL;
2100 goto fail_util_CMListCellsBegin;
2103 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2106 goto fail_util_CMListCellsBegin;
2109 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2113 goto fail_util_CMListCellsBegin;
2119 (iter, (void *)cell, ListCellsRPC, ListCellsFromCache, NULL, NULL,
2123 goto fail_util_CMListCellsBegin;
2125 *iterationIdP = (void *)iter;
2128 fail_util_CMListCellsBegin:
2137 * util_CMListCellsNext - Get next entry in cache manager cells
2141 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2143 * OUT cell - Next entry in cache manager cells.
2147 * No locks are obtained or released by this function
2151 * Returns != 0 upon successful completion.
2156 util_CMListCellsNext(const void *iterationId, afs_CMListCell_p cell,
2160 afs_status_t tst = 0;
2161 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2163 if (iterationId == NULL) {
2164 tst = ADMITERATIONIDPNULL;
2165 goto fail_util_CMListCellsNext;
2168 rc = IteratorNext(iter, (void *)cell, &tst);
2170 fail_util_CMListCellsNext:
2179 * util_CMListCellsDone - Finish listing cache manager cells
2183 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2187 * No locks are obtained or released by this function
2191 * Returns != 0 upon successful completion.
2196 util_CMListCellsDone(const void *iterationId, afs_status_p st)
2199 afs_status_t tst = 0;
2200 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2202 if (iterationId == NULL) {
2203 tst = ADMITERATIONIDPNULL;
2204 goto fail_util_CMListCellsDone;
2207 rc = IteratorDone(iter, &tst);
2210 fail_util_CMListCellsDone:
2219 * util_CMLocalCell - Get the name of the cache manager's local cell.
2223 * IN conn - an rx connection to the process to be queried
2225 * OUT cellName - the name of the cache manager's local cell.
2229 * No locks are obtained or released by this function
2233 * Returns != 0 upon successful completion.
2238 util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
2242 afs_status_t tst = 0;
2243 afs_CMCellName_p name;
2246 tst = ADMRXCONNNULL;
2247 goto fail_util_CMLocalCell;
2250 if (cellName == NULL) {
2251 tst = ADMCLIENTCMCELLNAMENULL;
2252 goto fail_util_CMLocalCell;
2256 tst = RXAFSCB_GetLocalCell(conn, &name);
2262 fail_util_CMLocalCell:
2271 UnmarshallCMClientConfig(afs_uint32 serverVersion, afs_uint32 * ptr,
2272 afs_ClientConfigUnion_p config)
2275 * We currently only support version 1.
2277 config->config_v1.nChunkFiles = *(ptr++);
2278 config->config_v1.nStatCaches = *(ptr++);
2279 config->config_v1.nDataCaches = *(ptr++);
2280 config->config_v1.nVolumeCaches = *(ptr++);
2281 config->config_v1.firstChunkSize = *(ptr++);
2282 config->config_v1.otherChunkSize = *(ptr++);
2283 config->config_v1.cacheSize = *(ptr++);
2284 config->config_v1.setTime = *(ptr++);
2285 config->config_v1.memCache = *(ptr++);
2289 * util_CMClientConfig - Get the cache manager's configuration parameters.
2293 * IN conn - an rx connection to the process to be queried
2295 * OUT config - the cache manager's configuration parameters.
2299 * No locks are obtained or released by this function
2303 * Returns != 0 upon successful completion.
2308 util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
2312 afs_status_t tst = 0;
2313 afs_uint32 allocbytes;
2314 struct cacheConfig tconfig;
2317 tst = ADMRXCONNNULL;
2318 goto fail_util_CMClientConfig;
2321 if (config == NULL) {
2322 tst = ADMCLIENTCMCELLNAMENULL;
2323 goto fail_util_CMClientConfig;
2326 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2327 tconfig.cacheConfig_val = NULL;
2328 tconfig.cacheConfig_len = 0;
2330 RXAFSCB_GetCacheConfig(conn, config->clientVersion,
2331 &config->serverVersion, &allocbytes, &tconfig);
2334 goto fail_util_CMClientConfig;
2337 UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
2340 free(tconfig.cacheConfig_val);
2342 fail_util_CMClientConfig:
2351 * util_RXDebugVersion - Get the rxdebug version string.
2355 * IN handle - an rxdebug handle for the process to be queried.
2357 * OUT version - the rxdebug version string.
2361 * No locks are obtained or released by this function
2365 * Returns != 0 upon successful completion.
2370 util_RXDebugVersion(rxdebugHandle_p handle, rxdebugVersion_p version,
2374 afs_status_t tst = 0;
2377 if (handle == NULL) {
2378 tst = ADMRXDEBUGHANDLENULL;
2379 goto fail_util_RXDebugVersion;
2382 if (version == NULL) {
2383 tst = ADMRXDEBUGVERSIONNULL;
2384 goto fail_util_RXDebugVersion;
2388 rx_GetServerVersion(handle->sock, handle->ipAddr, handle->udpPort,
2389 UTIL_MAX_RXDEBUG_VERSION_LEN, version);
2391 tst = ADMCLIENTRXDEBUGTIMEOUT;
2392 goto fail_util_RXDebugVersion;
2397 fail_util_RXDebugVersion:
2406 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2411 * IN handle - an rxdebug handle for the process to be queried.
2413 * OUT supportedStats - bit mask with supported rxstats.
2417 * No locks are obtained or released by this function
2421 * Returns != 0 upon successful completion.
2426 util_RXDebugSupportedStats(rxdebugHandle_p handle,
2427 afs_uint32 * supportedStats, afs_status_p st)
2430 afs_status_t tst = 0;
2431 struct rx_debugStats tstats;
2433 if (handle == NULL) {
2434 tst = ADMRXDEBUGHANDLENULL;
2435 goto fail_util_RXDebugSupportedStats;
2438 if (supportedStats == NULL) {
2439 tst = ADMRXDEBUGSTATSNULL;
2440 goto fail_util_RXDebugSupportedStats;
2443 if (handle->firstFlag) {
2444 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2446 goto fail_util_RXDebugSupportedStats;
2450 *supportedStats = handle->supportedStats;
2453 fail_util_RXDebugSupportedStats:
2463 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2467 * IN handle - an rxdebug handle for the process to be queried.
2469 * OUT stats - Basic rxdebug statistics for the process.
2473 * No locks are obtained or released by this function
2477 * Returns != 0 upon successful completion.
2482 util_RXDebugBasicStats(rxdebugHandle_p handle, struct rx_debugStats *stats,
2486 afs_status_t tst = 0;
2489 if (handle == NULL) {
2490 tst = ADMRXDEBUGHANDLENULL;
2491 goto fail_util_RXDebugBasicStats;
2494 if (stats == NULL) {
2495 tst = ADMRXDEBUGSTATSNULL;
2496 goto fail_util_RXDebugBasicStats;
2500 rx_GetServerDebug(handle->sock, handle->ipAddr, handle->udpPort,
2501 stats, &handle->supportedStats);
2503 tst = ADMCLIENTRXDEBUGTIMEOUT;
2504 goto fail_util_RXDebugBasicStats;
2507 handle->firstFlag = 0;
2510 fail_util_RXDebugBasicStats:
2520 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2524 * IN handle - an rxdebug handle for the process to be queried.
2526 * OUT stats - Detailed rxdebug statistics for the process.
2530 * No locks are obtained or released by this function
2534 * Returns != 0 upon successful completion.
2539 util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_statistics *stats,
2540 afs_uint32 * supportedValues, afs_status_p st)
2544 afs_status_t tst = 0;
2546 afs_uint32 tsupported;
2548 if (handle == NULL) {
2549 tst = ADMRXDEBUGHANDLENULL;
2550 goto fail_util_RXDebugRxStats;
2553 if (supportedValues == NULL) {
2554 tst = ADMRXDEBUGSTATSNULL;
2555 goto fail_util_RXDebugRxStats;
2558 if (stats == NULL) {
2559 tst = ADMRXDEBUGSTATSNULL;
2560 goto fail_util_RXDebugRxStats;
2563 if (handle->firstFlag) {
2564 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2567 goto fail_util_RXDebugRxStats;
2571 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2572 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2573 goto fail_util_RXDebugRxStats;
2577 rx_GetServerStats(handle->sock, handle->ipAddr, handle->udpPort,
2578 stats, &handle->supportedStats);
2580 tst = ADMCLIENTRXDEBUGTIMEOUT;
2581 goto fail_util_RXDebugRxStats;
2586 fail_util_RXDebugRxStats:
2595 * The iterator for listing RXDebug connections
2598 typedef struct rxdebug_conn_item {
2599 struct rx_debugConn conn;
2600 afs_uint32 supportedValues;
2601 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2603 typedef struct rxdebug_conn_get {
2605 rxdebugHandle_p handle;
2607 rxdebug_conn_item_t items[CACHED_ITEMS];
2608 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2611 RXDebugConnsFromServer(void *rpc_specific, int slot, int *last_item,
2612 int *last_item_contains_data, afs_status_p st)
2616 afs_status_t tst = 0;
2617 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2620 * Get the next entry the list of connections
2623 rx_GetServerConnections(t->handle->sock, t->handle->ipAddr,
2624 t->handle->udpPort, &t->index, t->allconns,
2625 t->handle->supportedStats,
2626 &t->items[slot].conn,
2627 &t->items[slot].supportedValues);
2629 tst = ADMCLIENTRXDEBUGTIMEOUT;
2630 goto fail_ListCellsRPC;
2634 * See if we've processed all the entries
2636 if (t->items[slot].conn.cid == 0xffffffff) {
2638 *last_item_contains_data = 0;
2651 RXDebugConnsFromCache(void *rpc_specific, int slot, void *dest,
2655 afs_status_t tst = 0;
2656 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2658 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_conn_item_t));
2668 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2673 * IN handle - an rxdebug handle for the process to be queried
2675 * IN allcons - non-zero to list all connections. If zero, only
2676 * "interesting" connections will be listed.
2678 * OUT iterationIdP - an iteration id that can be passed to
2679 * util_RXDebugConnectionsNext.
2683 * No locks are obtained or released by this function
2687 * Returns != 0 upon successful completion.
2692 util_RXDebugConnectionsBegin(rxdebugHandle_p handle, int allconns,
2693 void **iterationIdP, afs_status_p st)
2697 afs_uint32 tsupported;
2698 afs_status_t tst = 0;
2699 afs_admin_iterator_p iter;
2700 rxdebug_conn_get_p t;
2702 if (handle == NULL) {
2703 tst = ADMRXDEBUGHANDLENULL;
2704 goto fail_util_RXDebugConnectionsBegin;
2707 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2710 goto fail_util_RXDebugConnectionsBegin;
2713 if (handle->firstFlag) {
2714 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2717 goto fail_util_RXDebugConnectionsBegin;
2721 if (allconns && !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2722 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2723 goto fail_util_RXDebugConnectionsBegin;
2726 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2730 goto fail_util_RXDebugConnectionsBegin;
2733 t->allconns = allconns;
2737 (iter, (void *)t, RXDebugConnsFromServer, RXDebugConnsFromCache, NULL,
2739 goto fail_util_RXDebugConnectionsBegin;
2741 *iterationIdP = (void *)iter;
2744 fail_util_RXDebugConnectionsBegin:
2754 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2759 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2761 * OUT conn - Rxdebug information for the next connection.
2763 * OUT supportedValues - Bit mask of supported rxdebug values.
2767 * No locks are obtained or released by this function
2771 * Returns != 0 upon successful completion.
2776 util_RXDebugConnectionsNext(const void *iterationId,
2777 struct rx_debugConn *conn,
2778 afs_uint32 * supportedValues, afs_status_p st)
2781 afs_status_t tst = 0;
2782 rxdebug_conn_item_t item;
2783 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2785 if (iterationId == NULL) {
2786 tst = ADMITERATIONIDPNULL;
2787 goto fail_util_RXDebugConnectionsNext;
2791 tst = ADMRXDEBUGHANDLENULL;
2792 goto fail_util_RXDebugConnectionsNext;
2795 if (supportedValues == NULL) {
2796 tst = ADMRXDEBUGHANDLENULL;
2797 goto fail_util_RXDebugConnectionsNext;
2800 rc = IteratorNext(iter, (void *)&item, &tst);
2802 goto fail_util_RXDebugConnectionsNext;
2806 *supportedValues = item.supportedValues;
2808 fail_util_RXDebugConnectionsNext:
2818 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2822 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2826 * No locks are obtained or released by this function
2830 * Returns != 0 upon successful completion.
2835 util_RXDebugConnectionsDone(const void *iterationId, afs_status_p st)
2838 afs_status_t tst = 0;
2839 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2842 * Validate parameters
2846 tst = ADMITERATORNULL;
2847 goto fail_util_RXDebugConnectionsDone;
2850 rc = IteratorDone(iter, &tst);
2852 fail_util_RXDebugConnectionsDone:
2862 * The iterator for listing RXDebug peer
2865 typedef struct rxdebug_peer_item {
2866 struct rx_debugPeer peer;
2867 afs_uint32 supportedValues;
2868 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2870 typedef struct rxdebug_peer_get {
2871 rxdebugHandle_p handle;
2873 rxdebug_peer_item_t items[CACHED_ITEMS];
2874 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2877 RXDebugPeersFromServer(void *rpc_specific, int slot, int *last_item,
2878 int *last_item_contains_data, afs_status_p st)
2882 afs_status_t tst = 0;
2883 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2886 * Get the next entry the list of peers
2889 rx_GetServerPeers(t->handle->sock, t->handle->ipAddr,
2890 t->handle->udpPort, &t->index,
2891 t->handle->supportedStats, &t->items[slot].peer,
2892 &t->items[slot].supportedValues);
2894 tst = ADMCLIENTRXDEBUGTIMEOUT;
2895 goto fail_ListCellsRPC;
2899 * See if we've processed all the entries
2901 if (t->items[slot].peer.host == 0xffffffff) {
2903 *last_item_contains_data = 0;
2916 RXDebugPeersFromCache(void *rpc_specific, int slot, void *dest,
2920 afs_status_t tst = 0;
2921 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2923 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_peer_item_t));
2934 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
2939 * IN handle - an rxdebug handle for the process to be queried
2941 * OUT iterationIdP - an iteration id that can be passed to
2942 * util_RXDebugPeersNext.
2946 * No locks are obtained or released by this function
2950 * Returns != 0 upon successful completion.
2955 util_RXDebugPeersBegin(rxdebugHandle_p handle, void **iterationIdP,
2960 afs_uint32 tsupported;
2961 afs_status_t tst = 0;
2962 afs_admin_iterator_p iter;
2963 rxdebug_peer_get_p t;
2965 if (handle == NULL) {
2966 tst = ADMRXDEBUGHANDLENULL;
2967 goto fail_util_RXDebugPeersBegin;
2970 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2973 goto fail_util_RXDebugPeersBegin;
2976 if (handle->firstFlag) {
2977 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2980 goto fail_util_RXDebugPeersBegin;
2984 if (!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
2985 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2986 goto fail_util_RXDebugPeersBegin;
2989 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
2993 goto fail_util_RXDebugPeersBegin;
2999 (iter, (void *)t, RXDebugPeersFromServer, RXDebugPeersFromCache, NULL,
3001 goto fail_util_RXDebugPeersBegin;
3003 *iterationIdP = (void *)iter;
3006 fail_util_RXDebugPeersBegin:
3015 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3019 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3021 * OUT peer - Rxdebug information for the next peer.
3023 * OUT supportedValues - Bit mask of supported rxdebug values.
3027 * No locks are obtained or released by this function
3031 * Returns != 0 upon successful completion.
3035 util_RXDebugPeersNext(const void *iterationId, struct rx_debugPeer *peer,
3036 afs_uint32 * supportedValues, afs_status_p st)
3039 afs_status_t tst = 0;
3040 rxdebug_peer_item_t item;
3041 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3043 if (iterationId == NULL) {
3044 tst = ADMITERATIONIDPNULL;
3045 goto fail_util_RXDebugPeersNext;
3049 tst = ADMRXDEBUGHANDLENULL;
3050 goto fail_util_RXDebugPeersNext;
3053 if (supportedValues == NULL) {
3054 tst = ADMRXDEBUGHANDLENULL;
3055 goto fail_util_RXDebugPeersNext;
3058 rc = IteratorNext(iter, (void *)&item, &tst);
3060 goto fail_util_RXDebugPeersNext;
3064 *supportedValues = item.supportedValues;
3066 fail_util_RXDebugPeersNext:
3075 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3079 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3083 * No locks are obtained or released by this function
3087 * Returns != 0 upon successful completion.
3092 util_RXDebugPeersDone(const void *iterationId, afs_status_p st)
3095 afs_status_t tst = 0;
3096 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3099 * Validate parameters
3103 tst = ADMITERATORNULL;
3104 goto fail_util_RXDebugPeersDone;
3107 rc = IteratorDone(iter, &tst);
3109 fail_util_RXDebugPeersDone: