2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
17 #include <rx/rxstat.h>
20 # include <winsock2.h>
21 # include <afs/krb5_nt.h>
24 #include <afs/afs_Admin.h>
25 #include <afs/pthread_glock.h>
26 #include <afs/cellconfig.h>
27 #include <afs/dirpath.h>
28 #include <afs/com_err.h>
29 #include <afs/kautils.h>
31 #include <afs/vlserver.h>
32 #include <afs/pterror.h>
33 #include <afs/bnode.h>
34 #include <afs/volser.h>
35 #include <afs/afscbint.h>
37 #include "afs_AdminInternal.h"
38 #include "afs_utilAdmin.h"
41 * AIX 4.2 has PTHREAD_CREATE_UNDETACHED and not PTHREAD_CREATE_JOINABLE
43 * This fix should be done more centrally, but there's no time right now.
45 #if defined(AFS_AIX_ENV)
46 # if !defined(PTHREAD_CREATE_JOINABLE) && defined(PTHREAD_CREATE_UNDETACHED)
47 # define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED
51 #define ERRCODE_RANGE 8
52 static pthread_once_t error_init_once = PTHREAD_ONCE_INIT;
53 static int error_init_done;
59 initialize_KA_error_table();
60 initialize_RXK_error_table();
61 initialize_KTC_error_table();
62 initialize_ACFG_error_table();
63 initialize_CMD_error_table();
64 initialize_VL_error_table();
65 initialize_PT_error_table();
66 initialize_BZ_error_table();
67 initialize_U_error_table();
68 initialize_AB_error_table();
69 initialize_AF_error_table();
70 initialize_AL_error_table();
71 initialize_AC_error_table();
72 initialize_AK_error_table();
73 initialize_AM_error_table();
74 initialize_AP_error_table();
75 initialize_AU_error_table();
76 initialize_AV_error_table();
77 initialize_VOLS_error_table();
78 #ifdef AFS_KRB5_ERROR_ENV
85 * (*errorTextP) will not be freed by the caller.
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 = afs_error_message(code);
108 #ifdef AFS_KRB5_ERROR_ENV
109 if (strncmp(*errorTextP, "unknown", strlen("unknown")) == 0) {
110 const char *msg = fetch_krb5_error_message(code);
117 fail_util_AdminErrorCodeTranslate:
126 * The iterator functions and data for the database server retrieval functions.
129 typedef struct database_server_get {
132 struct afsconf_dir *conf;
133 struct afsconf_cell cell;
134 util_databaseServerEntry_t server[CACHED_ITEMS];
135 } database_server_get_t, *database_server_get_p;
138 GetDatabaseServerRPC(void *rpc_specific, int slot, int *last_item,
139 int *last_item_contains_data, afs_status_p st)
142 afs_status_t tst = 0;
143 database_server_get_p serv = (database_server_get_p) rpc_specific;
145 serv->server[slot].serverAddress =
146 ntohl(serv->cell.hostAddr[serv->index].sin_addr.s_addr);
147 strcpy(serv->server[slot].serverName, serv->cell.hostName[serv->index]);
151 * See if we've processed all the entries
154 if (serv->index == serv->total) {
156 *last_item_contains_data = 1;
167 GetDatabaseServerFromCache(void *rpc_specific, int slot, void *dest,
171 afs_status_t tst = 0;
172 database_server_get_p serv = (database_server_get_p) rpc_specific;
174 memcpy(dest, (const void *)&serv->server[slot],
175 sizeof(util_databaseServerEntry_t));
185 DestroyDatabaseServer(void *rpc_specific, afs_status_p st)
188 afs_status_t tst = 0;
189 database_server_get_p serv = (database_server_get_p) rpc_specific;
191 afsconf_Close(serv->conf);
201 * util_DatabaseServerGetBegin - begin iterating over the database
202 * server machines in a cell.
206 * IN cellName - the cell where database servers reside.
208 * OUT iterationIdP - upon successful completion contains an iterator that
209 * can be passed to util_DatabaseServerGetNext.
213 * No locks are obtained or released by this function
221 * Returns != 0 upon successful completion.
225 util_DatabaseServerGetBegin(const char *cellName, void **iterationIdP,
229 afs_status_t tst = 0;
230 afs_admin_iterator_p iter =
231 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
232 database_server_get_p serv =
233 (database_server_get_p) calloc(1, sizeof(database_server_get_t));
234 char copyCell[MAXCELLCHARS];
240 if ((cellName == NULL) || (*cellName == 0)) {
241 tst = ADMUTILCELLNAMENULL;
242 goto fail_util_DatabaseServerGetBegin;
245 if (iterationIdP == NULL) {
246 goto fail_util_DatabaseServerGetBegin;
249 if ((iter == NULL) || (serv == NULL)) {
251 goto fail_util_DatabaseServerGetBegin;
255 * Fill in the serv structure
258 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
259 if (serv->conf == NULL) {
260 tst = ADMUTILCANTOPENCELLSERVDB;
261 goto fail_util_DatabaseServerGetBegin;
265 * We must copy the cellname because afsconf_GetCellInfo
266 * actually writes over the cell name it is passed.
268 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
270 afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
273 goto fail_util_DatabaseServerGetBegin;
276 serv->total = serv->cell.numServers;
278 (iter, (void *)serv, GetDatabaseServerRPC, GetDatabaseServerFromCache,
279 NULL, DestroyDatabaseServer, &tst)) {
280 *iterationIdP = (void *)iter;
282 goto fail_util_DatabaseServerGetBegin;
286 fail_util_DatabaseServerGetBegin:
304 * util_DatabaseServerGetNext - get the next server address.
308 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
310 * OUT serverAddressP - upon successful completion contains the next
311 * server address in the cell.
315 * This function locks the iterator for the duration of its processing.
323 * Returns != 0 upon successful completion.
328 util_DatabaseServerGetNext(const void *iterationId,
329 util_databaseServerEntry_p serverP,
333 afs_status_t tst = 0;
334 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
337 tst = ADMITERATORNULL;
338 goto fail_util_DatabaseServerGetNext;
341 if (serverP == NULL) {
342 tst = ADMUTILSERVERADDRESSPNULL;
343 goto fail_util_DatabaseServerGetNext;
346 rc = IteratorNext(iter, (void *)serverP, &tst);
348 fail_util_DatabaseServerGetNext:
357 * util_DatabaseServerGetDone - stop using a database iterator.
361 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
365 * This function locks the iterator for the duration of its processing.
366 * And then destroys it before returning.
374 * Returns != 0 upon successful completion.
378 util_DatabaseServerGetDone(const void *iterationId, afs_status_p st)
381 afs_status_t tst = 0;
382 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
385 * Validate parameters
389 tst = ADMITERATORNULL;
390 goto fail_util_DatabaseServerGetDone;
393 rc = IteratorDone(iter, &tst);
395 fail_util_DatabaseServerGetDone:
404 * GetServerAddressFromName - translate a character string server name
405 * to an integer representation of an IP address.
409 * IN serverName - the character string server name in either foo.com
410 * format, or 123.12.1.1 format.
412 * OUT serverAddress - an integer that is filled with the correct address
413 * in host byte order upon successful completion.
417 * No locks are obtained or released by this function
421 * On many platforms, gethostbyname is not thread safe. Since we are
422 * only working under NT for now I'll use it directly. In future UNIX
423 * ports, a wrapper function should be written to call the correct function
424 * on the particular platform.
428 * Returns != 0 upon successful completion.
432 util_AdminServerAddressGetFromName(const char *serverName, int *serverAddress,
436 afs_status_t tst = 0;
437 struct hostent *server;
438 int part1, part2, part3, part4;
441 if ((serverName == NULL) || (*serverName == 0)) {
442 tst = ADMUTILSERVERNAMENULL;
443 goto fail_util_AdminServerAddressGetFromName;
446 if (serverAddress == NULL) {
447 tst = ADMUTILSERVERADDRESSNULL;
448 goto fail_util_AdminServerAddressGetFromName;
452 sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
453 if (num_converted == 4) {
454 *serverAddress = (part1 << 24) | (part2 << 16) | (part3 << 8) | part4;
457 server = gethostbyname(serverName);
458 if (server != NULL) {
459 memcpy((void *)serverAddress, (const void *)server->h_addr,
461 *serverAddress = ntohl(*serverAddress);
463 tst = ADMUTILCANTGETSERVERNAME;
465 goto fail_util_AdminServerAddressGetFromName;
471 fail_util_AdminServerAddressGetFromName:
481 * This file contains functions that can be used to create iterator
482 * functions within the api. I have attempted to make these functions
483 * generic so that they can be used across the admin components.
485 * The functions in this file are a generalized producer/consumer
486 * implementation. They manage access to a queue of data. The only
487 * assumption these functions make about this data is that it is
488 * stored in a queue which is implemented via an array. These functions
489 * know about the index into the array, but they know nothing about
490 * the contents of the array.
492 * The data specific functions you implement will have to create some
493 * data specific storage structure that will have an array
494 * of size CACHED_ITEMS data items. This structure will also need to
495 * store any necessary parameters/state variables you need to issue the
496 * rpc to retrieve the next item.
498 * In order to use the generic functions, you must implement four functions
499 * for each type of data you wish to retrieve. The functions are:
501 * validate_specific_data_func - this function is handed a void pointer
502 * that points to the rpc specific data you've allocated. The function
503 * should examine the data for validity and return an appropriate error.
504 * This function is called every time the iterator is validated.
506 * destroy_specific_data_func - this function is handed a void pointer
507 * that points to the rpc specific data you've allocated. It should
508 * destroy any components of the specific data as required and then
509 * return. The void pointer is free'd by the generic functions.
511 * get_cached_data_func - this function is handed a void pointer
512 * that points to the rpc specific data you've allocated, an index
513 * into the cache of the item to be copied to the caller, and a void
514 * pointer where the cache item should be copied.
516 * make_rpc_func - this function is handed a void pointer that points
517 * to the rpc specific data you've allocated, an index into the cache
518 * of the item to be filled with the next retrieved item, and an int
519 * pointer that should be set to 1 if there are no more items to be
520 * retrieved. The assumption made by the generic functions is that
521 * the last_item status requires an individual rpc - the data isn't
522 * piggybacked on the last data item.
526 * IteratorDelete - delete an iterator.
530 * IN interator - the iterator to delete.
534 * No locks are held by this function.
538 * Returns != 0 upon successful completion.
542 IteratorDelete(afs_admin_iterator_p iter, afs_status_p st)
545 afs_status_t tst = 0;
547 if (pthread_mutex_destroy(&iter->mutex)) {
548 tst = ADMMUTEXDESTROY;
549 goto fail_IteratorDelete;
551 if (pthread_cond_destroy(&iter->add_item)) {
552 tst = ADMCONDDESTROY;
553 goto fail_IteratorDelete;
555 if (pthread_cond_destroy(&iter->remove_item)) {
556 tst = ADMCONDDESTROY;
557 goto fail_IteratorDelete;
560 if (iter->destroy_specific != NULL) {
561 iter->destroy_specific(iter->rpc_specific, &tst);
563 free(iter->rpc_specific);
576 * DataGet - the background thread that is spawned for every
577 * IteratorBegin call that is successful. This thread tries
578 * to fetch the data from the server ahead of the
579 * IteratorNext calls.
583 * IN arg - the address of the iterator structure to be used for this
588 * The iterator mutex is used by this function to protect elements
589 * of the iterator structure.
593 * Returns != 0 upon successful completion.
599 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
601 afs_status_t tst = 0;
602 int mutex_locked = 0;
604 int last_item_contains_data = 0;
606 if (pthread_mutex_lock(&iter->mutex)) {
607 iter->st = ADMMUTEXLOCK;
616 * Check to see if there's room for this datum. If not, wait
617 * on the consumer to free up another slot.
620 while (iter->cache_slots_used == CACHED_ITEMS) {
621 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
622 iter->st = ADMCONDWAIT;
628 * Check to see if someone called Done and terminated the request.
629 * We could have gone to sleep above when the buffer was full and
630 * instead of being awoken because another slot is open, we were
631 * awoken because the request was terminated.
634 if (iter->request_terminated) {
638 if (pthread_mutex_unlock(&iter->mutex)) {
639 iter->st = ADMMUTEXUNLOCK;
646 * Make an rpc without holding the iter mutex
647 * We reference an item in the principal cache here without
648 * holding the mutex. This is safe because:
649 * 1. The iter structure is ref counted and won't be deleted
650 * from underneath us.
651 * 2. cache_queue_tail is always one item ahead of the consumer
652 * thread so we are the only thread accessing this member.
655 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail, &last_item,
656 &last_item_contains_data, &tst);
658 if (pthread_mutex_lock(&iter->mutex)) {
659 iter->st = ADMMUTEXLOCK;
666 * Check to see if someone called Done and terminated the request
669 if (iter->request_terminated) {
674 * Check the rc of the rpc, and see if there are no more items
684 * Check to see if this is the last item produced by the rpc.
685 * If it isn't, add the item to the cache and proceed.
686 * If it is, check to see if the last item contains valid data.
687 * If it contains valid data, we need to add it to our cache.
688 * If it doesn't, we mark the iterator as complete.
691 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
692 iter->cache_queue_tail =
693 (iter->cache_queue_tail + 1) % CACHED_ITEMS;
694 iter->cache_slots_used++;
697 iter->st = ADMITERATORDONE;
698 iter->done_iterating = 1;
700 * There's a small chance that the consumer emptied the
701 * cache queue while we were making the last rpc and has
702 * since gone to sleep waiting for more data. In this case
703 * there will never be more data so we signal him here.
705 pthread_cond_signal(&iter->add_item);
711 * If the cache was empty and we just added another item, signal
715 if (iter->cache_slots_used == 1) {
716 if (pthread_cond_signal(&iter->add_item)) {
717 iter->st = ADMCONDSIGNAL;
727 * If we are exiting with an error, signal the consumer in the event
728 * they were waiting for us to produce more data
732 pthread_cond_signal(&iter->add_item);
736 pthread_mutex_unlock(&iter->mutex);
743 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
747 * IN interator - the interator to be verified.
751 * We assume the iter->mutex lock is already held.
755 * Returns != 0 upon successful completion.
759 IsValidIterator(const afs_admin_iterator_p iterator, afs_status_p st)
762 afs_status_t tst = 0;
765 * Validate input parameters
768 if (iterator == NULL) {
769 tst = ADMITERATORNULL;
770 goto fail_IsValidIterator;
773 if ((iterator->begin_magic != BEGIN_MAGIC)
774 || (iterator->end_magic != END_MAGIC)) {
775 tst = ADMITERATORBADMAGICNULL;
776 goto fail_IsValidIterator;
779 if (iterator->is_valid == 0) {
780 tst = ADMITERATORINVALID;
781 goto fail_IsValidIterator;
785 * Call the iterator specific validation function
788 if (iterator->validate_specific != NULL) {
789 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
790 goto fail_IsValidIterator;
795 fail_IsValidIterator:
804 * IteratorNext - return the next datum in an interator.
808 * IN interator - the iterator containing the data.
810 * IN dest - the address where the data should be copied.
814 * Lock the iterator upon entry, and hold it during the duration of this
819 * Returns != 0 upon successful completion.
823 IteratorNext(afs_admin_iterator_p iter, void *dest, afs_status_p st)
826 afs_status_t tst = 0;
830 * We have to lock the iterator before we validate it
833 if (pthread_mutex_lock(&iter->mutex)) {
835 goto fail_IteratorNext;
840 if (!IsValidIterator(iter, &tst)) {
841 goto fail_IteratorNext;
844 if (iter->request_terminated == 1) {
845 tst = ADMITERATORTERMINATED;
846 goto fail_IteratorNext;
849 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
851 goto fail_IteratorNext;
855 * Check to see if there are any queue'd items. If not, wait here
856 * until signalled by the producer.
859 while (iter->cache_slots_used == 0) {
862 * Maybe the producer experienced an rpc failure.
865 if ((!iter->done_iterating) && (iter->st != 0)) {
867 goto fail_IteratorNext;
871 * Maybe there are no queue'd items because the producer is done
874 if (iter->done_iterating) {
876 goto fail_IteratorNext;
879 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
881 goto fail_IteratorNext;
886 * Copy the next cached item and update the cached item count
887 * and the index into the cache array
891 get_cached_data(iter->rpc_specific, iter->cache_queue_head, dest,
893 goto fail_IteratorNext;
896 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
897 iter->cache_slots_used--;
900 * If the cache was full before we removed the item above, the
901 * producer may have been waiting for us to remove an item.
902 * Signal the producer letting him know that we've opened a slot
906 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
907 if (pthread_cond_signal(&iter->remove_item)) {
909 goto fail_IteratorNext;
917 if (locked_iter == 1) {
918 pthread_mutex_unlock(&iter->mutex);
928 * IteratorDone - mark the iterator done.
932 * IN interator - the iterator to mark done.
936 * Lock the iterator upon entry, and hold it during the duration of this
941 * Returns != 0 upon successful completion.
945 IteratorDone(afs_admin_iterator_p iter, afs_status_p st)
948 afs_status_t tst = 0;
949 int mutex_locked = 1;
951 if (pthread_mutex_lock(&iter->mutex)) {
953 goto fail_IteratorDone;
959 if (!IsValidIterator(iter, &tst)) {
960 goto fail_IteratorDone;
965 * Depending upon the status of the background worker thread,
966 * we can either join with him immediately (if we know he has
967 * terminated), or we need to tell him the request has been
968 * terminated and then join with him.
971 if (!iter->done_iterating) {
972 iter->request_terminated = 1;
973 iter->cache_slots_used = 0;
974 pthread_cond_signal(&iter->remove_item);
978 * We have to unlock the mutex to allow the background thread to
982 if (pthread_mutex_unlock(&iter->mutex)) {
983 tst = ADMMUTEXUNLOCK;
984 goto fail_IteratorDone;
987 if (iter->make_rpc != NULL) {
988 if (pthread_join(iter->bg_worker, (void **)0)) {
990 goto fail_IteratorDone;
995 * We don't relock the mutex here since we are the only thread
996 * that has access to the iter now
999 rc = IteratorDelete(iter, &tst);
1005 pthread_mutex_unlock(&iter->mutex);
1015 * IteratorInit - initialize an iterator.
1019 * IN interator - the iterator to initialize.
1023 * No locks are held by this function.
1027 * Returns != 0 upon successful completion.
1031 IteratorInit(afs_admin_iterator_p iter, void *rpc_specific,
1032 make_rpc_func make_rpc, get_cached_data_func get_cached_data,
1033 validate_specific_data_func validate_specific_data,
1034 destroy_specific_data_func destroy_specific_data,
1038 afs_status_t tst = 0;
1039 int mutex_inited = 0;
1040 int add_item_cond_inited = 0;
1041 int remove_item_cond_inited = 0;
1044 tst = ADMITERATORNULL;
1045 goto fail_IteratorInit;
1048 if (rpc_specific == NULL) {
1049 tst = ADMITERATORRPCSPECIFICNULL;
1050 goto fail_IteratorInit;
1054 * Initialize the iterator structure
1056 iter->begin_magic = BEGIN_MAGIC;
1057 iter->end_magic = END_MAGIC;
1059 iter->cache_slots_used = 0;
1060 iter->done_iterating = 0;
1061 iter->request_terminated = 0;
1062 iter->st = AFS_STATUS_OK;
1063 iter->cache_queue_head = 0;
1064 iter->cache_queue_tail = 0;
1065 iter->cache_slots_used = 0;
1066 iter->rpc_specific = rpc_specific;
1067 iter->make_rpc = make_rpc;
1068 iter->get_cached_data = get_cached_data;
1069 iter->validate_specific = validate_specific_data;
1070 iter->destroy_specific = destroy_specific_data;
1072 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *)0)) {
1074 goto fail_IteratorInit;
1079 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *)0)) {
1081 goto fail_IteratorInit;
1083 add_item_cond_inited = 1;
1086 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *)0)) {
1088 goto fail_IteratorInit;
1090 remove_item_cond_inited = 1;
1094 * Create a worker thread that will begin to query the server
1095 * and cache responses.
1098 if (iter->make_rpc != NULL) {
1099 pthread_attr_t tattr;
1101 if (pthread_attr_init(&tattr)) {
1102 tst = ADMTHREADATTRINIT;
1103 goto fail_IteratorInit;
1106 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1107 tst = ADMTHREADATTRSETDETACHSTATE;
1108 goto fail_IteratorInit;
1111 if (pthread_create(&iter->bg_worker, &tattr, DataGet, (void *)iter)) {
1112 tst = ADMTHREADCREATE;
1113 goto fail_IteratorInit;
1122 pthread_mutex_destroy(&iter->mutex);
1124 if (remove_item_cond_inited) {
1125 pthread_cond_destroy(&iter->remove_item);
1127 if (add_item_cond_inited) {
1128 pthread_cond_destroy(&iter->add_item);
1139 CellHandleIsValid(const void *cellHandle, afs_status_p st)
1142 afs_status_t tst = 0;
1143 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1146 * Validate input parameters
1149 if (c_handle == NULL) {
1150 tst = ADMCLIENTCELLHANDLENULL;
1151 goto fail_CellHandleIsValid;
1154 if ((c_handle->begin_magic != BEGIN_MAGIC)
1155 || (c_handle->end_magic != END_MAGIC)) {
1156 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1157 goto fail_CellHandleIsValid;
1160 if (c_handle->is_valid == 0) {
1161 tst = ADMCLIENTCELLINVALID;
1162 goto fail_CellHandleIsValid;
1166 fail_CellHandleIsValid:
1175 * The iterator functions and data for the rpc statistic retrieval functions
1178 typedef struct rpc_stat_get {
1179 afs_uint32 clock_sec;
1180 afs_uint32 clock_usec;
1183 afs_uint32 clientVersion;
1184 afs_uint32 serverVersion;
1185 struct rpcStats stat_list;
1186 afs_RPCStats_t stats[CACHED_ITEMS];
1187 afs_uint32 *pointer;
1188 } rpc_stat_get_t, *rpc_stat_get_p;
1191 UnmarshallRPCStats(afs_uint32 serverVersion, afs_uint32 ** ptrP,
1195 unsigned int hi, lo;
1198 * Server must always match lower versions. We are version 1.
1201 s->stats_v1.remote_peer = *(ptr++);
1202 s->stats_v1.remote_port = *(ptr++);
1203 s->stats_v1.remote_is_server = *(ptr++);
1204 s->stats_v1.interfaceId = *(ptr++);
1205 s->stats_v1.func_total = *(ptr++);
1206 s->stats_v1.func_index = *(ptr++);
1209 hset64(s->stats_v1.invocations, hi, lo);
1212 hset64(s->stats_v1.bytes_sent, hi, lo);
1215 hset64(s->stats_v1.bytes_rcvd, hi, lo);
1216 s->stats_v1.queue_time_sum.sec = *(ptr++);
1217 s->stats_v1.queue_time_sum.usec = *(ptr++);
1218 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1219 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1220 s->stats_v1.queue_time_min.sec = *(ptr++);
1221 s->stats_v1.queue_time_min.usec = *(ptr++);
1222 s->stats_v1.queue_time_max.sec = *(ptr++);
1223 s->stats_v1.queue_time_max.usec = *(ptr++);
1224 s->stats_v1.execution_time_sum.sec = *(ptr++);
1225 s->stats_v1.execution_time_sum.usec = *(ptr++);
1226 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1227 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1228 s->stats_v1.execution_time_min.sec = *(ptr++);
1229 s->stats_v1.execution_time_min.usec = *(ptr++);
1230 s->stats_v1.execution_time_max.sec = *(ptr++);
1231 s->stats_v1.execution_time_max.usec = *(ptr++);
1236 GetRPCStatsRPC(void *rpc_specific, int slot, int *last_item,
1237 int *last_item_contains_data, afs_status_p st)
1240 afs_status_t tst = 0;
1241 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1243 t->stats[slot].clientVersion = t->clientVersion;
1244 t->stats[slot].serverVersion = t->serverVersion;
1245 t->stats[slot].statCount = t->total;
1248 * If the server stat version is greater than or equal to my version
1249 * number, it is required to return the values in the client's current
1253 UnmarshallRPCStats(t->serverVersion, &t->pointer, &t->stats[slot].s);
1258 * See if we've processed all the entries
1261 if (t->index == t->total) {
1263 *last_item_contains_data = 1;
1274 GetRPCStatsFromCache(void *rpc_specific, int slot, void *dest,
1278 afs_status_t tst = 0;
1279 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1281 memcpy(dest, (const void *)&stat->stats[slot], sizeof(afs_RPCStats_t));
1291 DestroyRPCStats(void *rpc_specific, afs_status_p st)
1294 afs_status_t tst = 0;
1295 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1297 if (stat->stat_list.rpcStats_val != NULL) {
1298 free(stat->stat_list.rpcStats_val);
1309 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1313 * IN conn - an rx connection to the process to be queried
1315 * IN rpc - the function to call to make the actual rpc
1317 * OUT iterationIdP - an iteration id that can be passed to
1318 * util_RPCStatsGetNext to get the next rpc stat
1322 * No locks are obtained or released by this function
1326 * Returns != 0 upon successful completion.
1331 util_RPCStatsGetBegin(struct rx_connection *conn,
1332 int (*rpc) (struct rx_connection *,
1333 afs_uint32, afs_uint32 *,
1334 afs_uint32 *, afs_uint32 *,
1335 afs_uint32 *, struct rpcStats *),
1336 void **iterationIdP, afs_status_p st)
1339 afs_status_t tst = 0;
1340 afs_admin_iterator_p iter =
1341 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1342 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1345 tst = ADMRXCONNNULL;
1346 goto fail_util_RPCStatsGetBegin;
1350 tst = ADMRPCPTRNULL;
1351 goto fail_util_RPCStatsGetBegin;
1354 if (iterationIdP == NULL) {
1355 tst = ADMITERATIONIDPNULL;
1356 goto fail_util_RPCStatsGetBegin;
1359 if ((iter == NULL) || (stat == NULL)) {
1361 goto fail_util_RPCStatsGetBegin;
1364 stat->stat_list.rpcStats_len = 0;
1365 stat->stat_list.rpcStats_val = 0;
1367 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1370 (*rpc) (conn, stat->clientVersion, &stat->serverVersion,
1371 &stat->clock_sec, &stat->clock_usec, &stat->total,
1375 goto fail_util_RPCStatsGetBegin;
1379 * If there are no statistics, just mark the iterator done and
1383 if (stat->stat_list.rpcStats_len == 0) {
1384 stat->pointer = NULL;
1385 if (!IteratorInit(iter, (void *)stat, NULL, NULL, NULL, NULL, &tst)) {
1386 goto fail_util_RPCStatsGetBegin;
1388 iter->done_iterating = 1;
1389 iter->st = ADMITERATORDONE;
1391 stat->pointer = stat->stat_list.rpcStats_val;
1393 (iter, (void *)stat, GetRPCStatsRPC, GetRPCStatsFromCache, NULL,
1394 DestroyRPCStats, &tst)) {
1395 goto fail_util_RPCStatsGetBegin;
1398 *iterationIdP = (void *)iter;
1401 fail_util_RPCStatsGetBegin:
1419 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1423 * IN iterationId - an iterator previously returned by
1424 * util_RPCStatsGetBegin.
1426 * OUT stats - upon successful completion contains the next set of stats
1431 * No locks are obtained or released by this function
1435 * Returns != 0 upon successful completion.
1440 util_RPCStatsGetNext(const void *iterationId, afs_RPCStats_p stats,
1444 afs_status_t tst = 0;
1445 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1447 if (iterationId == NULL) {
1448 tst = ADMITERATIONIDPNULL;
1449 goto fail_util_RPCStatsGetNext;
1452 if (stats == NULL) {
1453 tst = ADMUTILRPCSTATSNULL;
1454 goto fail_util_RPCStatsGetNext;
1457 rc = IteratorNext(iter, (void *)stats, &tst);
1459 fail_util_RPCStatsGetNext:
1468 * util_RPCStatsGetDone - finish using a stats iterator
1472 * IN iterationId - an iterator previously returned by
1473 * util_RPCStatsGetBegin.
1477 * No locks are obtained or released by this function
1481 * Returns != 0 upon successful completion.
1486 util_RPCStatsGetDone(const void *iterationId, afs_status_p st)
1489 afs_status_t tst = 0;
1490 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1492 if (iterationId == NULL) {
1493 tst = ADMITERATIONIDPNULL;
1494 goto fail_util_RPCStatsGetDone;
1497 rc = IteratorDone(iter, &tst);
1499 fail_util_RPCStatsGetDone:
1508 * util_RPCStatsStateGet - get the current state of rpc stat collection
1512 * IN conn - an rx connection to the process to be queried
1514 * IN rpc - the function to call to make the actual rpc
1516 * OUT state - the rpc stat collection state.
1520 * No locks are obtained or released by this function
1524 * Returns != 0 upon successful completion.
1529 util_RPCStatsStateGet(struct rx_connection *conn,
1530 int (*rpc) (struct rx_connection *,
1531 afs_RPCStatsState_p),
1532 afs_RPCStatsState_p state, afs_status_p st)
1535 afs_status_t tst = 0;
1538 tst = ADMRXCONNNULL;
1539 goto fail_util_RPCStatsStateGet;
1543 tst = ADMRPCPTRNULL;
1544 goto fail_util_RPCStatsStateGet;
1547 if (state == NULL) {
1548 tst = ADMRPCSTATENULL;
1549 goto fail_util_RPCStatsStateGet;
1552 tst = (*rpc) (conn, state);
1558 fail_util_RPCStatsStateGet:
1567 * util_RPCStatsStateEnable - enable rpc stat collection
1572 * IN conn - an rx connection to the process to be modified
1574 * IN rpc - the function to call to make the actual rpc
1578 * No locks are obtained or released by this function
1582 * Returns != 0 upon successful completion.
1587 util_RPCStatsStateEnable(struct rx_connection *conn,
1588 int (*rpc) (struct rx_connection *),
1592 afs_status_t tst = 0;
1595 tst = ADMRXCONNNULL;
1596 goto fail_util_RPCStatsStateEnable;
1600 tst = ADMRPCPTRNULL;
1601 goto fail_util_RPCStatsStateEnable;
1604 tst = (*rpc) (conn);
1610 fail_util_RPCStatsStateEnable:
1619 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1624 * IN conn - an rx connection to the process to be modified
1626 * IN rpc - the function to call to make the actual rpc
1630 * No locks are obtained or released by this function
1634 * Returns != 0 upon successful completion.
1639 util_RPCStatsStateDisable(struct rx_connection *conn,
1640 int (*rpc) (struct rx_connection *),
1644 afs_status_t tst = 0;
1647 tst = ADMRXCONNNULL;
1648 goto fail_util_RPCStatsStateDisable;
1652 tst = ADMRPCPTRNULL;
1653 goto fail_util_RPCStatsStateDisable;
1656 tst = (*rpc) (conn);
1662 fail_util_RPCStatsStateDisable:
1671 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1672 * collection at a server
1676 * IN conn - an rx connection to the process to be modified
1678 * IN rpc - the function to call to make the actual rpc
1680 * IN flag - a flag containing the fields to be cleared
1685 * No locks are obtained or released by this function
1689 * Returns != 0 upon successful completion.
1694 util_RPCStatsClear(struct rx_connection *conn,
1695 int (*rpc) (struct rx_connection *,
1696 afs_RPCStatsClearFlag_t),
1697 afs_RPCStatsClearFlag_t flag, afs_status_p st)
1700 afs_status_t tst = 0;
1703 tst = ADMRXCONNNULL;
1704 goto fail_util_RPCStatsClear;
1708 tst = ADMRPCPTRNULL;
1709 goto fail_util_RPCStatsClear;
1712 tst = (*rpc) (conn, flag);
1718 fail_util_RPCStatsClear:
1727 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1731 * IN conn - an rx connection to the process to be modified
1733 * OUT version - the version of rpc stat collection at the remote process
1737 * No locks are obtained or released by this function
1741 * Returns != 0 upon successful completion.
1746 util_RPCStatsVersionGet(struct rx_connection *conn,
1747 afs_RPCStatsVersion_p version, afs_status_p st)
1750 afs_status_t tst = 0;
1753 tst = ADMRXCONNNULL;
1754 goto fail_util_RPCStatsVersionGet;
1757 if (version == NULL) {
1758 tst = ADMRPCVERSIONNULL;
1759 goto fail_util_RPCStatsVersionGet;
1762 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1768 fail_util_RPCStatsVersionGet:
1777 * The iterator for listing CM server preferences
1780 typedef struct cm_srvr_pref_get {
1781 struct rx_connection *conn;
1783 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1784 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1787 GetServerPrefsRPC(void *rpc_specific, int slot, int *last_item,
1788 int *last_item_contains_data, afs_status_p st)
1791 afs_status_t tst = 0;
1792 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1795 * Get the next entry in the list of server preferences.
1798 RXAFSCB_GetServerPrefs(t->conn, t->index, &t->srvrPrefs[slot].ipAddr,
1799 &t->srvrPrefs[slot].ipRank);
1801 goto fail_GetServerPrefsRPC;
1805 * See if we've processed all the entries
1807 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1809 *last_item_contains_data = 0;
1815 fail_GetServerPrefsRPC:
1824 GetServerPrefsFromCache(void *rpc_specific, int slot, void *dest,
1828 afs_status_t tst = 0;
1829 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1831 memcpy(dest, (const void *)&prefs->srvrPrefs[slot],
1832 sizeof(afs_CMServerPref_t));
1842 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1846 * IN conn - an rx connection to the process to be queried
1848 * OUT iterationIdP - an iteration id that can be passed to
1849 * util_CMGetServerPrefsNext to get the next server preference
1853 * No locks are obtained or released by this function
1857 * Returns != 0 upon successful completion.
1862 util_CMGetServerPrefsBegin(struct rx_connection *conn, void **iterationIdP,
1866 afs_status_t tst = 0;
1867 afs_admin_iterator_p iter;
1868 cm_srvr_pref_get_p pref;
1871 tst = ADMRXCONNNULL;
1872 goto fail_util_CMGetServerPrefsBegin;
1875 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1878 goto fail_util_CMGetServerPrefsBegin;
1881 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1885 goto fail_util_CMGetServerPrefsBegin;
1891 (iter, (void *)pref, GetServerPrefsRPC, GetServerPrefsFromCache, NULL,
1895 goto fail_util_CMGetServerPrefsBegin;
1897 *iterationIdP = (void *)iter;
1900 fail_util_CMGetServerPrefsBegin:
1909 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1914 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1916 * OUT prefs - Next entry in cache manager server preferences.
1920 * No locks are obtained or released by this function
1924 * Returns != 0 upon successful completion.
1929 util_CMGetServerPrefsNext(const void *iterationId, afs_CMServerPref_p prefs,
1933 afs_status_t tst = 0;
1934 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1936 if (iterationId == NULL) {
1937 tst = ADMITERATIONIDPNULL;
1938 goto fail_util_CMGetServerPrefsNext;
1941 rc = IteratorNext(iter, (void *)prefs, &tst);
1943 fail_util_CMGetServerPrefsNext:
1952 * util_CMGetServerPrefsDone - Finish listing cache manager server
1957 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1961 * No locks are obtained or released by this function
1965 * Returns != 0 upon successful completion.
1970 util_CMGetServerPrefsDone(const void *iterationId, afs_status_p st)
1973 afs_status_t tst = 0;
1974 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1976 if (iterationId == NULL) {
1977 tst = ADMITERATIONIDPNULL;
1978 goto fail_util_CMGetServerPrefsDone;
1981 rc = IteratorDone(iter, &tst);
1984 fail_util_CMGetServerPrefsDone:
1993 * The iterator for listing CM CellServDB
1996 typedef struct cm_list_cell_get {
1997 struct rx_connection *conn;
1999 afs_CMListCell_t cell[CACHED_ITEMS];
2000 } cm_list_cell_get_t, *cm_list_cell_get_p;
2003 ListCellsRPC(void *rpc_specific, int slot, int *last_item,
2004 int *last_item_contains_data, afs_status_p st)
2007 afs_status_t tst = 0;
2008 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2014 * Get the next entry in the CellServDB.
2016 name = t->cell[slot].cellname;
2017 sl.serverList_len = 0;
2018 sl.serverList_val = NULL;
2019 memset(t->cell[slot].serverAddr, 0, sizeof(afs_int32)*UTIL_MAX_CELL_HOSTS);
2021 RXAFSCB_GetCellServDB(t->conn, t->index, &name, &sl);
2023 goto fail_ListCellsRPC;
2025 strcpy(t->cell[slot].cellname, name);
2026 if (sl.serverList_val) {
2027 for (n=0; n<sl.serverList_len && n<UTIL_MAX_CELL_HOSTS; n++) {
2028 t->cell[slot].serverAddr[n] = sl.serverList_val[n];
2030 xdr_free((xdrproc_t) xdr_serverList, &sl);
2034 * See if we've processed all the entries
2036 if (strlen(t->cell[slot].cellname) == 0) {
2038 *last_item_contains_data = 0;
2053 ListCellsFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
2056 afs_status_t tst = 0;
2057 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2059 memcpy(dest, (const void *)&cell->cell[slot], sizeof(afs_CMListCell_t));
2069 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2073 * IN conn - an rx connection to the process to be queried
2075 * OUT iterationIdP - an iteration id that can be passed to
2076 * util_CMListCellsNext to get the next cell
2080 * No locks are obtained or released by this function
2084 * Returns != 0 upon successful completion.
2089 util_CMListCellsBegin(struct rx_connection *conn, void **iterationIdP,
2093 afs_status_t tst = 0;
2094 afs_admin_iterator_p iter;
2095 cm_list_cell_get_p cell;
2098 tst = ADMRXCONNNULL;
2099 goto fail_util_CMListCellsBegin;
2102 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2105 goto fail_util_CMListCellsBegin;
2108 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2112 goto fail_util_CMListCellsBegin;
2118 (iter, (void *)cell, ListCellsRPC, ListCellsFromCache, NULL, NULL,
2122 goto fail_util_CMListCellsBegin;
2124 *iterationIdP = (void *)iter;
2127 fail_util_CMListCellsBegin:
2136 * util_CMListCellsNext - Get next entry in cache manager cells
2140 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2142 * OUT cell - Next entry in cache manager cells.
2146 * No locks are obtained or released by this function
2150 * Returns != 0 upon successful completion.
2155 util_CMListCellsNext(const void *iterationId, afs_CMListCell_p cell,
2159 afs_status_t tst = 0;
2160 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2162 if (iterationId == NULL) {
2163 tst = ADMITERATIONIDPNULL;
2164 goto fail_util_CMListCellsNext;
2167 rc = IteratorNext(iter, (void *)cell, &tst);
2169 fail_util_CMListCellsNext:
2178 * util_CMListCellsDone - Finish listing cache manager cells
2182 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2186 * No locks are obtained or released by this function
2190 * Returns != 0 upon successful completion.
2195 util_CMListCellsDone(const void *iterationId, afs_status_p st)
2198 afs_status_t tst = 0;
2199 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2201 if (iterationId == NULL) {
2202 tst = ADMITERATIONIDPNULL;
2203 goto fail_util_CMListCellsDone;
2206 rc = IteratorDone(iter, &tst);
2209 fail_util_CMListCellsDone:
2218 * util_CMLocalCell - Get the name of the cache manager's local cell.
2222 * IN conn - an rx connection to the process to be queried
2224 * OUT cellName - the name of the cache manager's local cell.
2228 * No locks are obtained or released by this function
2232 * Returns != 0 upon successful completion.
2237 util_CMLocalCell(struct rx_connection *conn, afs_CMCellName_p cellName,
2241 afs_status_t tst = 0;
2242 afs_CMCellName_p name;
2245 tst = ADMRXCONNNULL;
2246 goto fail_util_CMLocalCell;
2249 if (cellName == NULL) {
2250 tst = ADMCLIENTCMCELLNAMENULL;
2251 goto fail_util_CMLocalCell;
2255 tst = RXAFSCB_GetLocalCell(conn, &name);
2261 fail_util_CMLocalCell:
2270 UnmarshallCMClientConfig(afs_uint32 serverVersion, afs_uint32 * ptr,
2271 afs_ClientConfigUnion_p config)
2274 * We currently only support version 1.
2276 config->config_v1.nChunkFiles = *(ptr++);
2277 config->config_v1.nStatCaches = *(ptr++);
2278 config->config_v1.nDataCaches = *(ptr++);
2279 config->config_v1.nVolumeCaches = *(ptr++);
2280 config->config_v1.firstChunkSize = *(ptr++);
2281 config->config_v1.otherChunkSize = *(ptr++);
2282 config->config_v1.cacheSize = *(ptr++);
2283 config->config_v1.setTime = *(ptr++);
2284 config->config_v1.memCache = *(ptr++);
2288 * util_CMClientConfig - Get the cache manager's configuration parameters.
2292 * IN conn - an rx connection to the process to be queried
2294 * OUT config - the cache manager's configuration parameters.
2298 * No locks are obtained or released by this function
2302 * Returns != 0 upon successful completion.
2307 util_CMClientConfig(struct rx_connection *conn, afs_ClientConfig_p config,
2311 afs_status_t tst = 0;
2312 afs_uint32 allocbytes;
2313 struct cacheConfig tconfig;
2316 tst = ADMRXCONNNULL;
2317 goto fail_util_CMClientConfig;
2320 if (config == NULL) {
2321 tst = ADMCLIENTCMCELLNAMENULL;
2322 goto fail_util_CMClientConfig;
2325 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2326 tconfig.cacheConfig_val = NULL;
2327 tconfig.cacheConfig_len = 0;
2329 RXAFSCB_GetCacheConfig(conn, config->clientVersion,
2330 &config->serverVersion, &allocbytes, &tconfig);
2333 goto fail_util_CMClientConfig;
2336 UnmarshallCMClientConfig(config->serverVersion, tconfig.cacheConfig_val,
2339 free(tconfig.cacheConfig_val);
2341 fail_util_CMClientConfig:
2350 * util_RXDebugVersion - Get the rxdebug version string.
2354 * IN handle - an rxdebug handle for the process to be queried.
2356 * OUT version - the rxdebug version string.
2360 * No locks are obtained or released by this function
2364 * Returns != 0 upon successful completion.
2369 util_RXDebugVersion(rxdebugHandle_p handle, rxdebugVersion_p version,
2373 afs_status_t tst = 0;
2376 if (handle == NULL) {
2377 tst = ADMRXDEBUGHANDLENULL;
2378 goto fail_util_RXDebugVersion;
2381 if (version == NULL) {
2382 tst = ADMRXDEBUGVERSIONNULL;
2383 goto fail_util_RXDebugVersion;
2387 rx_GetServerVersion(handle->sock, handle->ipAddr, handle->udpPort,
2388 UTIL_MAX_RXDEBUG_VERSION_LEN, version);
2390 tst = ADMCLIENTRXDEBUGTIMEOUT;
2391 goto fail_util_RXDebugVersion;
2396 fail_util_RXDebugVersion:
2405 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2410 * IN handle - an rxdebug handle for the process to be queried.
2412 * OUT supportedStats - bit mask with supported rxstats.
2416 * No locks are obtained or released by this function
2420 * Returns != 0 upon successful completion.
2425 util_RXDebugSupportedStats(rxdebugHandle_p handle,
2426 afs_uint32 * supportedStats, afs_status_p st)
2429 afs_status_t tst = 0;
2430 struct rx_debugStats tstats;
2432 if (handle == NULL) {
2433 tst = ADMRXDEBUGHANDLENULL;
2434 goto fail_util_RXDebugSupportedStats;
2437 if (supportedStats == NULL) {
2438 tst = ADMRXDEBUGSTATSNULL;
2439 goto fail_util_RXDebugSupportedStats;
2442 if (handle->firstFlag) {
2443 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2445 goto fail_util_RXDebugSupportedStats;
2449 *supportedStats = handle->supportedStats;
2452 fail_util_RXDebugSupportedStats:
2462 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2466 * IN handle - an rxdebug handle for the process to be queried.
2468 * OUT stats - Basic rxdebug statistics for the process.
2472 * No locks are obtained or released by this function
2476 * Returns != 0 upon successful completion.
2481 util_RXDebugBasicStats(rxdebugHandle_p handle, struct rx_debugStats *stats,
2485 afs_status_t tst = 0;
2488 if (handle == NULL) {
2489 tst = ADMRXDEBUGHANDLENULL;
2490 goto fail_util_RXDebugBasicStats;
2493 if (stats == NULL) {
2494 tst = ADMRXDEBUGSTATSNULL;
2495 goto fail_util_RXDebugBasicStats;
2499 rx_GetServerDebug(handle->sock, handle->ipAddr, handle->udpPort,
2500 stats, &handle->supportedStats);
2502 tst = ADMCLIENTRXDEBUGTIMEOUT;
2503 goto fail_util_RXDebugBasicStats;
2506 handle->firstFlag = 0;
2509 fail_util_RXDebugBasicStats:
2519 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2523 * IN handle - an rxdebug handle for the process to be queried.
2525 * OUT stats - Detailed rxdebug statistics for the process.
2529 * No locks are obtained or released by this function
2533 * Returns != 0 upon successful completion.
2538 util_RXDebugRxStats(rxdebugHandle_p handle, struct rx_statistics *stats,
2539 afs_uint32 * supportedValues, afs_status_p st)
2543 afs_status_t tst = 0;
2545 afs_uint32 tsupported;
2547 if (handle == NULL) {
2548 tst = ADMRXDEBUGHANDLENULL;
2549 goto fail_util_RXDebugRxStats;
2552 if (supportedValues == NULL) {
2553 tst = ADMRXDEBUGSTATSNULL;
2554 goto fail_util_RXDebugRxStats;
2557 if (stats == NULL) {
2558 tst = ADMRXDEBUGSTATSNULL;
2559 goto fail_util_RXDebugRxStats;
2562 if (handle->firstFlag) {
2563 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2566 goto fail_util_RXDebugRxStats;
2570 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2571 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2572 goto fail_util_RXDebugRxStats;
2576 rx_GetServerStats(handle->sock, handle->ipAddr, handle->udpPort,
2577 stats, &handle->supportedStats);
2579 tst = ADMCLIENTRXDEBUGTIMEOUT;
2580 goto fail_util_RXDebugRxStats;
2585 fail_util_RXDebugRxStats:
2594 * The iterator for listing RXDebug connections
2597 typedef struct rxdebug_conn_item {
2598 struct rx_debugConn conn;
2599 afs_uint32 supportedValues;
2600 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2602 typedef struct rxdebug_conn_get {
2604 rxdebugHandle_p handle;
2606 rxdebug_conn_item_t items[CACHED_ITEMS];
2607 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2610 RXDebugConnsFromServer(void *rpc_specific, int slot, int *last_item,
2611 int *last_item_contains_data, afs_status_p st)
2615 afs_status_t tst = 0;
2616 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2619 * Get the next entry the list of connections
2622 rx_GetServerConnections(t->handle->sock, t->handle->ipAddr,
2623 t->handle->udpPort, &t->index, t->allconns,
2624 t->handle->supportedStats,
2625 &t->items[slot].conn,
2626 &t->items[slot].supportedValues);
2628 tst = ADMCLIENTRXDEBUGTIMEOUT;
2629 goto fail_ListCellsRPC;
2633 * See if we've processed all the entries
2635 if (t->items[slot].conn.cid == 0xffffffff) {
2637 *last_item_contains_data = 0;
2650 RXDebugConnsFromCache(void *rpc_specific, int slot, void *dest,
2654 afs_status_t tst = 0;
2655 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2657 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_conn_item_t));
2667 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2672 * IN handle - an rxdebug handle for the process to be queried
2674 * IN allcons - non-zero to list all connections. If zero, only
2675 * "interesting" connections will be listed.
2677 * OUT iterationIdP - an iteration id that can be passed to
2678 * util_RXDebugConnectionsNext.
2682 * No locks are obtained or released by this function
2686 * Returns != 0 upon successful completion.
2691 util_RXDebugConnectionsBegin(rxdebugHandle_p handle, int allconns,
2692 void **iterationIdP, afs_status_p st)
2696 afs_uint32 tsupported;
2697 afs_status_t tst = 0;
2698 afs_admin_iterator_p iter;
2699 rxdebug_conn_get_p t;
2701 if (handle == NULL) {
2702 tst = ADMRXDEBUGHANDLENULL;
2703 goto fail_util_RXDebugConnectionsBegin;
2706 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2709 goto fail_util_RXDebugConnectionsBegin;
2712 if (handle->firstFlag) {
2713 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2716 goto fail_util_RXDebugConnectionsBegin;
2720 if (allconns && !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2721 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2722 goto fail_util_RXDebugConnectionsBegin;
2725 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2729 goto fail_util_RXDebugConnectionsBegin;
2732 t->allconns = allconns;
2736 (iter, (void *)t, RXDebugConnsFromServer, RXDebugConnsFromCache, NULL,
2738 goto fail_util_RXDebugConnectionsBegin;
2740 *iterationIdP = (void *)iter;
2743 fail_util_RXDebugConnectionsBegin:
2753 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2758 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2760 * OUT conn - Rxdebug information for the next connection.
2762 * OUT supportedValues - Bit mask of supported rxdebug values.
2766 * No locks are obtained or released by this function
2770 * Returns != 0 upon successful completion.
2775 util_RXDebugConnectionsNext(const void *iterationId,
2776 struct rx_debugConn *conn,
2777 afs_uint32 * supportedValues, afs_status_p st)
2780 afs_status_t tst = 0;
2781 rxdebug_conn_item_t item;
2782 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2784 if (iterationId == NULL) {
2785 tst = ADMITERATIONIDPNULL;
2786 goto fail_util_RXDebugConnectionsNext;
2790 tst = ADMRXDEBUGHANDLENULL;
2791 goto fail_util_RXDebugConnectionsNext;
2794 if (supportedValues == NULL) {
2795 tst = ADMRXDEBUGHANDLENULL;
2796 goto fail_util_RXDebugConnectionsNext;
2799 rc = IteratorNext(iter, (void *)&item, &tst);
2801 goto fail_util_RXDebugConnectionsNext;
2805 *supportedValues = item.supportedValues;
2807 fail_util_RXDebugConnectionsNext:
2817 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2821 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2825 * No locks are obtained or released by this function
2829 * Returns != 0 upon successful completion.
2834 util_RXDebugConnectionsDone(const void *iterationId, afs_status_p st)
2837 afs_status_t tst = 0;
2838 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2841 * Validate parameters
2845 tst = ADMITERATORNULL;
2846 goto fail_util_RXDebugConnectionsDone;
2849 rc = IteratorDone(iter, &tst);
2851 fail_util_RXDebugConnectionsDone:
2861 * The iterator for listing RXDebug peer
2864 typedef struct rxdebug_peer_item {
2865 struct rx_debugPeer peer;
2866 afs_uint32 supportedValues;
2867 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2869 typedef struct rxdebug_peer_get {
2870 rxdebugHandle_p handle;
2872 rxdebug_peer_item_t items[CACHED_ITEMS];
2873 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2876 RXDebugPeersFromServer(void *rpc_specific, int slot, int *last_item,
2877 int *last_item_contains_data, afs_status_p st)
2881 afs_status_t tst = 0;
2882 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2885 * Get the next entry the list of peers
2888 rx_GetServerPeers(t->handle->sock, t->handle->ipAddr,
2889 t->handle->udpPort, &t->index,
2890 t->handle->supportedStats, &t->items[slot].peer,
2891 &t->items[slot].supportedValues);
2893 tst = ADMCLIENTRXDEBUGTIMEOUT;
2894 goto fail_ListCellsRPC;
2898 * See if we've processed all the entries
2900 if (t->items[slot].peer.host == 0xffffffff) {
2902 *last_item_contains_data = 0;
2915 RXDebugPeersFromCache(void *rpc_specific, int slot, void *dest,
2919 afs_status_t tst = 0;
2920 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2922 memcpy(dest, (const void *)&t->items[slot], sizeof(rxdebug_peer_item_t));
2933 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
2938 * IN handle - an rxdebug handle for the process to be queried
2940 * OUT iterationIdP - an iteration id that can be passed to
2941 * util_RXDebugPeersNext.
2945 * No locks are obtained or released by this function
2949 * Returns != 0 upon successful completion.
2954 util_RXDebugPeersBegin(rxdebugHandle_p handle, void **iterationIdP,
2959 afs_uint32 tsupported;
2960 afs_status_t tst = 0;
2961 afs_admin_iterator_p iter;
2962 rxdebug_peer_get_p t;
2964 if (handle == NULL) {
2965 tst = ADMRXDEBUGHANDLENULL;
2966 goto fail_util_RXDebugPeersBegin;
2969 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2972 goto fail_util_RXDebugPeersBegin;
2975 if (handle->firstFlag) {
2976 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2979 goto fail_util_RXDebugPeersBegin;
2983 if (!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
2984 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2985 goto fail_util_RXDebugPeersBegin;
2988 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
2992 goto fail_util_RXDebugPeersBegin;
2998 (iter, (void *)t, RXDebugPeersFromServer, RXDebugPeersFromCache, NULL,
3000 goto fail_util_RXDebugPeersBegin;
3002 *iterationIdP = (void *)iter;
3005 fail_util_RXDebugPeersBegin:
3014 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3018 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3020 * OUT peer - Rxdebug information for the next peer.
3022 * OUT supportedValues - Bit mask of supported rxdebug values.
3026 * No locks are obtained or released by this function
3030 * Returns != 0 upon successful completion.
3034 util_RXDebugPeersNext(const void *iterationId, struct rx_debugPeer *peer,
3035 afs_uint32 * supportedValues, afs_status_p st)
3038 afs_status_t tst = 0;
3039 rxdebug_peer_item_t item;
3040 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3042 if (iterationId == NULL) {
3043 tst = ADMITERATIONIDPNULL;
3044 goto fail_util_RXDebugPeersNext;
3048 tst = ADMRXDEBUGHANDLENULL;
3049 goto fail_util_RXDebugPeersNext;
3052 if (supportedValues == NULL) {
3053 tst = ADMRXDEBUGHANDLENULL;
3054 goto fail_util_RXDebugPeersNext;
3057 rc = IteratorNext(iter, (void *)&item, &tst);
3059 goto fail_util_RXDebugPeersNext;
3063 *supportedValues = item.supportedValues;
3065 fail_util_RXDebugPeersNext:
3074 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3078 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3082 * No locks are obtained or released by this function
3086 * Returns != 0 upon successful completion.
3091 util_RXDebugPeersDone(const void *iterationId, afs_status_p st)
3094 afs_status_t tst = 0;
3095 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3098 * Validate parameters
3102 tst = ADMITERATORNULL;
3103 goto fail_util_RXDebugPeersDone;
3106 rc = IteratorDone(iter, &tst);
3108 fail_util_RXDebugPeersDone: