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 <afs/param.h>
11 #include <afsconfig.h>
16 #include <afs/afs_Admin.h>
19 #include <afs/afs_Admin.h>
20 #include "afs_AdminInternal.h"
21 #include "afs_utilAdmin.h"
22 #include <afs/pthread_glock.h>
23 #include <afs/cellconfig.h>
24 #include <afs/dirpath.h>
25 #include <afs/com_err.h>
26 #include <afs/kautils.h>
28 #include <afs/vlserver.h>
29 #include <afs/pterror.h>
30 #include <afs/bnode.h>
31 #include <afs/volser.h>
32 #include <afs/afsint.h>
34 #include <rx/rxstat.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netinet/in.h>
41 #include <arpa/inet.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;
60 static void init_once(void) {
62 initialize_ka_error_table();
63 initialize_rxk_error_table();
64 initialize_ktc_error_table();
65 initialize_acfg_error_table();
66 initialize_cmd_error_table();
67 initialize_vl_error_table();
68 initialize_pt_error_table();
69 initialize_bz_error_table();
70 initialize_u_error_table();
71 initialize_ab_error_table();
72 initialize_af_error_table();
73 initialize_al_error_table();
74 initialize_ac_error_table();
75 initialize_ak_error_table();
76 initialize_am_error_table();
77 initialize_ap_error_table();
78 initialize_au_error_table();
79 initialize_av_error_table();
80 initialize_vols_error_table();
84 int ADMINAPI util_AdminErrorCodeTranslate(
85 afs_status_t errorCode,
87 const char **errorTextP,
94 if (errorTextP == NULL) {
95 tst = ADMUTILERRORTEXTPNULL;
96 goto fail_util_AdminErrorCodeTranslate;
100 * Translate the error
103 if ( !error_init_done )
104 pthread_once(&error_init_once, init_once);
105 code = (afs_int32) errorCode;
106 *errorTextP = error_message(code);
109 fail_util_AdminErrorCodeTranslate:
118 * The iterator functions and data for the database server retrieval functions.
121 typedef struct database_server_get {
124 struct afsconf_dir *conf;
125 struct afsconf_cell cell;
126 util_databaseServerEntry_t server[CACHED_ITEMS];
127 } database_server_get_t, *database_server_get_p;
129 static int GetDatabaseServerRPC(
133 int *last_item_contains_data,
137 afs_status_t tst = 0;
138 database_server_get_p serv = (database_server_get_p) rpc_specific;
140 serv->server[slot].serverAddress = ntohl(serv->cell.hostAddr[serv->index].sin_addr.s_addr);
141 strcpy(serv->server[slot].serverName, serv->cell.hostName[serv->index]);
145 * See if we've processed all the entries
148 if (serv->index == serv->total) {
150 *last_item_contains_data = 1;
160 static int GetDatabaseServerFromCache(
167 afs_status_t tst = 0;
168 database_server_get_p serv = (database_server_get_p) rpc_specific;
170 memcpy(dest, (const void *) &serv->server[slot],
171 sizeof(util_databaseServerEntry_t));
180 static int DestroyDatabaseServer(
185 afs_status_t tst = 0;
186 database_server_get_p serv = (database_server_get_p) rpc_specific;
188 afsconf_Close(serv->conf);
198 * util_DatabaseServerGetBegin - begin iterating over the database
199 * server machines in a cell.
203 * IN cellName - the cell where database servers reside.
205 * OUT iterationIdP - upon successful completion contains an iterator that
206 * can be passed to util_DatabaseServerGetNext.
210 * No locks are obtained or released by this function
218 * Returns != 0 upon successful completion.
221 int ADMINAPI util_DatabaseServerGetBegin(
222 const char *cellName,
227 afs_status_t tst = 0;
228 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
229 database_server_get_p serv = (database_server_get_p) calloc(1, sizeof(database_server_get_t));
230 char copyCell[MAXCELLCHARS];
236 if ((cellName == NULL) || (*cellName == 0)) {
237 tst = ADMUTILCELLNAMENULL;
238 goto fail_util_DatabaseServerGetBegin;
241 if (iterationIdP == NULL) {
242 goto fail_util_DatabaseServerGetBegin;
245 if ((iter == NULL) || (serv == NULL)) {
247 goto fail_util_DatabaseServerGetBegin;
251 * Fill in the serv structure
254 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
255 if (serv->conf == NULL) {
256 tst = ADMUTILCANTOPENCELLSERVDB;
257 goto fail_util_DatabaseServerGetBegin;
261 * We must copy the cellname because afsconf_GetCellInfo
262 * actually writes over the cell name it is passed.
264 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
265 tst = afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
268 goto fail_util_DatabaseServerGetBegin;
271 serv->total = serv->cell.numServers;
272 if (IteratorInit(iter, (void *) serv, GetDatabaseServerRPC,
273 GetDatabaseServerFromCache, NULL, DestroyDatabaseServer,
275 *iterationIdP = (void *) iter;
277 goto fail_util_DatabaseServerGetBegin;
281 fail_util_DatabaseServerGetBegin:
299 * util_DatabaseServerGetNext - get the next server address.
303 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
305 * OUT serverAddressP - upon successful completion contains the next
306 * server address in the cell.
310 * This function locks the iterator for the duration of its processing.
318 * Returns != 0 upon successful completion.
322 int ADMINAPI util_DatabaseServerGetNext(
323 const void *iterationId,
324 util_databaseServerEntry_p serverP,
328 afs_status_t tst = 0;
329 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
332 tst = ADMITERATORNULL;
333 goto fail_util_DatabaseServerGetNext;
336 if (serverP == NULL) {
337 tst = ADMUTILSERVERADDRESSPNULL;
338 goto fail_util_DatabaseServerGetNext;
341 rc = IteratorNext(iter, (void *) serverP, &tst);
343 fail_util_DatabaseServerGetNext:
352 * util_DatabaseServerGetDone - stop using a database iterator.
356 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
360 * This function locks the iterator for the duration of its processing.
361 * And then destroys it before returning.
369 * Returns != 0 upon successful completion.
372 int ADMINAPI util_DatabaseServerGetDone(
373 const void *iterationId,
377 afs_status_t tst = 0;
378 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
381 * Validate parameters
385 tst = ADMITERATORNULL;
386 goto fail_util_DatabaseServerGetDone;
389 rc = IteratorDone(iter, &tst);
391 fail_util_DatabaseServerGetDone:
400 * GetServerAddressFromName - translate a character string server name
401 * to an integer representation of an IP address.
405 * IN serverName - the character string server name in either foo.com
406 * format, or 123.12.1.1 format.
408 * OUT serverAddress - an integer that is filled with the correct address
409 * in host byte order upon successful completion.
413 * No locks are obtained or released by this function
417 * On many platforms, gethostbyname is not thread safe. Since we are
418 * only working under NT for now I'll use it directly. In future UNIX
419 * ports, a wrapper function should be written to call the correct function
420 * on the particular platform.
424 * Returns != 0 upon successful completion.
427 int ADMINAPI util_AdminServerAddressGetFromName(
428 const char *serverName,
433 afs_status_t tst = 0;
434 struct hostent *server;
435 int part1, part2, part3, part4;
438 if ((serverName == NULL) || (*serverName == 0)) {
439 tst = ADMUTILSERVERNAMENULL;
440 goto fail_util_AdminServerAddressGetFromName;
443 if (serverAddress == NULL) {
444 tst = ADMUTILSERVERADDRESSNULL;
445 goto fail_util_AdminServerAddressGetFromName;
448 num_converted = sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
449 if (num_converted == 4) {
450 *serverAddress = (part1<<24) | (part2<<16) | (part3<<8) | part4;
453 server = gethostbyname(serverName);
454 if (server != NULL) {
455 memcpy((void *) serverAddress, (const void *) server->h_addr, sizeof(serverAddress));
456 *serverAddress = ntohl(*serverAddress);
458 tst = ADMUTILCANTGETSERVERNAME;
460 goto fail_util_AdminServerAddressGetFromName;
466 fail_util_AdminServerAddressGetFromName:
476 * This file contains functions that can be used to create iterator
477 * functions within the api. I have attempted to make these functions
478 * generic so that they can be used across the admin components.
480 * The functions in this file are a generalized producer/consumer
481 * implementation. They manage access to a queue of data. The only
482 * assumption these functions make about this data is that it is
483 * stored in a queue which is implemented via an array. These functions
484 * know about the index into the array, but they know nothing about
485 * the contents of the array.
487 * The data specific functions you implement will have to create some
488 * data specific storage structure that will have an array
489 * of size CACHED_ITEMS data items. This structure will also need to
490 * store any necessary parameters/state variables you need to issue the
491 * rpc to retrieve the next item.
493 * In order to use the generic functions, you must implement four functions
494 * for each type of data you wish to retrieve. The functions are:
496 * validate_specific_data_func - this function is handed a void pointer
497 * that points to the rpc specific data you've allocated. The function
498 * should examine the data for validity and return an appropriate error.
499 * This function is called every time the iterator is validated.
501 * destroy_specific_data_func - this function is handed a void pointer
502 * that points to the rpc specific data you've allocated. It should
503 * destroy any components of the specific data as required and then
504 * return. The void pointer is free'd by the generic functions.
506 * get_cached_data_func - this function is handed a void pointer
507 * that points to the rpc specific data you've allocated, an index
508 * into the cache of the item to be copied to the caller, and a void
509 * pointer where the cache item should be copied.
511 * make_rpc_func - this function is handed a void pointer that points
512 * to the rpc specific data you've allocated, an index into the cache
513 * of the item to be filled with the next retrieved item, and an int
514 * pointer that should be set to 1 if there are no more items to be
515 * retrieved. The assumption made by the generic functions is that
516 * the last_item status requires an individual rpc - the data isn't
517 * piggybacked on the last data item.
521 * IteratorDelete - delete an iterator.
525 * IN interator - the iterator to delete.
529 * No locks are held by this function.
533 * Returns != 0 upon successful completion.
536 static int IteratorDelete(
537 afs_admin_iterator_p iter,
541 afs_status_t tst = 0;
543 if(pthread_mutex_destroy(&iter->mutex)) {
544 tst = ADMMUTEXDESTROY;
545 goto fail_IteratorDelete;
547 if(pthread_cond_destroy(&iter->add_item)) {
548 tst = ADMCONDDESTROY;
549 goto fail_IteratorDelete;
551 if(pthread_cond_destroy(&iter->remove_item)) {
552 tst = ADMCONDDESTROY;
553 goto fail_IteratorDelete;
556 if (iter->destroy_specific != NULL) {
557 iter->destroy_specific(iter->rpc_specific, &tst);
559 free(iter->rpc_specific);
572 * DataGet - the background thread that is spawned for every
573 * IteratorBegin call that is successful. This thread tries
574 * to fetch the data from the server ahead of the
575 * IteratorNext calls.
579 * IN arg - the address of the iterator structure to be used for this
584 * The iterator mutex is used by this function to protect elements
585 * of the iterator structure.
589 * Returns != 0 upon successful completion.
592 static void *DataGet(void *arg)
594 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
596 afs_status_t tst = 0;
597 int mutex_locked = 0;
599 int last_item_contains_data = 0;
601 if (pthread_mutex_lock(&iter->mutex)) {
602 iter->st = ADMMUTEXLOCK;
611 * Check to see if there's room for this datum. If not, wait
612 * on the consumer to free up another slot.
615 while (iter->cache_slots_used == CACHED_ITEMS) {
616 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
617 iter->st = ADMCONDWAIT;
623 * Check to see if someone called Done and terminated the request.
624 * We could have gone to sleep above when the buffer was full and
625 * instead of being awoken because another slot is open, we were
626 * awoken because the request was terminated.
629 if (iter->request_terminated) {
633 if (pthread_mutex_unlock(&iter->mutex)) {
634 iter->st = ADMMUTEXUNLOCK;
641 * Make an rpc without holding the iter mutex
642 * We reference an item in the principal cache here without
643 * holding the mutex. This is safe because:
644 * 1. The iter structure is ref counted and won't be deleted
645 * from underneath us.
646 * 2. cache_queue_tail is always one item ahead of the consumer
647 * thread so we are the only thread accessing this member.
650 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail,
651 &last_item, &last_item_contains_data, &tst);
653 if (pthread_mutex_lock(&iter->mutex)) {
654 iter->st = ADMMUTEXLOCK;
661 * Check to see if someone called Done and terminated the request
664 if (iter->request_terminated) {
669 * Check the rc of the rpc, and see if there are no more items
679 * Check to see if this is the last item produced by the rpc.
680 * If it isn't, add the item to the cache and proceed.
681 * If it is, check to see if the last item contains valid data.
682 * If it contains valid data, we need to add it to our cache.
683 * If it doesn't, we mark the iterator as complete.
686 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
687 iter->cache_queue_tail = (iter->cache_queue_tail + 1) %
689 iter->cache_slots_used++;
692 iter->st = ADMITERATORDONE;
693 iter->done_iterating = 1;
695 * There's a small chance that the consumer emptied the
696 * cache queue while we were making the last rpc and has
697 * since gone to sleep waiting for more data. In this case
698 * there will never be more data so we signal him here.
700 pthread_cond_signal(&iter->add_item);
706 * If the cache was empty and we just added another item, signal
710 if (iter->cache_slots_used == 1) {
711 if (pthread_cond_signal(&iter->add_item)) {
712 iter->st = ADMCONDSIGNAL;
722 * If we are exiting with an error, signal the consumer in the event
723 * they were waiting for us to produce more data
727 pthread_cond_signal(&iter->add_item);
731 pthread_mutex_unlock(&iter->mutex);
738 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
742 * IN interator - the interator to be verified.
746 * We assume the iter->mutex lock is already held.
750 * Returns != 0 upon successful completion.
753 static int IsValidIterator(
754 const afs_admin_iterator_p iterator,
758 afs_status_t tst = 0;
761 * Validate input parameters
764 if (iterator == NULL) {
765 tst = ADMITERATORNULL;
766 goto fail_IsValidIterator;
769 if ((iterator->begin_magic != BEGIN_MAGIC) ||
770 (iterator->end_magic != END_MAGIC)) {
771 tst = ADMITERATORBADMAGICNULL;
772 goto fail_IsValidIterator;
775 if (iterator->is_valid == 0) {
776 tst = ADMITERATORINVALID;
777 goto fail_IsValidIterator;
781 * Call the iterator specific validation function
784 if (iterator->validate_specific != NULL) {
785 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
786 goto fail_IsValidIterator;
791 fail_IsValidIterator:
800 * IteratorNext - return the next datum in an interator.
804 * IN interator - the iterator containing the data.
806 * IN dest - the address where the data should be copied.
810 * Lock the iterator upon entry, and hold it during the duration of this
815 * Returns != 0 upon successful completion.
819 afs_admin_iterator_p iter,
824 afs_status_t tst = 0;
828 * We have to lock the iterator before we validate it
831 if (pthread_mutex_lock(&iter->mutex)) {
833 goto fail_IteratorNext;
838 if (!IsValidIterator(iter, &tst)) {
839 goto fail_IteratorNext;
842 if (iter->request_terminated == 1) {
843 tst = ADMITERATORTERMINATED;
844 goto fail_IteratorNext;
847 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
849 goto fail_IteratorNext;
853 * Check to see if there are any queue'd items. If not, wait here
854 * until signalled by the producer.
857 while (iter->cache_slots_used == 0) {
860 * Maybe the producer experienced an rpc failure.
863 if ((!iter->done_iterating) && (iter->st != 0)) {
865 goto fail_IteratorNext;
869 * Maybe there are no queue'd items because the producer is done
872 if (iter->done_iterating) {
874 goto fail_IteratorNext;
877 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
879 goto fail_IteratorNext;
884 * Copy the next cached item and update the cached item count
885 * and the index into the cache array
888 if (!iter->get_cached_data(iter->rpc_specific,
889 iter->cache_queue_head,
892 goto fail_IteratorNext;
895 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
896 iter->cache_slots_used--;
899 * If the cache was full before we removed the item above, the
900 * producer may have been waiting for us to remove an item.
901 * Signal the producer letting him know that we've opened a slot
905 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
906 if (pthread_cond_signal(&iter->remove_item)) {
908 goto fail_IteratorNext;
916 if (locked_iter == 1) {
917 pthread_mutex_unlock(&iter->mutex);
927 * IteratorDone - mark the iterator done.
931 * IN interator - the iterator to mark done.
935 * Lock the iterator upon entry, and hold it during the duration of this
940 * Returns != 0 upon successful completion.
944 afs_admin_iterator_p iter,
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 afs_admin_iterator_p iter,
1033 make_rpc_func make_rpc,
1034 get_cached_data_func get_cached_data,
1035 validate_specific_data_func validate_specific_data,
1036 destroy_specific_data_func destroy_specific_data,
1040 afs_status_t tst = 0;
1041 int mutex_inited = 0;
1042 int add_item_cond_inited = 0;
1043 int remove_item_cond_inited = 0;
1046 tst = ADMITERATORNULL;
1047 goto fail_IteratorInit;
1050 if (rpc_specific == NULL) {
1051 tst = ADMITERATORRPCSPECIFICNULL;
1052 goto fail_IteratorInit;
1056 * Initialize the iterator structure
1058 iter->begin_magic = BEGIN_MAGIC;
1059 iter->end_magic = END_MAGIC;
1061 iter->cache_slots_used = 0;
1062 iter->done_iterating = 0;
1063 iter->request_terminated = 0;
1064 iter->st = AFS_STATUS_OK;
1065 iter->cache_queue_head = 0;
1066 iter->cache_queue_tail = 0;
1067 iter->cache_slots_used = 0;
1068 iter->rpc_specific = rpc_specific;
1069 iter->make_rpc = make_rpc;
1070 iter->get_cached_data = get_cached_data;
1071 iter->validate_specific = validate_specific_data;
1072 iter->destroy_specific = destroy_specific_data;
1074 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *) 0)) {
1076 goto fail_IteratorInit;
1081 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *) 0)) {
1083 goto fail_IteratorInit;
1085 add_item_cond_inited = 1;
1088 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *) 0)) {
1090 goto fail_IteratorInit;
1092 remove_item_cond_inited = 1;
1096 * Create a worker thread that will begin to query the server
1097 * and cache responses.
1100 if (iter->make_rpc != NULL) {
1101 pthread_attr_t tattr;
1103 if (pthread_attr_init(&tattr)) {
1104 tst = ADMTHREADATTRINIT;
1105 goto fail_IteratorInit;
1108 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1109 tst = ADMTHREADATTRSETDETACHSTATE;
1110 goto fail_IteratorInit;
1113 if (pthread_create(&iter->bg_worker, &tattr,
1114 DataGet, (void *) iter)) {
1115 tst = ADMTHREADCREATE;
1116 goto fail_IteratorInit;
1125 pthread_mutex_destroy(&iter->mutex);
1127 if (remove_item_cond_inited) {
1128 pthread_cond_destroy(&iter->remove_item);
1130 if (add_item_cond_inited) {
1131 pthread_cond_destroy(&iter->add_item);
1141 int ADMINAPI CellHandleIsValid(
1142 const void *cellHandle,
1146 afs_status_t tst = 0;
1147 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1150 * Validate input parameters
1153 if (c_handle == NULL) {
1154 tst = ADMCLIENTCELLHANDLENULL;
1155 goto fail_CellHandleIsValid;
1158 if ((c_handle->begin_magic != BEGIN_MAGIC) ||
1159 (c_handle->end_magic != END_MAGIC)) {
1160 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1161 goto fail_CellHandleIsValid;
1164 if (c_handle->is_valid == 0) {
1165 tst = ADMCLIENTCELLINVALID;
1166 goto fail_CellHandleIsValid;
1170 fail_CellHandleIsValid:
1179 * The iterator functions and data for the rpc statistic retrieval functions
1182 typedef struct rpc_stat_get {
1183 afs_uint32 clock_sec;
1184 afs_uint32 clock_usec;
1187 afs_uint32 clientVersion;
1188 afs_uint32 serverVersion;
1189 struct rpcStats stat_list;
1190 afs_RPCStats_t stats[CACHED_ITEMS];
1191 afs_uint32 *pointer;
1192 } rpc_stat_get_t, *rpc_stat_get_p;
1194 static void UnmarshallRPCStats(
1195 afs_uint32 serverVersion,
1200 unsigned int hi, lo;
1203 * Server must always match lower versions. We are version 1.
1206 s->stats_v1.remote_peer = *(ptr++);
1207 s->stats_v1.remote_port = *(ptr++);
1208 s->stats_v1.remote_is_server = *(ptr++);
1209 s->stats_v1.interfaceId = *(ptr++);
1210 s->stats_v1.func_total = *(ptr++);
1211 s->stats_v1.func_index = *(ptr++);
1214 hset64(s->stats_v1.invocations, hi, lo);
1217 hset64(s->stats_v1.bytes_sent, hi, lo);
1220 hset64(s->stats_v1.bytes_rcvd, hi, lo);
1221 s->stats_v1.queue_time_sum.sec = *(ptr++);
1222 s->stats_v1.queue_time_sum.usec = *(ptr++);
1223 s->stats_v1.queue_time_sum_sqr.sec = *(ptr++);
1224 s->stats_v1.queue_time_sum_sqr.usec = *(ptr++);
1225 s->stats_v1.queue_time_min.sec = *(ptr++);
1226 s->stats_v1.queue_time_min.usec = *(ptr++);
1227 s->stats_v1.queue_time_max.sec = *(ptr++);
1228 s->stats_v1.queue_time_max.usec = *(ptr++);
1229 s->stats_v1.execution_time_sum.sec = *(ptr++);
1230 s->stats_v1.execution_time_sum.usec = *(ptr++);
1231 s->stats_v1.execution_time_sum_sqr.sec = *(ptr++);
1232 s->stats_v1.execution_time_sum_sqr.usec = *(ptr++);
1233 s->stats_v1.execution_time_min.sec = *(ptr++);
1234 s->stats_v1.execution_time_min.usec = *(ptr++);
1235 s->stats_v1.execution_time_max.sec = *(ptr++);
1236 s->stats_v1.execution_time_max.usec = *(ptr++);
1240 static int GetRPCStatsRPC(
1244 int *last_item_contains_data,
1248 afs_status_t tst = 0;
1249 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1251 t->stats[slot].clientVersion = t->clientVersion;
1252 t->stats[slot].serverVersion = t->serverVersion;
1253 t->stats[slot].statCount = t->total;
1256 * If the server stat version is greater than or equal to my version
1257 * number, it is required to return the values in the client's current
1261 UnmarshallRPCStats(t->serverVersion,
1268 * See if we've processed all the entries
1271 if (t->index == t->total) {
1273 *last_item_contains_data = 1;
1283 static int GetRPCStatsFromCache(
1290 afs_status_t tst = 0;
1291 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1293 memcpy(dest, (const void *) &stat->stats[slot],
1294 sizeof(afs_RPCStats_t));
1303 static int DestroyRPCStats(
1308 afs_status_t tst = 0;
1309 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1311 if (stat->stat_list.rpcStats_val != NULL) {
1312 free(stat->stat_list.rpcStats_val);
1323 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1327 * IN conn - an rx connection to the process to be queried
1329 * IN rpc - the function to call to make the actual rpc
1331 * OUT iterationIdP - an iteration id that can be passed to
1332 * util_RPCStatsGetNext to get the next rpc stat
1336 * No locks are obtained or released by this function
1340 * Returns != 0 upon successful completion.
1344 int ADMINAPI util_RPCStatsGetBegin(
1345 struct rx_connection *conn,
1347 void **iterationIdP,
1351 afs_status_t tst = 0;
1352 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1353 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1356 tst = ADMRXCONNNULL;
1357 goto fail_util_RPCStatsGetBegin;
1361 tst = ADMRPCPTRNULL;
1362 goto fail_util_RPCStatsGetBegin;
1365 if (iterationIdP == NULL) {
1366 tst = ADMITERATIONIDPNULL;
1367 goto fail_util_RPCStatsGetBegin;
1370 if ((iter == NULL) || (stat == NULL)) {
1372 goto fail_util_RPCStatsGetBegin;
1375 stat->stat_list.rpcStats_len = 0;
1376 stat->stat_list.rpcStats_val = 0;
1378 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1381 stat->clientVersion,
1382 &stat->serverVersion,
1389 goto fail_util_RPCStatsGetBegin;
1393 * If there are no statistics, just mark the iterator done and
1397 if (stat->stat_list.rpcStats_len == 0) {
1398 stat->pointer = NULL;
1399 if (!IteratorInit(iter,
1406 goto fail_util_RPCStatsGetBegin;
1408 iter->done_iterating = 1;
1409 iter->st = ADMITERATORDONE;
1411 stat->pointer = stat->stat_list.rpcStats_val;
1412 if (!IteratorInit(iter,
1415 GetRPCStatsFromCache,
1419 goto fail_util_RPCStatsGetBegin;
1422 *iterationIdP = (void *) iter;
1425 fail_util_RPCStatsGetBegin:
1443 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1447 * IN iterationId - an iterator previously returned by
1448 * util_RPCStatsGetBegin.
1450 * OUT stats - upon successful completion contains the next set of stats
1455 * No locks are obtained or released by this function
1459 * Returns != 0 upon successful completion.
1463 int ADMINAPI util_RPCStatsGetNext(
1464 const void *iterationId,
1465 afs_RPCStats_p stats,
1469 afs_status_t tst = 0;
1470 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1472 if (iterationId == NULL) {
1473 tst = ADMITERATIONIDPNULL;
1474 goto fail_util_RPCStatsGetNext;
1477 if (stats == NULL) {
1478 tst = ADMUTILRPCSTATSNULL;
1479 goto fail_util_RPCStatsGetNext;
1482 rc = IteratorNext(iter, (void *) stats, &tst);
1484 fail_util_RPCStatsGetNext:
1493 * util_RPCStatsGetDone - finish using a stats iterator
1497 * IN iterationId - an iterator previously returned by
1498 * util_RPCStatsGetBegin.
1502 * No locks are obtained or released by this function
1506 * Returns != 0 upon successful completion.
1510 int ADMINAPI util_RPCStatsGetDone(
1511 const void *iterationId,
1515 afs_status_t tst = 0;
1516 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1518 if (iterationId == NULL) {
1519 tst = ADMITERATIONIDPNULL;
1520 goto fail_util_RPCStatsGetDone;
1523 rc = IteratorDone(iter, &tst);
1525 fail_util_RPCStatsGetDone:
1534 * util_RPCStatsStateGet - get the current state of rpc stat collection
1538 * IN conn - an rx connection to the process to be queried
1540 * IN rpc - the function to call to make the actual rpc
1542 * OUT state - the rpc stat collection state.
1546 * No locks are obtained or released by this function
1550 * Returns != 0 upon successful completion.
1554 int ADMINAPI util_RPCStatsStateGet(
1555 struct rx_connection *conn,
1557 afs_RPCStatsState_p state,
1561 afs_status_t tst = 0;
1564 tst = ADMRXCONNNULL;
1565 goto fail_util_RPCStatsStateGet;
1569 tst = ADMRPCPTRNULL;
1570 goto fail_util_RPCStatsStateGet;
1573 if (state == NULL) {
1574 tst = ADMRPCSTATENULL;
1575 goto fail_util_RPCStatsStateGet;
1578 tst = (*rpc)(conn, state);
1584 fail_util_RPCStatsStateGet:
1593 * util_RPCStatsStateEnable - enable rpc stat collection
1598 * IN conn - an rx connection to the process to be modified
1600 * IN rpc - the function to call to make the actual rpc
1604 * No locks are obtained or released by this function
1608 * Returns != 0 upon successful completion.
1612 int ADMINAPI util_RPCStatsStateEnable(
1613 struct rx_connection *conn,
1618 afs_status_t tst = 0;
1621 tst = ADMRXCONNNULL;
1622 goto fail_util_RPCStatsStateEnable;
1626 tst = ADMRPCPTRNULL;
1627 goto fail_util_RPCStatsStateEnable;
1636 fail_util_RPCStatsStateEnable:
1645 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1650 * IN conn - an rx connection to the process to be modified
1652 * IN rpc - the function to call to make the actual rpc
1656 * No locks are obtained or released by this function
1660 * Returns != 0 upon successful completion.
1664 int ADMINAPI util_RPCStatsStateDisable(
1665 struct rx_connection *conn,
1670 afs_status_t tst = 0;
1673 tst = ADMRXCONNNULL;
1674 goto fail_util_RPCStatsStateDisable;
1678 tst = ADMRPCPTRNULL;
1679 goto fail_util_RPCStatsStateDisable;
1688 fail_util_RPCStatsStateDisable:
1697 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1698 * collection at a server
1702 * IN conn - an rx connection to the process to be modified
1704 * IN rpc - the function to call to make the actual rpc
1706 * IN flag - a flag containing the fields to be cleared
1711 * No locks are obtained or released by this function
1715 * Returns != 0 upon successful completion.
1719 int ADMINAPI util_RPCStatsClear(
1720 struct rx_connection *conn,
1722 afs_RPCStatsClearFlag_t flag,
1726 afs_status_t tst = 0;
1729 tst = ADMRXCONNNULL;
1730 goto fail_util_RPCStatsClear;
1734 tst = ADMRPCPTRNULL;
1735 goto fail_util_RPCStatsClear;
1738 tst = (*rpc)(conn, flag);
1744 fail_util_RPCStatsClear:
1753 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1757 * IN conn - an rx connection to the process to be modified
1759 * OUT version - the version of rpc stat collection at the remote process
1763 * No locks are obtained or released by this function
1767 * Returns != 0 upon successful completion.
1771 int ADMINAPI util_RPCStatsVersionGet(
1772 struct rx_connection *conn,
1773 afs_RPCStatsVersion_p version,
1777 afs_status_t tst = 0;
1780 tst = ADMRXCONNNULL;
1781 goto fail_util_RPCStatsVersionGet;
1784 if (version == NULL) {
1785 tst = ADMRPCVERSIONNULL;
1786 goto fail_util_RPCStatsVersionGet;
1789 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1795 fail_util_RPCStatsVersionGet:
1804 * The iterator for listing CM server preferences
1807 typedef struct cm_srvr_pref_get {
1808 struct rx_connection *conn;
1810 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1811 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1813 static int GetServerPrefsRPC(
1817 int *last_item_contains_data,
1821 afs_status_t tst = 0;
1822 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1825 * Get the next entry in the list of server preferences.
1827 tst = RXAFSCB_GetServerPrefs(t->conn, t->index,
1828 &t->srvrPrefs[slot].ipAddr,
1829 &t->srvrPrefs[slot].ipRank);
1831 goto fail_GetServerPrefsRPC;
1835 * See if we've processed all the entries
1837 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1839 *last_item_contains_data = 0;
1845 fail_GetServerPrefsRPC:
1853 static int GetServerPrefsFromCache(
1860 afs_status_t tst = 0;
1861 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1863 memcpy(dest, (const void *) &prefs->srvrPrefs[slot],
1864 sizeof(afs_CMServerPref_t));
1874 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1878 * IN conn - an rx connection to the process to be queried
1880 * OUT iterationIdP - an iteration id that can be passed to
1881 * util_CMGetServerPrefsNext to get the next server preference
1885 * No locks are obtained or released by this function
1889 * Returns != 0 upon successful completion.
1893 int ADMINAPI util_CMGetServerPrefsBegin(
1894 struct rx_connection *conn,
1895 void **iterationIdP,
1899 afs_status_t tst = 0;
1900 afs_admin_iterator_p iter;
1901 cm_srvr_pref_get_p pref;
1904 tst = ADMRXCONNNULL;
1905 goto fail_util_CMGetServerPrefsBegin;
1908 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1911 goto fail_util_CMGetServerPrefsBegin;
1914 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1918 goto fail_util_CMGetServerPrefsBegin;
1923 if (!IteratorInit(iter, (void *) pref, GetServerPrefsRPC,
1924 GetServerPrefsFromCache, NULL, NULL, &tst)) {
1927 goto fail_util_CMGetServerPrefsBegin;
1929 *iterationIdP = (void *) iter;
1932 fail_util_CMGetServerPrefsBegin:
1941 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1946 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1948 * OUT prefs - Next entry in cache manager server preferences.
1952 * No locks are obtained or released by this function
1956 * Returns != 0 upon successful completion.
1960 int ADMINAPI util_CMGetServerPrefsNext(
1961 const void *iterationId,
1962 afs_CMServerPref_p prefs,
1966 afs_status_t tst = 0;
1967 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1969 if (iterationId == NULL) {
1970 tst = ADMITERATIONIDPNULL;
1971 goto fail_util_CMGetServerPrefsNext;
1974 rc = IteratorNext(iter, (void *) prefs, &tst);
1976 fail_util_CMGetServerPrefsNext:
1985 * util_CMGetServerPrefsDone - Finish listing cache manager server
1990 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1994 * No locks are obtained or released by this function
1998 * Returns != 0 upon successful completion.
2002 int ADMINAPI util_CMGetServerPrefsDone(
2003 const void *iterationId,
2007 afs_status_t tst = 0;
2008 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2010 if (iterationId == NULL) {
2011 tst = ADMITERATIONIDPNULL;
2012 goto fail_util_CMGetServerPrefsDone;
2015 rc = IteratorDone(iter, &tst);
2018 fail_util_CMGetServerPrefsDone:
2027 * The iterator for listing CM CellServDB
2030 typedef struct cm_list_cell_get {
2031 struct rx_connection *conn;
2033 afs_CMListCell_t cell[CACHED_ITEMS];
2034 } cm_list_cell_get_t, *cm_list_cell_get_p;
2036 static int ListCellsRPC(
2040 int *last_item_contains_data,
2044 afs_status_t tst = 0;
2045 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2049 * Get the next entry in the CellServDB.
2051 name = t->cell[slot].cellname;
2052 tst = RXAFSCB_GetCellServDB(t->conn, t->index, &name,
2053 t->cell[slot].serverAddr);
2055 goto fail_ListCellsRPC;
2057 strcpy(t->cell[slot].cellname, name);
2060 * See if we've processed all the entries
2062 if (strlen(t->cell[slot].cellname) == 0) {
2064 *last_item_contains_data = 0;
2078 static int ListCellsFromCache(
2085 afs_status_t tst = 0;
2086 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2088 memcpy(dest, (const void *) &cell->cell[slot],
2089 sizeof(afs_CMListCell_t));
2099 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2103 * IN conn - an rx connection to the process to be queried
2105 * OUT iterationIdP - an iteration id that can be passed to
2106 * util_CMListCellsNext to get the next cell
2110 * No locks are obtained or released by this function
2114 * Returns != 0 upon successful completion.
2118 int ADMINAPI util_CMListCellsBegin(
2119 struct rx_connection *conn,
2120 void **iterationIdP,
2124 afs_status_t tst = 0;
2125 afs_admin_iterator_p iter;
2126 cm_list_cell_get_p cell;
2129 tst = ADMRXCONNNULL;
2130 goto fail_util_CMListCellsBegin;
2133 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2136 goto fail_util_CMListCellsBegin;
2139 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2143 goto fail_util_CMListCellsBegin;
2148 if (!IteratorInit(iter, (void *) cell, ListCellsRPC,
2149 ListCellsFromCache, NULL, NULL, &tst)) {
2152 goto fail_util_CMListCellsBegin;
2154 *iterationIdP = (void *) iter;
2157 fail_util_CMListCellsBegin:
2166 * util_CMListCellsNext - Get next entry in cache manager cells
2170 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2172 * OUT cell - Next entry in cache manager cells.
2176 * No locks are obtained or released by this function
2180 * Returns != 0 upon successful completion.
2184 int ADMINAPI util_CMListCellsNext(
2185 const void *iterationId,
2186 afs_CMListCell_p cell,
2190 afs_status_t tst = 0;
2191 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2193 if (iterationId == NULL) {
2194 tst = ADMITERATIONIDPNULL;
2195 goto fail_util_CMListCellsNext;
2198 rc = IteratorNext(iter, (void *) cell, &tst);
2200 fail_util_CMListCellsNext:
2209 * util_CMListCellsDone - Finish listing cache manager cells
2213 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2217 * No locks are obtained or released by this function
2221 * Returns != 0 upon successful completion.
2225 int ADMINAPI util_CMListCellsDone(
2226 const void *iterationId,
2230 afs_status_t tst = 0;
2231 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2233 if (iterationId == NULL) {
2234 tst = ADMITERATIONIDPNULL;
2235 goto fail_util_CMListCellsDone;
2238 rc = IteratorDone(iter, &tst);
2241 fail_util_CMListCellsDone:
2250 * util_CMLocalCell - Get the name of the cache manager's local cell.
2254 * IN conn - an rx connection to the process to be queried
2256 * OUT cellName - the name of the cache manager's local cell.
2260 * No locks are obtained or released by this function
2264 * Returns != 0 upon successful completion.
2268 int ADMINAPI util_CMLocalCell(
2269 struct rx_connection *conn,
2270 afs_CMCellName_p cellName,
2274 afs_status_t tst = 0;
2275 afs_CMCellName_p name;
2278 tst = ADMRXCONNNULL;
2279 goto fail_util_CMLocalCell;
2282 if (cellName == NULL) {
2283 tst = ADMCLIENTCMCELLNAMENULL;
2284 goto fail_util_CMLocalCell;
2288 tst = RXAFSCB_GetLocalCell(conn, &name);
2294 fail_util_CMLocalCell:
2302 static void UnmarshallCMClientConfig(
2303 afs_uint32 serverVersion,
2305 afs_ClientConfigUnion_p config)
2308 * We currently only support version 1.
2310 config->config_v1.nChunkFiles = *(ptr++);
2311 config->config_v1.nStatCaches = *(ptr++);
2312 config->config_v1.nDataCaches = *(ptr++);
2313 config->config_v1.nVolumeCaches = *(ptr++);
2314 config->config_v1.firstChunkSize = *(ptr++);
2315 config->config_v1.otherChunkSize = *(ptr++);
2316 config->config_v1.cacheSize = *(ptr++);
2317 config->config_v1.setTime = *(ptr++);
2318 config->config_v1.memCache = *(ptr++);
2322 * util_CMClientConfig - Get the cache manager's configuration parameters.
2326 * IN conn - an rx connection to the process to be queried
2328 * OUT config - the cache manager's configuration parameters.
2332 * No locks are obtained or released by this function
2336 * Returns != 0 upon successful completion.
2340 int ADMINAPI util_CMClientConfig(
2341 struct rx_connection *conn,
2342 afs_ClientConfig_p config,
2346 afs_status_t tst = 0;
2347 afs_int32 allocbytes;
2348 struct cacheConfig tconfig;
2351 tst = ADMRXCONNNULL;
2352 goto fail_util_CMClientConfig;
2355 if (config == NULL) {
2356 tst = ADMCLIENTCMCELLNAMENULL;
2357 goto fail_util_CMClientConfig;
2360 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2361 tconfig.cacheConfig_val = NULL;
2362 tconfig.cacheConfig_len = 0;
2363 tst = RXAFSCB_GetCacheConfig(conn,
2364 config->clientVersion,
2365 &config->serverVersion,
2370 goto fail_util_CMClientConfig;
2373 UnmarshallCMClientConfig(config->serverVersion,
2374 tconfig.cacheConfig_val,
2377 free(tconfig.cacheConfig_val);
2379 fail_util_CMClientConfig:
2388 * util_RXDebugVersion - Get the rxdebug version string.
2392 * IN handle - an rxdebug handle for the process to be queried.
2394 * OUT version - the rxdebug version string.
2398 * No locks are obtained or released by this function
2402 * Returns != 0 upon successful completion.
2406 int ADMINAPI util_RXDebugVersion(
2407 rxdebugHandle_p handle,
2408 rxdebugVersion_p version,
2412 afs_status_t tst = 0;
2415 if (handle == NULL) {
2416 tst = ADMRXDEBUGHANDLENULL;
2417 goto fail_util_RXDebugVersion;
2420 if (version == NULL) {
2421 tst = ADMRXDEBUGVERSIONNULL;
2422 goto fail_util_RXDebugVersion;
2425 code = rx_GetServerVersion(handle->sock,
2428 UTIL_MAX_RXDEBUG_VERSION_LEN,
2431 tst = ADMCLIENTRXDEBUGTIMEOUT;
2432 goto fail_util_RXDebugVersion;
2437 fail_util_RXDebugVersion:
2446 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2451 * IN handle - an rxdebug handle for the process to be queried.
2453 * OUT supportedStats - bit mask with supported rxstats.
2457 * No locks are obtained or released by this function
2461 * Returns != 0 upon successful completion.
2465 int ADMINAPI util_RXDebugSupportedStats(
2466 rxdebugHandle_p handle,
2467 afs_uint32 *supportedStats,
2471 afs_status_t tst = 0;
2472 struct rx_debugStats tstats;
2474 if (handle == NULL) {
2475 tst = ADMRXDEBUGHANDLENULL;
2476 goto fail_util_RXDebugSupportedStats;
2479 if (supportedStats == NULL) {
2480 tst = ADMRXDEBUGSTATSNULL;
2481 goto fail_util_RXDebugSupportedStats;
2484 if (handle->firstFlag) {
2485 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2487 goto fail_util_RXDebugSupportedStats;
2491 *supportedStats = handle->supportedStats;
2494 fail_util_RXDebugSupportedStats:
2504 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2508 * IN handle - an rxdebug handle for the process to be queried.
2510 * OUT stats - Basic rxdebug statistics for the process.
2514 * No locks are obtained or released by this function
2518 * Returns != 0 upon successful completion.
2522 int ADMINAPI util_RXDebugBasicStats(
2523 rxdebugHandle_p handle,
2524 struct rx_debugStats *stats,
2528 afs_status_t tst = 0;
2531 if (handle == NULL) {
2532 tst = ADMRXDEBUGHANDLENULL;
2533 goto fail_util_RXDebugBasicStats;
2536 if (stats == NULL) {
2537 tst = ADMRXDEBUGSTATSNULL;
2538 goto fail_util_RXDebugBasicStats;
2541 code = rx_GetServerDebug(handle->sock,
2545 &handle->supportedStats);
2547 tst = ADMCLIENTRXDEBUGTIMEOUT;
2548 goto fail_util_RXDebugBasicStats;
2551 handle->firstFlag = 0;
2554 fail_util_RXDebugBasicStats:
2564 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2568 * IN handle - an rxdebug handle for the process to be queried.
2570 * OUT stats - Detailed rxdebug statistics for the process.
2574 * No locks are obtained or released by this function
2578 * Returns != 0 upon successful completion.
2582 int ADMINAPI util_RXDebugRxStats(
2583 rxdebugHandle_p handle,
2584 struct rx_stats *stats,
2585 afs_uint32 *supportedValues,
2590 afs_status_t tst = 0;
2592 afs_uint32 tsupported;
2594 if (handle == NULL) {
2595 tst = ADMRXDEBUGHANDLENULL;
2596 goto fail_util_RXDebugRxStats;
2599 if (supportedValues == NULL) {
2600 tst = ADMRXDEBUGSTATSNULL;
2601 goto fail_util_RXDebugRxStats;
2604 if (stats == NULL) {
2605 tst = ADMRXDEBUGSTATSNULL;
2606 goto fail_util_RXDebugRxStats;
2609 if (handle->firstFlag) {
2610 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2613 goto fail_util_RXDebugRxStats;
2617 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2618 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2619 goto fail_util_RXDebugRxStats;
2622 code = rx_GetServerStats(handle->sock,
2626 &handle->supportedStats);
2628 tst = ADMCLIENTRXDEBUGTIMEOUT;
2629 goto fail_util_RXDebugRxStats;
2634 fail_util_RXDebugRxStats:
2643 * The iterator for listing RXDebug connections
2646 typedef struct rxdebug_conn_item {
2647 struct rx_debugConn conn;
2648 afs_uint32 supportedValues;
2649 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2651 typedef struct rxdebug_conn_get {
2653 rxdebugHandle_p handle;
2655 rxdebug_conn_item_t items[CACHED_ITEMS];
2656 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2658 static int RXDebugConnsFromServer(
2662 int *last_item_contains_data,
2667 afs_status_t tst = 0;
2668 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2671 * Get the next entry the list of connections
2673 code = rx_GetServerConnections(t->handle->sock,
2678 t->handle->supportedStats,
2679 &t->items[slot].conn,
2680 &t->items[slot].supportedValues);
2682 tst = ADMCLIENTRXDEBUGTIMEOUT;
2683 goto fail_ListCellsRPC;
2687 * See if we've processed all the entries
2689 if (t->items[slot].conn.cid == 0xffffffff) {
2691 *last_item_contains_data = 0;
2703 static int RXDebugConnsFromCache(
2710 afs_status_t tst = 0;
2711 rxdebug_conn_get_p t = (rxdebug_conn_get_p)rpc_specific;
2713 memcpy(dest, (const void *)&t->items[slot],
2714 sizeof(rxdebug_conn_item_t));
2724 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2729 * IN handle - an rxdebug handle for the process to be queried
2731 * IN allcons - non-zero to list all connections. If zero, only
2732 * "interesting" connections will be listed.
2734 * OUT iterationIdP - an iteration id that can be passed to
2735 * util_RXDebugConnectionsNext.
2739 * No locks are obtained or released by this function
2743 * Returns != 0 upon successful completion.
2747 int ADMINAPI util_RXDebugConnectionsBegin(
2748 rxdebugHandle_p handle,
2750 void **iterationIdP,
2755 afs_uint32 tsupported;
2756 afs_status_t tst = 0;
2757 afs_admin_iterator_p iter;
2758 rxdebug_conn_get_p t;
2760 if (handle == NULL) {
2761 tst = ADMRXDEBUGHANDLENULL;
2762 goto fail_util_RXDebugConnectionsBegin;
2765 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2768 goto fail_util_RXDebugConnectionsBegin;
2771 if (handle->firstFlag) {
2772 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2775 goto fail_util_RXDebugConnectionsBegin;
2780 !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2781 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2782 goto fail_util_RXDebugConnectionsBegin;
2785 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2789 goto fail_util_RXDebugConnectionsBegin;
2792 t->allconns = allconns;
2795 if (!IteratorInit(iter, (void *)t, RXDebugConnsFromServer,
2796 RXDebugConnsFromCache, NULL, NULL, &tst)) {
2797 goto fail_util_RXDebugConnectionsBegin;
2799 *iterationIdP = (void *) iter;
2802 fail_util_RXDebugConnectionsBegin:
2812 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2817 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2819 * OUT conn - Rxdebug information for the next connection.
2821 * OUT supportedValues - Bit mask of supported rxdebug values.
2825 * No locks are obtained or released by this function
2829 * Returns != 0 upon successful completion.
2833 int ADMINAPI util_RXDebugConnectionsNext(
2834 const void *iterationId,
2835 struct rx_debugConn *conn,
2836 afs_uint32 *supportedValues,
2840 afs_status_t tst = 0;
2841 rxdebug_conn_item_t item;
2842 afs_admin_iterator_p iter = (afs_admin_iterator_p)iterationId;
2844 if (iterationId == NULL) {
2845 tst = ADMITERATIONIDPNULL;
2846 goto fail_util_RXDebugConnectionsNext;
2850 tst = ADMRXDEBUGHANDLENULL;
2851 goto fail_util_RXDebugConnectionsNext;
2854 if (supportedValues == NULL) {
2855 tst = ADMRXDEBUGHANDLENULL;
2856 goto fail_util_RXDebugConnectionsNext;
2859 rc = IteratorNext(iter, (void *)&item, &tst);
2861 goto fail_util_RXDebugConnectionsNext;
2865 *supportedValues = item.supportedValues;
2867 fail_util_RXDebugConnectionsNext:
2877 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2881 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2885 * No locks are obtained or released by this function
2889 * Returns != 0 upon successful completion.
2893 int ADMINAPI util_RXDebugConnectionsDone(
2894 const void *iterationId,
2898 afs_status_t tst = 0;
2899 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2902 * Validate parameters
2906 tst = ADMITERATORNULL;
2907 goto fail_util_RXDebugConnectionsDone;
2910 rc = IteratorDone(iter, &tst);
2912 fail_util_RXDebugConnectionsDone:
2922 * The iterator for listing RXDebug peer
2925 typedef struct rxdebug_peer_item {
2926 struct rx_debugPeer peer;
2927 afs_uint32 supportedValues;
2928 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2930 typedef struct rxdebug_peer_get {
2931 rxdebugHandle_p handle;
2933 rxdebug_peer_item_t items[CACHED_ITEMS];
2934 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2936 static int RXDebugPeersFromServer(
2940 int *last_item_contains_data,
2945 afs_status_t tst = 0;
2946 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2949 * Get the next entry the list of peers
2951 code = rx_GetServerPeers(t->handle->sock,
2955 t->handle->supportedStats,
2956 &t->items[slot].peer,
2957 &t->items[slot].supportedValues);
2959 tst = ADMCLIENTRXDEBUGTIMEOUT;
2960 goto fail_ListCellsRPC;
2964 * See if we've processed all the entries
2966 if (t->items[slot].peer.host == 0xffffffff) {
2968 *last_item_contains_data = 0;
2980 static int RXDebugPeersFromCache(
2987 afs_status_t tst = 0;
2988 rxdebug_peer_get_p t = (rxdebug_peer_get_p)rpc_specific;
2990 memcpy(dest, (const void *)&t->items[slot],
2991 sizeof(rxdebug_peer_item_t));
3002 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
3007 * IN handle - an rxdebug handle for the process to be queried
3009 * OUT iterationIdP - an iteration id that can be passed to
3010 * util_RXDebugPeersNext.
3014 * No locks are obtained or released by this function
3018 * Returns != 0 upon successful completion.
3022 int ADMINAPI util_RXDebugPeersBegin(
3023 rxdebugHandle_p handle,
3024 void **iterationIdP,
3029 afs_uint32 tsupported;
3030 afs_status_t tst = 0;
3031 afs_admin_iterator_p iter;
3032 rxdebug_peer_get_p t;
3034 if (handle == NULL) {
3035 tst = ADMRXDEBUGHANDLENULL;
3036 goto fail_util_RXDebugPeersBegin;
3039 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
3042 goto fail_util_RXDebugPeersBegin;
3045 if (handle->firstFlag) {
3046 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
3049 goto fail_util_RXDebugPeersBegin;
3053 if(!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
3054 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
3055 goto fail_util_RXDebugPeersBegin;
3058 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
3062 goto fail_util_RXDebugPeersBegin;
3067 if (!IteratorInit(iter, (void *)t, RXDebugPeersFromServer,
3068 RXDebugPeersFromCache, NULL, NULL, &tst)) {
3069 goto fail_util_RXDebugPeersBegin;
3071 *iterationIdP = (void *) iter;
3074 fail_util_RXDebugPeersBegin:
3083 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3087 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3089 * OUT peer - Rxdebug information for the next peer.
3091 * OUT supportedValues - Bit mask of supported rxdebug values.
3095 * No locks are obtained or released by this function
3099 * Returns != 0 upon successful completion.
3102 int ADMINAPI util_RXDebugPeersNext(
3103 const void *iterationId,
3104 struct rx_debugPeer *peer,
3105 afs_uint32 *supportedValues,
3109 afs_status_t tst = 0;
3110 rxdebug_peer_item_t item;
3111 afs_admin_iterator_p iter = (afs_admin_iterator_p)iterationId;
3113 if (iterationId == NULL) {
3114 tst = ADMITERATIONIDPNULL;
3115 goto fail_util_RXDebugPeersNext;
3119 tst = ADMRXDEBUGHANDLENULL;
3120 goto fail_util_RXDebugPeersNext;
3123 if (supportedValues == NULL) {
3124 tst = ADMRXDEBUGHANDLENULL;
3125 goto fail_util_RXDebugPeersNext;
3128 rc = IteratorNext(iter, (void *)&item, &tst);
3130 goto fail_util_RXDebugPeersNext;
3134 *supportedValues = item.supportedValues;
3136 fail_util_RXDebugPeersNext:
3145 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3149 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3153 * No locks are obtained or released by this function
3157 * Returns != 0 upon successful completion.
3161 int ADMINAPI util_RXDebugPeersDone(
3162 const void *iterationId,
3166 afs_status_t tst = 0;
3167 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3170 * Validate parameters
3174 tst = ADMITERATORNULL;
3175 goto fail_util_RXDebugPeersDone;
3178 rc = IteratorDone(iter, &tst);
3180 fail_util_RXDebugPeersDone: