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
11 #include <afs/afs_Admin.h>
14 #include <afs/afs_Admin.h>
15 #include "afs_AdminInternal.h"
16 #include "afs_utilAdmin.h"
17 #include <afs/pthread_glock.h>
18 #include <afs/cellconfig.h>
19 #include <afs/dirpath.h>
20 #include <afs/com_err.h>
21 #include <afs/kautils.h>
23 #include <afs/vlserver.h>
24 #include <afs/pterror.h>
25 #include <afs/bnode.h>
26 #include <afs/volser.h>
27 #include <afs/afsint.h>
29 #include <rx/rxstat.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.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;
55 static void init_once(void) {
57 initialize_ka_error_table();
58 initialize_rxk_error_table();
59 initialize_ktc_error_table();
60 initialize_acfg_error_table();
61 initialize_cmd_error_table();
62 initialize_vl_error_table();
63 initialize_pt_error_table();
64 initialize_bz_error_table();
65 initialize_u_error_table();
66 initialize_ab_error_table();
67 initialize_af_error_table();
68 initialize_al_error_table();
69 initialize_ac_error_table();
70 initialize_ak_error_table();
71 initialize_am_error_table();
72 initialize_ap_error_table();
73 initialize_au_error_table();
74 initialize_av_error_table();
75 initialize_vols_error_table();
79 int ADMINAPI util_AdminErrorCodeTranslate(
80 afs_status_t errorCode,
82 const char **errorTextP,
89 if (errorTextP == NULL) {
90 tst = ADMUTILERRORTEXTPNULL;
91 goto fail_util_AdminErrorCodeTranslate;
98 if ( !error_init_done )
99 pthread_once(&error_init_once, init_once);
100 code = (afs_int32) errorCode;
101 *errorTextP = error_message(code);
104 fail_util_AdminErrorCodeTranslate:
113 * The iterator functions and data for the database server retrieval functions.
116 typedef struct database_server_get {
119 struct afsconf_dir *conf;
120 struct afsconf_cell cell;
121 util_databaseServerEntry_t server[CACHED_ITEMS];
122 } database_server_get_t, *database_server_get_p;
124 static int GetDatabaseServerRPC(
128 int *last_item_contains_data,
132 afs_status_t tst = 0;
133 database_server_get_p serv = (database_server_get_p) rpc_specific;
135 serv->server[slot].serverAddress = ntohl(serv->cell.hostAddr[serv->index].sin_addr.s_addr);
136 strcpy(serv->server[slot].serverName, serv->cell.hostName[serv->index]);
140 * See if we've processed all the entries
143 if (serv->index == serv->total) {
145 *last_item_contains_data = 1;
155 static int GetDatabaseServerFromCache(
162 afs_status_t tst = 0;
163 database_server_get_p serv = (database_server_get_p) rpc_specific;
165 memcpy(dest, (const void *) &serv->server[slot],
166 sizeof(util_databaseServerEntry_t));
175 static int DestroyDatabaseServer(
180 afs_status_t tst = 0;
181 database_server_get_p serv = (database_server_get_p) rpc_specific;
183 afsconf_Close(serv->conf);
193 * util_DatabaseServerGetBegin - begin iterating over the database
194 * server machines in a cell.
198 * IN cellName - the cell where database servers reside.
200 * OUT iterationIdP - upon successful completion contains an iterator that
201 * can be passed to util_DatabaseServerGetNext.
205 * No locks are obtained or released by this function
213 * Returns != 0 upon successful completion.
216 int ADMINAPI util_DatabaseServerGetBegin(
217 const char *cellName,
222 afs_status_t tst = 0;
223 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
224 database_server_get_p serv = (database_server_get_p) calloc(1, sizeof(database_server_get_t));
225 char copyCell[MAXCELLCHARS];
231 if ((cellName == NULL) || (*cellName == 0)) {
232 tst = ADMUTILCELLNAMENULL;
233 goto fail_util_DatabaseServerGetBegin;
236 if (iterationIdP == NULL) {
237 goto fail_util_DatabaseServerGetBegin;
240 if ((iter == NULL) || (serv == NULL)) {
242 goto fail_util_DatabaseServerGetBegin;
246 * Fill in the serv structure
249 serv->conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
250 if (serv->conf == NULL) {
251 tst = ADMUTILCANTOPENCELLSERVDB;
252 goto fail_util_DatabaseServerGetBegin;
256 * We must copy the cellname because afsconf_GetCellInfo
257 * actually writes over the cell name it is passed.
259 strncpy(copyCell, cellName, MAXCELLCHARS - 1);
260 tst = afsconf_GetCellInfo(serv->conf, copyCell, AFSCONF_KAUTHSERVICE,
263 goto fail_util_DatabaseServerGetBegin;
266 serv->total = serv->cell.numServers;
267 if (IteratorInit(iter, (void *) serv, GetDatabaseServerRPC,
268 GetDatabaseServerFromCache, NULL, DestroyDatabaseServer,
270 *iterationIdP = (void *) iter;
272 goto fail_util_DatabaseServerGetBegin;
276 fail_util_DatabaseServerGetBegin:
294 * util_DatabaseServerGetNext - get the next server address.
298 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
300 * OUT serverAddressP - upon successful completion contains the next
301 * server address in the cell.
305 * This function locks the iterator for the duration of its processing.
313 * Returns != 0 upon successful completion.
317 int ADMINAPI util_DatabaseServerGetNext(
318 const void *iterationId,
319 util_databaseServerEntry_p serverP,
323 afs_status_t tst = 0;
324 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
327 tst = ADMITERATORNULL;
328 goto fail_util_DatabaseServerGetNext;
331 if (serverP == NULL) {
332 tst = ADMUTILSERVERADDRESSPNULL;
333 goto fail_util_DatabaseServerGetNext;
336 rc = IteratorNext(iter, (void *) serverP, &tst);
338 fail_util_DatabaseServerGetNext:
347 * util_DatabaseServerGetDone - stop using a database iterator.
351 * IN iterationId - an iterator returned by util_DatabaseServerGetBegin
355 * This function locks the iterator for the duration of its processing.
356 * And then destroys it before returning.
364 * Returns != 0 upon successful completion.
367 int ADMINAPI util_DatabaseServerGetDone(
368 const void *iterationId,
372 afs_status_t tst = 0;
373 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
376 * Validate parameters
380 tst = ADMITERATORNULL;
381 goto fail_util_DatabaseServerGetDone;
384 rc = IteratorDone(iter, &tst);
386 fail_util_DatabaseServerGetDone:
395 * GetServerAddressFromName - translate a character string server name
396 * to an integer representation of an IP address.
400 * IN serverName - the character string server name in either foo.com
401 * format, or 123.12.1.1 format.
403 * OUT serverAddress - an integer that is filled with the correct address
404 * in host byte order upon successful completion.
408 * No locks are obtained or released by this function
412 * On many platforms, gethostbyname is not thread safe. Since we are
413 * only working under NT for now I'll use it directly. In future UNIX
414 * ports, a wrapper function should be written to call the correct function
415 * on the particular platform.
419 * Returns != 0 upon successful completion.
422 int ADMINAPI util_AdminServerAddressGetFromName(
423 const char *serverName,
428 afs_status_t tst = 0;
429 struct hostent *server;
430 int part1, part2, part3, part4;
433 if ((serverName == NULL) || (*serverName == 0)) {
434 tst = ADMUTILSERVERNAMENULL;
435 goto fail_util_AdminServerAddressGetFromName;
438 if (serverAddress == NULL) {
439 tst = ADMUTILSERVERADDRESSNULL;
440 goto fail_util_AdminServerAddressGetFromName;
443 num_converted = sscanf(serverName, "%d.%d.%d.%d", &part1, &part2, &part3, &part4);
444 if (num_converted == 4) {
445 *serverAddress = (part1<<24) | (part2<<16) | (part3<<8) | part4;
448 server = gethostbyname(serverName);
449 if (server != NULL) {
450 memcpy((void *) serverAddress, (const void *) server->h_addr, sizeof(serverAddress));
451 *serverAddress = ntohl(*serverAddress);
453 tst = ADMUTILCANTGETSERVERNAME;
455 goto fail_util_AdminServerAddressGetFromName;
461 fail_util_AdminServerAddressGetFromName:
471 * This file contains functions that can be used to create iterator
472 * functions within the api. I have attempted to make these functions
473 * generic so that they can be used across the admin components.
475 * The functions in this file are a generalized producer/consumer
476 * implementation. They manage access to a queue of data. The only
477 * assumption these functions make about this data is that it is
478 * stored in a queue which is implemented via an array. These functions
479 * know about the index into the array, but they know nothing about
480 * the contents of the array.
482 * The data specific functions you implement will have to create some
483 * data specific storage structure that will have an array
484 * of size CACHED_ITEMS data items. This structure will also need to
485 * store any necessary parameters/state variables you need to issue the
486 * rpc to retrieve the next item.
488 * In order to use the generic functions, you must implement four functions
489 * for each type of data you wish to retrieve. The functions are:
491 * validate_specific_data_func - this function is handed a void pointer
492 * that points to the rpc specific data you've allocated. The function
493 * should examine the data for validity and return an appropriate error.
494 * This function is called every time the iterator is validated.
496 * destroy_specific_data_func - this function is handed a void pointer
497 * that points to the rpc specific data you've allocated. It should
498 * destroy any components of the specific data as required and then
499 * return. The void pointer is free'd by the generic functions.
501 * get_cached_data_func - this function is handed a void pointer
502 * that points to the rpc specific data you've allocated, an index
503 * into the cache of the item to be copied to the caller, and a void
504 * pointer where the cache item should be copied.
506 * make_rpc_func - this function is handed a void pointer that points
507 * to the rpc specific data you've allocated, an index into the cache
508 * of the item to be filled with the next retrieved item, and an int
509 * pointer that should be set to 1 if there are no more items to be
510 * retrieved. The assumption made by the generic functions is that
511 * the last_item status requires an individual rpc - the data isn't
512 * piggybacked on the last data item.
516 * IteratorDelete - delete an iterator.
520 * IN interator - the iterator to delete.
524 * No locks are held by this function.
528 * Returns != 0 upon successful completion.
531 static int IteratorDelete(
532 afs_admin_iterator_p iter,
536 afs_status_t tst = 0;
538 if(pthread_mutex_destroy(&iter->mutex)) {
539 tst = ADMMUTEXDESTROY;
540 goto fail_IteratorDelete;
542 if(pthread_cond_destroy(&iter->add_item)) {
543 tst = ADMCONDDESTROY;
544 goto fail_IteratorDelete;
546 if(pthread_cond_destroy(&iter->remove_item)) {
547 tst = ADMCONDDESTROY;
548 goto fail_IteratorDelete;
551 if (iter->destroy_specific != NULL) {
552 iter->destroy_specific(iter->rpc_specific, &tst);
554 free(iter->rpc_specific);
567 * DataGet - the background thread that is spawned for every
568 * IteratorBegin call that is successful. This thread tries
569 * to fetch the data from the server ahead of the
570 * IteratorNext calls.
574 * IN arg - the address of the iterator structure to be used for this
579 * The iterator mutex is used by this function to protect elements
580 * of the iterator structure.
584 * Returns != 0 upon successful completion.
587 static void *DataGet(void *arg)
589 afs_admin_iterator_p iter = (afs_admin_iterator_p) arg;
591 afs_status_t tst = 0;
592 int mutex_locked = 0;
594 int last_item_contains_data = 0;
596 if (pthread_mutex_lock(&iter->mutex)) {
597 iter->st = ADMMUTEXLOCK;
606 * Check to see if there's room for this datum. If not, wait
607 * on the consumer to free up another slot.
610 while (iter->cache_slots_used == CACHED_ITEMS) {
611 if (pthread_cond_wait(&iter->remove_item, &iter->mutex)) {
612 iter->st = ADMCONDWAIT;
618 * Check to see if someone called Done and terminated the request.
619 * We could have gone to sleep above when the buffer was full and
620 * instead of being awoken because another slot is open, we were
621 * awoken because the request was terminated.
624 if (iter->request_terminated) {
628 if (pthread_mutex_unlock(&iter->mutex)) {
629 iter->st = ADMMUTEXUNLOCK;
636 * Make an rpc without holding the iter mutex
637 * We reference an item in the principal cache here without
638 * holding the mutex. This is safe because:
639 * 1. The iter structure is ref counted and won't be deleted
640 * from underneath us.
641 * 2. cache_queue_tail is always one item ahead of the consumer
642 * thread so we are the only thread accessing this member.
645 iter->make_rpc(iter->rpc_specific, iter->cache_queue_tail,
646 &last_item, &last_item_contains_data, &tst);
648 if (pthread_mutex_lock(&iter->mutex)) {
649 iter->st = ADMMUTEXLOCK;
656 * Check to see if someone called Done and terminated the request
659 if (iter->request_terminated) {
664 * Check the rc of the rpc, and see if there are no more items
674 * Check to see if this is the last item produced by the rpc.
675 * If it isn't, add the item to the cache and proceed.
676 * If it is, check to see if the last item contains valid data.
677 * If it contains valid data, we need to add it to our cache.
678 * If it doesn't, we mark the iterator as complete.
681 if ((!last_item) || ((last_item) && (last_item_contains_data))) {
682 iter->cache_queue_tail = (iter->cache_queue_tail + 1) %
684 iter->cache_slots_used++;
687 iter->st = ADMITERATORDONE;
688 iter->done_iterating = 1;
690 * There's a small chance that the consumer emptied the
691 * cache queue while we were making the last rpc and has
692 * since gone to sleep waiting for more data. In this case
693 * there will never be more data so we signal him here.
695 pthread_cond_signal(&iter->add_item);
701 * If the cache was empty and we just added another item, signal
705 if (iter->cache_slots_used == 1) {
706 if (pthread_cond_signal(&iter->add_item)) {
707 iter->st = ADMCONDSIGNAL;
717 * If we are exiting with an error, signal the consumer in the event
718 * they were waiting for us to produce more data
722 pthread_cond_signal(&iter->add_item);
726 pthread_mutex_unlock(&iter->mutex);
733 * IsValidIterator - verify the validity of a afs_admin_iterator_t.
737 * IN interator - the interator to be verified.
741 * We assume the iter->mutex lock is already held.
745 * Returns != 0 upon successful completion.
748 static int IsValidIterator(
749 const afs_admin_iterator_p iterator,
753 afs_status_t tst = 0;
756 * Validate input parameters
759 if (iterator == NULL) {
760 tst = ADMITERATORNULL;
761 goto fail_IsValidIterator;
764 if ((iterator->begin_magic != BEGIN_MAGIC) ||
765 (iterator->end_magic != END_MAGIC)) {
766 tst = ADMITERATORBADMAGICNULL;
767 goto fail_IsValidIterator;
770 if (iterator->is_valid == 0) {
771 tst = ADMITERATORINVALID;
772 goto fail_IsValidIterator;
776 * Call the iterator specific validation function
779 if (iterator->validate_specific != NULL) {
780 if (!iterator->validate_specific(iterator->rpc_specific, &tst)) {
781 goto fail_IsValidIterator;
786 fail_IsValidIterator:
795 * IteratorNext - return the next datum in an interator.
799 * IN interator - the iterator containing the data.
801 * IN dest - the address where the data should be copied.
805 * Lock the iterator upon entry, and hold it during the duration of this
810 * Returns != 0 upon successful completion.
814 afs_admin_iterator_p iter,
819 afs_status_t tst = 0;
823 * We have to lock the iterator before we validate it
826 if (pthread_mutex_lock(&iter->mutex)) {
828 goto fail_IteratorNext;
833 if (!IsValidIterator(iter, &tst)) {
834 goto fail_IteratorNext;
837 if (iter->request_terminated == 1) {
838 tst = ADMITERATORTERMINATED;
839 goto fail_IteratorNext;
842 if ((iter->st != AFS_STATUS_OK) && (iter->st != ADMITERATORDONE)) {
844 goto fail_IteratorNext;
848 * Check to see if there are any queue'd items. If not, wait here
849 * until signalled by the producer.
852 while (iter->cache_slots_used == 0) {
855 * Maybe the producer experienced an rpc failure.
858 if ((!iter->done_iterating) && (iter->st != 0)) {
860 goto fail_IteratorNext;
864 * Maybe there are no queue'd items because the producer is done
867 if (iter->done_iterating) {
869 goto fail_IteratorNext;
872 if (pthread_cond_wait(&iter->add_item, &iter->mutex)) {
874 goto fail_IteratorNext;
879 * Copy the next cached item and update the cached item count
880 * and the index into the cache array
883 if (!iter->get_cached_data(iter->rpc_specific,
884 iter->cache_queue_head,
887 goto fail_IteratorNext;
890 iter->cache_queue_head = (iter->cache_queue_head + 1) % CACHED_ITEMS;
891 iter->cache_slots_used--;
894 * If the cache was full before we removed the item above, the
895 * producer may have been waiting for us to remove an item.
896 * Signal the producer letting him know that we've opened a slot
900 if (iter->cache_slots_used == (CACHED_ITEMS - 1)) {
901 if (pthread_cond_signal(&iter->remove_item)) {
903 goto fail_IteratorNext;
911 if (locked_iter == 1) {
912 pthread_mutex_unlock(&iter->mutex);
922 * IteratorDone - mark the iterator done.
926 * IN interator - the iterator to mark done.
930 * Lock the iterator upon entry, and hold it during the duration of this
935 * Returns != 0 upon successful completion.
939 afs_admin_iterator_p iter,
943 afs_status_t tst = 0;
944 int mutex_locked = 1;
946 if (pthread_mutex_lock(&iter->mutex)) {
948 goto fail_IteratorDone;
954 if (!IsValidIterator(iter, &tst)) {
955 goto fail_IteratorDone;
960 * Depending upon the status of the background worker thread,
961 * we can either join with him immediately (if we know he has
962 * terminated), or we need to tell him the request has been
963 * terminated and then join with him.
966 if (!iter->done_iterating) {
967 iter->request_terminated = 1;
968 iter->cache_slots_used = 0;
969 pthread_cond_signal(&iter->remove_item);
973 * We have to unlock the mutex to allow the background thread to
977 if (pthread_mutex_unlock(&iter->mutex)) {
978 tst = ADMMUTEXUNLOCK;
979 goto fail_IteratorDone;
982 if (iter->make_rpc != NULL) {
983 if (pthread_join(iter->bg_worker, (void **) 0)) {
985 goto fail_IteratorDone;
990 * We don't relock the mutex here since we are the only thread
991 * that has access to the iter now
994 rc = IteratorDelete(iter, &tst);
1000 pthread_mutex_unlock(&iter->mutex);
1010 * IteratorInit - initialize an iterator.
1014 * IN interator - the iterator to initialize.
1018 * No locks are held by this function.
1022 * Returns != 0 upon successful completion.
1026 afs_admin_iterator_p iter,
1028 make_rpc_func make_rpc,
1029 get_cached_data_func get_cached_data,
1030 validate_specific_data_func validate_specific_data,
1031 destroy_specific_data_func destroy_specific_data,
1035 afs_status_t tst = 0;
1036 int mutex_inited = 0;
1037 int add_item_cond_inited = 0;
1038 int remove_item_cond_inited = 0;
1041 tst = ADMITERATORNULL;
1042 goto fail_IteratorInit;
1045 if (rpc_specific == NULL) {
1046 tst = ADMITERATORRPCSPECIFICNULL;
1047 goto fail_IteratorInit;
1051 * Initialize the iterator structure
1053 iter->begin_magic = BEGIN_MAGIC;
1054 iter->end_magic = END_MAGIC;
1056 iter->cache_slots_used = 0;
1057 iter->done_iterating = 0;
1058 iter->request_terminated = 0;
1059 iter->st = AFS_STATUS_OK;
1060 iter->cache_queue_head = 0;
1061 iter->cache_queue_tail = 0;
1062 iter->cache_slots_used = 0;
1063 iter->rpc_specific = rpc_specific;
1064 iter->make_rpc = make_rpc;
1065 iter->get_cached_data = get_cached_data;
1066 iter->validate_specific = validate_specific_data;
1067 iter->destroy_specific = destroy_specific_data;
1069 if (pthread_mutex_init(&iter->mutex, (const pthread_mutexattr_t *) 0)) {
1071 goto fail_IteratorInit;
1076 if (pthread_cond_init(&iter->add_item, (const pthread_condattr_t *) 0)) {
1078 goto fail_IteratorInit;
1080 add_item_cond_inited = 1;
1083 if (pthread_cond_init(&iter->remove_item, (const pthread_condattr_t *) 0)) {
1085 goto fail_IteratorInit;
1087 remove_item_cond_inited = 1;
1091 * Create a worker thread that will begin to query the server
1092 * and cache responses.
1095 if (iter->make_rpc != NULL) {
1096 pthread_attr_t tattr;
1098 if (pthread_attr_init(&tattr)) {
1099 tst = ADMTHREADATTRINIT;
1100 goto fail_IteratorInit;
1103 if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_JOINABLE)) {
1104 tst = ADMTHREADATTRSETDETACHSTATE;
1105 goto fail_IteratorInit;
1108 if (pthread_create(&iter->bg_worker, &tattr,
1109 DataGet, (void *) iter)) {
1110 tst = ADMTHREADCREATE;
1111 goto fail_IteratorInit;
1120 pthread_mutex_destroy(&iter->mutex);
1122 if (remove_item_cond_inited) {
1123 pthread_cond_destroy(&iter->remove_item);
1125 if (add_item_cond_inited) {
1126 pthread_cond_destroy(&iter->add_item);
1136 int ADMINAPI CellHandleIsValid(
1137 const void *cellHandle,
1141 afs_status_t tst = 0;
1142 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1145 * Validate input parameters
1148 if (c_handle == NULL) {
1149 tst = ADMCLIENTCELLHANDLENULL;
1150 goto fail_CellHandleIsValid;
1153 if ((c_handle->begin_magic != BEGIN_MAGIC) ||
1154 (c_handle->end_magic != END_MAGIC)) {
1155 tst = ADMCLIENTCELLHANDLEBADMAGIC;
1156 goto fail_CellHandleIsValid;
1159 if (c_handle->is_valid == 0) {
1160 tst = ADMCLIENTCELLINVALID;
1161 goto fail_CellHandleIsValid;
1165 fail_CellHandleIsValid:
1174 * The iterator functions and data for the rpc statistic retrieval functions
1177 typedef struct rpc_stat_get {
1178 afs_uint32 clock_sec;
1179 afs_uint32 clock_usec;
1182 afs_uint32 clientVersion;
1183 afs_uint32 serverVersion;
1184 struct rpcStats stat_list;
1185 afs_RPCStats_t stats[CACHED_ITEMS];
1186 afs_uint32 *pointer;
1187 } rpc_stat_get_t, *rpc_stat_get_p;
1189 static void UnmarshallRPCStats(
1190 afs_uint32 serverVersion,
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++);
1235 static int GetRPCStatsRPC(
1239 int *last_item_contains_data,
1243 afs_status_t tst = 0;
1244 rpc_stat_get_p t = (rpc_stat_get_p) rpc_specific;
1246 t->stats[slot].clientVersion = t->clientVersion;
1247 t->stats[slot].serverVersion = t->serverVersion;
1248 t->stats[slot].statCount = t->total;
1251 * If the server stat version is greater than or equal to my version
1252 * number, it is required to return the values in the client's current
1256 UnmarshallRPCStats(t->serverVersion,
1263 * See if we've processed all the entries
1266 if (t->index == t->total) {
1268 *last_item_contains_data = 1;
1278 static int GetRPCStatsFromCache(
1285 afs_status_t tst = 0;
1286 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1288 memcpy(dest, (const void *) &stat->stats[slot],
1289 sizeof(afs_RPCStats_t));
1298 static int DestroyRPCStats(
1303 afs_status_t tst = 0;
1304 rpc_stat_get_p stat = (rpc_stat_get_p) rpc_specific;
1306 if (stat->stat_list.rpcStats_val != NULL) {
1307 free(stat->stat_list.rpcStats_val);
1318 * util_RPCStatsGetBegin - begin retrieving rpc stats for a process
1322 * IN conn - an rx connection to the process to be queried
1324 * IN rpc - the function to call to make the actual rpc
1326 * OUT iterationIdP - an iteration id that can be passed to
1327 * util_RPCStatsGetNext to get the next rpc stat
1331 * No locks are obtained or released by this function
1335 * Returns != 0 upon successful completion.
1339 int ADMINAPI util_RPCStatsGetBegin(
1340 struct rx_connection *conn,
1342 void **iterationIdP,
1346 afs_status_t tst = 0;
1347 afs_admin_iterator_p iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1348 rpc_stat_get_p stat = (rpc_stat_get_p) malloc(sizeof(rpc_stat_get_t));
1351 tst = ADMRXCONNNULL;
1352 goto fail_util_RPCStatsGetBegin;
1356 tst = ADMRPCPTRNULL;
1357 goto fail_util_RPCStatsGetBegin;
1360 if (iterationIdP == NULL) {
1361 tst = ADMITERATIONIDPNULL;
1362 goto fail_util_RPCStatsGetBegin;
1365 if ((iter == NULL) || (stat == NULL)) {
1367 goto fail_util_RPCStatsGetBegin;
1370 stat->stat_list.rpcStats_len = 0;
1371 stat->stat_list.rpcStats_val = 0;
1373 stat->clientVersion = RX_STATS_RETRIEVAL_VERSION;
1376 stat->clientVersion,
1377 &stat->serverVersion,
1384 goto fail_util_RPCStatsGetBegin;
1388 * If there are no statistics, just mark the iterator done and
1392 if (stat->stat_list.rpcStats_len == 0) {
1393 stat->pointer = NULL;
1394 if (!IteratorInit(iter,
1401 goto fail_util_RPCStatsGetBegin;
1403 iter->done_iterating = 1;
1404 iter->st = ADMITERATORDONE;
1406 stat->pointer = stat->stat_list.rpcStats_val;
1407 if (!IteratorInit(iter,
1410 GetRPCStatsFromCache,
1414 goto fail_util_RPCStatsGetBegin;
1417 *iterationIdP = (void *) iter;
1420 fail_util_RPCStatsGetBegin:
1438 * util_RPCStatsGetNext - retrieve the next rpc stat from the server
1442 * IN iterationId - an iterator previously returned by
1443 * util_RPCStatsGetBegin.
1445 * OUT stats - upon successful completion contains the next set of stats
1450 * No locks are obtained or released by this function
1454 * Returns != 0 upon successful completion.
1458 int ADMINAPI util_RPCStatsGetNext(
1459 const void *iterationId,
1460 afs_RPCStats_p stats,
1464 afs_status_t tst = 0;
1465 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1467 if (iterationId == NULL) {
1468 tst = ADMITERATIONIDPNULL;
1469 goto fail_util_RPCStatsGetNext;
1472 if (stats == NULL) {
1473 tst = ADMUTILRPCSTATSNULL;
1474 goto fail_util_RPCStatsGetNext;
1477 rc = IteratorNext(iter, (void *) stats, &tst);
1479 fail_util_RPCStatsGetNext:
1488 * util_RPCStatsGetDone - finish using a stats iterator
1492 * IN iterationId - an iterator previously returned by
1493 * util_RPCStatsGetBegin.
1497 * No locks are obtained or released by this function
1501 * Returns != 0 upon successful completion.
1505 int ADMINAPI util_RPCStatsGetDone(
1506 const void *iterationId,
1510 afs_status_t tst = 0;
1511 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1513 if (iterationId == NULL) {
1514 tst = ADMITERATIONIDPNULL;
1515 goto fail_util_RPCStatsGetDone;
1518 rc = IteratorDone(iter, &tst);
1520 fail_util_RPCStatsGetDone:
1529 * util_RPCStatsStateGet - get the current state of rpc stat collection
1533 * IN conn - an rx connection to the process to be queried
1535 * IN rpc - the function to call to make the actual rpc
1537 * OUT state - the rpc stat collection state.
1541 * No locks are obtained or released by this function
1545 * Returns != 0 upon successful completion.
1549 int ADMINAPI util_RPCStatsStateGet(
1550 struct rx_connection *conn,
1552 afs_RPCStatsState_p state,
1556 afs_status_t tst = 0;
1559 tst = ADMRXCONNNULL;
1560 goto fail_util_RPCStatsStateGet;
1564 tst = ADMRPCPTRNULL;
1565 goto fail_util_RPCStatsStateGet;
1568 if (state == NULL) {
1569 tst = ADMRPCSTATENULL;
1570 goto fail_util_RPCStatsStateGet;
1573 tst = (*rpc)(conn, state);
1579 fail_util_RPCStatsStateGet:
1588 * util_RPCStatsStateEnable - enable rpc stat collection
1593 * IN conn - an rx connection to the process to be modified
1595 * IN rpc - the function to call to make the actual rpc
1599 * No locks are obtained or released by this function
1603 * Returns != 0 upon successful completion.
1607 int ADMINAPI util_RPCStatsStateEnable(
1608 struct rx_connection *conn,
1613 afs_status_t tst = 0;
1616 tst = ADMRXCONNNULL;
1617 goto fail_util_RPCStatsStateEnable;
1621 tst = ADMRPCPTRNULL;
1622 goto fail_util_RPCStatsStateEnable;
1631 fail_util_RPCStatsStateEnable:
1640 * util_RPCStatsStateDisable - set the current state of rpc stat collection
1645 * IN conn - an rx connection to the process to be modified
1647 * IN rpc - the function to call to make the actual rpc
1651 * No locks are obtained or released by this function
1655 * Returns != 0 upon successful completion.
1659 int ADMINAPI util_RPCStatsStateDisable(
1660 struct rx_connection *conn,
1665 afs_status_t tst = 0;
1668 tst = ADMRXCONNNULL;
1669 goto fail_util_RPCStatsStateDisable;
1673 tst = ADMRPCPTRNULL;
1674 goto fail_util_RPCStatsStateDisable;
1683 fail_util_RPCStatsStateDisable:
1692 * util_RPCStatsClear - clear some or all of the fields in the rpc stat
1693 * collection at a server
1697 * IN conn - an rx connection to the process to be modified
1699 * IN rpc - the function to call to make the actual rpc
1701 * IN flag - a flag containing the fields to be cleared
1706 * No locks are obtained or released by this function
1710 * Returns != 0 upon successful completion.
1714 int ADMINAPI util_RPCStatsClear(
1715 struct rx_connection *conn,
1717 afs_RPCStatsClearFlag_t flag,
1721 afs_status_t tst = 0;
1724 tst = ADMRXCONNNULL;
1725 goto fail_util_RPCStatsClear;
1729 tst = ADMRPCPTRNULL;
1730 goto fail_util_RPCStatsClear;
1733 tst = (*rpc)(conn, flag);
1739 fail_util_RPCStatsClear:
1748 * util_RPCStatsVersionGet - get the current version of rpc stat collection
1752 * IN conn - an rx connection to the process to be modified
1754 * OUT version - the version of rpc stat collection at the remote process
1758 * No locks are obtained or released by this function
1762 * Returns != 0 upon successful completion.
1766 int ADMINAPI util_RPCStatsVersionGet(
1767 struct rx_connection *conn,
1768 afs_RPCStatsVersion_p version,
1772 afs_status_t tst = 0;
1775 tst = ADMRXCONNNULL;
1776 goto fail_util_RPCStatsVersionGet;
1779 if (version == NULL) {
1780 tst = ADMRPCVERSIONNULL;
1781 goto fail_util_RPCStatsVersionGet;
1784 tst = RXSTATS_QueryRPCStatsVersion(conn, version);
1790 fail_util_RPCStatsVersionGet:
1799 * The iterator for listing CM server preferences
1802 typedef struct cm_srvr_pref_get {
1803 struct rx_connection *conn;
1805 afs_CMServerPref_t srvrPrefs[CACHED_ITEMS];
1806 } cm_srvr_pref_get_t, *cm_srvr_pref_get_p;
1808 static int GetServerPrefsRPC(
1812 int *last_item_contains_data,
1816 afs_status_t tst = 0;
1817 cm_srvr_pref_get_p t = (cm_srvr_pref_get_p) rpc_specific;
1820 * Get the next entry in the list of server preferences.
1822 tst = RXAFSCB_GetServerPrefs(t->conn, t->index,
1823 &t->srvrPrefs[slot].ipAddr,
1824 &t->srvrPrefs[slot].ipRank);
1826 goto fail_GetServerPrefsRPC;
1830 * See if we've processed all the entries
1832 if (t->srvrPrefs[slot].ipAddr == 0xffffffff) {
1834 *last_item_contains_data = 0;
1840 fail_GetServerPrefsRPC:
1848 static int GetServerPrefsFromCache(
1855 afs_status_t tst = 0;
1856 cm_srvr_pref_get_p prefs = (cm_srvr_pref_get_p) rpc_specific;
1858 memcpy(dest, (const void *) &prefs->srvrPrefs[slot],
1859 sizeof(afs_CMServerPref_t));
1869 * util_CMGetServerPrefsBegin - Begin listing cache manager server preferences
1873 * IN conn - an rx connection to the process to be queried
1875 * OUT iterationIdP - an iteration id that can be passed to
1876 * util_CMGetServerPrefsNext to get the next server preference
1880 * No locks are obtained or released by this function
1884 * Returns != 0 upon successful completion.
1888 int ADMINAPI util_CMGetServerPrefsBegin(
1889 struct rx_connection *conn,
1890 void **iterationIdP,
1894 afs_status_t tst = 0;
1895 afs_admin_iterator_p iter;
1896 cm_srvr_pref_get_p pref;
1899 tst = ADMRXCONNNULL;
1900 goto fail_util_CMGetServerPrefsBegin;
1903 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1906 goto fail_util_CMGetServerPrefsBegin;
1909 pref = (cm_srvr_pref_get_p) malloc(sizeof(cm_srvr_pref_get_t));
1913 goto fail_util_CMGetServerPrefsBegin;
1918 if (!IteratorInit(iter, (void *) pref, GetServerPrefsRPC,
1919 GetServerPrefsFromCache, NULL, NULL, &tst)) {
1922 goto fail_util_CMGetServerPrefsBegin;
1924 *iterationIdP = (void *) iter;
1927 fail_util_CMGetServerPrefsBegin:
1936 * util_CMGetServerPrefsNext - Get next entry in cache manager server
1941 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1943 * OUT prefs - Next entry in cache manager server preferences.
1947 * No locks are obtained or released by this function
1951 * Returns != 0 upon successful completion.
1955 int ADMINAPI util_CMGetServerPrefsNext(
1956 const void *iterationId,
1957 afs_CMServerPref_p prefs,
1961 afs_status_t tst = 0;
1962 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
1964 if (iterationId == NULL) {
1965 tst = ADMITERATIONIDPNULL;
1966 goto fail_util_CMGetServerPrefsNext;
1969 rc = IteratorNext(iter, (void *) prefs, &tst);
1971 fail_util_CMGetServerPrefsNext:
1980 * util_CMGetServerPrefsDone - Finish listing cache manager server
1985 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
1989 * No locks are obtained or released by this function
1993 * Returns != 0 upon successful completion.
1997 int ADMINAPI util_CMGetServerPrefsDone(
1998 const void *iterationId,
2002 afs_status_t tst = 0;
2003 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2005 if (iterationId == NULL) {
2006 tst = ADMITERATIONIDPNULL;
2007 goto fail_util_CMGetServerPrefsDone;
2010 rc = IteratorDone(iter, &tst);
2013 fail_util_CMGetServerPrefsDone:
2022 * The iterator for listing CM CellServDB
2025 typedef struct cm_list_cell_get {
2026 struct rx_connection *conn;
2028 afs_CMListCell_t cell[CACHED_ITEMS];
2029 } cm_list_cell_get_t, *cm_list_cell_get_p;
2031 static int ListCellsRPC(
2035 int *last_item_contains_data,
2039 afs_status_t tst = 0;
2040 cm_list_cell_get_p t = (cm_list_cell_get_p) rpc_specific;
2044 * Get the next entry in the CellServDB.
2046 name = t->cell[slot].cellname;
2047 tst = RXAFSCB_GetCellServDB(t->conn, t->index, &name,
2048 t->cell[slot].serverAddr);
2050 goto fail_ListCellsRPC;
2052 strcpy(t->cell[slot].cellname, name);
2055 * See if we've processed all the entries
2057 if (strlen(t->cell[slot].cellname) == 0) {
2059 *last_item_contains_data = 0;
2073 static int ListCellsFromCache(
2080 afs_status_t tst = 0;
2081 cm_list_cell_get_p cell = (cm_list_cell_get_p) rpc_specific;
2083 memcpy(dest, (const void *) &cell->cell[slot],
2084 sizeof(afs_CMListCell_t));
2094 * util_CMListCellsBegin - Begin listing cache manager CellServDB
2098 * IN conn - an rx connection to the process to be queried
2100 * OUT iterationIdP - an iteration id that can be passed to
2101 * util_CMListCellsNext to get the next cell
2105 * No locks are obtained or released by this function
2109 * Returns != 0 upon successful completion.
2113 int ADMINAPI util_CMListCellsBegin(
2114 struct rx_connection *conn,
2115 void **iterationIdP,
2119 afs_status_t tst = 0;
2120 afs_admin_iterator_p iter;
2121 cm_list_cell_get_p cell;
2124 tst = ADMRXCONNNULL;
2125 goto fail_util_CMListCellsBegin;
2128 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2131 goto fail_util_CMListCellsBegin;
2134 cell = (cm_list_cell_get_p) malloc(sizeof(cm_list_cell_get_t));
2138 goto fail_util_CMListCellsBegin;
2143 if (!IteratorInit(iter, (void *) cell, ListCellsRPC,
2144 ListCellsFromCache, NULL, NULL, &tst)) {
2147 goto fail_util_CMListCellsBegin;
2149 *iterationIdP = (void *) iter;
2152 fail_util_CMListCellsBegin:
2161 * util_CMListCellsNext - Get next entry in cache manager cells
2165 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2167 * OUT cell - Next entry in cache manager cells.
2171 * No locks are obtained or released by this function
2175 * Returns != 0 upon successful completion.
2179 int ADMINAPI util_CMListCellsNext(
2180 const void *iterationId,
2181 afs_CMListCell_p cell,
2185 afs_status_t tst = 0;
2186 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2188 if (iterationId == NULL) {
2189 tst = ADMITERATIONIDPNULL;
2190 goto fail_util_CMListCellsNext;
2193 rc = IteratorNext(iter, (void *) cell, &tst);
2195 fail_util_CMListCellsNext:
2204 * util_CMListCellsDone - Finish listing cache manager cells
2208 * IN iterationId - Iteration id created by util_CMGetServerPrefsBegin.
2212 * No locks are obtained or released by this function
2216 * Returns != 0 upon successful completion.
2220 int ADMINAPI util_CMListCellsDone(
2221 const void *iterationId,
2225 afs_status_t tst = 0;
2226 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2228 if (iterationId == NULL) {
2229 tst = ADMITERATIONIDPNULL;
2230 goto fail_util_CMListCellsDone;
2233 rc = IteratorDone(iter, &tst);
2236 fail_util_CMListCellsDone:
2245 * util_CMLocalCell - Get the name of the cache manager's local cell.
2249 * IN conn - an rx connection to the process to be queried
2251 * OUT cellName - the name of the cache manager's local cell.
2255 * No locks are obtained or released by this function
2259 * Returns != 0 upon successful completion.
2263 int ADMINAPI util_CMLocalCell(
2264 struct rx_connection *conn,
2265 afs_CMCellName_p cellName,
2269 afs_status_t tst = 0;
2270 afs_CMCellName_p name;
2273 tst = ADMRXCONNNULL;
2274 goto fail_util_CMLocalCell;
2277 if (cellName == NULL) {
2278 tst = ADMCLIENTCMCELLNAMENULL;
2279 goto fail_util_CMLocalCell;
2283 tst = RXAFSCB_GetLocalCell(conn, &name);
2289 fail_util_CMLocalCell:
2297 static void UnmarshallCMClientConfig(
2298 afs_uint32 serverVersion,
2300 afs_ClientConfigUnion_p config)
2303 * We currently only support version 1.
2305 config->config_v1.nChunkFiles = *(ptr++);
2306 config->config_v1.nStatCaches = *(ptr++);
2307 config->config_v1.nDataCaches = *(ptr++);
2308 config->config_v1.nVolumeCaches = *(ptr++);
2309 config->config_v1.firstChunkSize = *(ptr++);
2310 config->config_v1.otherChunkSize = *(ptr++);
2311 config->config_v1.cacheSize = *(ptr++);
2312 config->config_v1.setTime = *(ptr++);
2313 config->config_v1.memCache = *(ptr++);
2317 * util_CMClientConfig - Get the cache manager's configuration parameters.
2321 * IN conn - an rx connection to the process to be queried
2323 * OUT config - the cache manager's configuration parameters.
2327 * No locks are obtained or released by this function
2331 * Returns != 0 upon successful completion.
2335 int ADMINAPI util_CMClientConfig(
2336 struct rx_connection *conn,
2337 afs_ClientConfig_p config,
2341 afs_status_t tst = 0;
2342 afs_int32 allocbytes;
2343 struct cacheConfig tconfig;
2346 tst = ADMRXCONNNULL;
2347 goto fail_util_CMClientConfig;
2350 if (config == NULL) {
2351 tst = ADMCLIENTCMCELLNAMENULL;
2352 goto fail_util_CMClientConfig;
2355 config->clientVersion = AFS_CLIENT_RETRIEVAL_VERSION;
2356 tconfig.cacheConfig_val = NULL;
2357 tconfig.cacheConfig_len = 0;
2358 tst = RXAFSCB_GetCacheConfig(conn,
2359 config->clientVersion,
2360 &config->serverVersion,
2365 goto fail_util_CMClientConfig;
2368 UnmarshallCMClientConfig(config->serverVersion,
2369 tconfig.cacheConfig_val,
2372 free(tconfig.cacheConfig_val);
2374 fail_util_CMClientConfig:
2383 * util_RXDebugVersion - Get the rxdebug version string.
2387 * IN handle - an rxdebug handle for the process to be queried.
2389 * OUT version - the rxdebug version string.
2393 * No locks are obtained or released by this function
2397 * Returns != 0 upon successful completion.
2401 int ADMINAPI util_RXDebugVersion(
2402 rxdebugHandle_p handle,
2403 rxdebugVersion_p version,
2407 afs_status_t tst = 0;
2410 if (handle == NULL) {
2411 tst = ADMRXDEBUGHANDLENULL;
2412 goto fail_util_RXDebugVersion;
2415 if (version == NULL) {
2416 tst = ADMRXDEBUGVERSIONNULL;
2417 goto fail_util_RXDebugVersion;
2420 code = rx_GetServerVersion(handle->sock,
2423 UTIL_MAX_RXDEBUG_VERSION_LEN,
2426 tst = ADMCLIENTRXDEBUGTIMEOUT;
2427 goto fail_util_RXDebugVersion;
2432 fail_util_RXDebugVersion:
2441 * util_RXDebugSupportedStats - Get the rxdebug statistics supported by
2446 * IN handle - an rxdebug handle for the process to be queried.
2448 * OUT supportedStats - bit mask with supported rxstats.
2452 * No locks are obtained or released by this function
2456 * Returns != 0 upon successful completion.
2460 int ADMINAPI util_RXDebugSupportedStats(
2461 rxdebugHandle_p handle,
2462 afs_uint32 *supportedStats,
2466 afs_status_t tst = 0;
2467 struct rx_debugStats tstats;
2469 if (handle == NULL) {
2470 tst = ADMRXDEBUGHANDLENULL;
2471 goto fail_util_RXDebugSupportedStats;
2474 if (supportedStats == NULL) {
2475 tst = ADMRXDEBUGSTATSNULL;
2476 goto fail_util_RXDebugSupportedStats;
2479 if (handle->firstFlag) {
2480 rc = util_RXDebugBasicStats(handle, &tstats, &tst);
2482 goto fail_util_RXDebugSupportedStats;
2486 *supportedStats = handle->supportedStats;
2489 fail_util_RXDebugSupportedStats:
2499 * util_RXDebugBasicStats - Get the basic rxdebug statistics for the process.
2503 * IN handle - an rxdebug handle for the process to be queried.
2505 * OUT stats - Basic rxdebug statistics for the process.
2509 * No locks are obtained or released by this function
2513 * Returns != 0 upon successful completion.
2517 int ADMINAPI util_RXDebugBasicStats(
2518 rxdebugHandle_p handle,
2519 struct rx_debugStats *stats,
2523 afs_status_t tst = 0;
2526 if (handle == NULL) {
2527 tst = ADMRXDEBUGHANDLENULL;
2528 goto fail_util_RXDebugBasicStats;
2531 if (stats == NULL) {
2532 tst = ADMRXDEBUGSTATSNULL;
2533 goto fail_util_RXDebugBasicStats;
2536 code = rx_GetServerDebug(handle->sock,
2540 &handle->supportedStats);
2542 tst = ADMCLIENTRXDEBUGTIMEOUT;
2543 goto fail_util_RXDebugBasicStats;
2546 handle->firstFlag = 0;
2549 fail_util_RXDebugBasicStats:
2559 * util_RXDebugRxStats - Get the detailed rxdebug statistics for the process.
2563 * IN handle - an rxdebug handle for the process to be queried.
2565 * OUT stats - Detailed rxdebug statistics for the process.
2569 * No locks are obtained or released by this function
2573 * Returns != 0 upon successful completion.
2577 int ADMINAPI util_RXDebugRxStats(
2578 rxdebugHandle_p handle,
2579 struct rx_stats *stats,
2580 afs_uint32 *supportedValues,
2585 afs_status_t tst = 0;
2587 afs_uint32 tsupported;
2589 if (handle == NULL) {
2590 tst = ADMRXDEBUGHANDLENULL;
2591 goto fail_util_RXDebugRxStats;
2594 if (supportedValues == NULL) {
2595 tst = ADMRXDEBUGSTATSNULL;
2596 goto fail_util_RXDebugRxStats;
2599 if (stats == NULL) {
2600 tst = ADMRXDEBUGSTATSNULL;
2601 goto fail_util_RXDebugRxStats;
2604 if (handle->firstFlag) {
2605 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2608 goto fail_util_RXDebugRxStats;
2612 if (!(handle->supportedStats & RX_SERVER_DEBUG_RX_STATS)) {
2613 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2614 goto fail_util_RXDebugRxStats;
2617 code = rx_GetServerStats(handle->sock,
2621 &handle->supportedStats);
2623 tst = ADMCLIENTRXDEBUGTIMEOUT;
2624 goto fail_util_RXDebugRxStats;
2629 fail_util_RXDebugRxStats:
2638 * The iterator for listing RXDebug connections
2641 typedef struct rxdebug_conn_item {
2642 struct rx_debugConn conn;
2643 afs_uint32 supportedValues;
2644 } rxdebug_conn_item_t, *rxdebug_conn_item_p;
2646 typedef struct rxdebug_conn_get {
2648 rxdebugHandle_p handle;
2650 rxdebug_conn_item_t items[CACHED_ITEMS];
2651 } rxdebug_conn_get_t, *rxdebug_conn_get_p;
2653 static int RXDebugConnsFromServer(
2657 int *last_item_contains_data,
2662 afs_status_t tst = 0;
2663 rxdebug_conn_get_p t = (rxdebug_conn_get_p) rpc_specific;
2666 * Get the next entry the list of connections
2668 code = rx_GetServerConnections(t->handle->sock,
2673 t->handle->supportedStats,
2674 &t->items[slot].conn,
2675 &t->items[slot].supportedValues);
2677 tst = ADMCLIENTRXDEBUGTIMEOUT;
2678 goto fail_ListCellsRPC;
2682 * See if we've processed all the entries
2684 if (t->items[slot].conn.cid == 0xffffffff) {
2686 *last_item_contains_data = 0;
2698 static int RXDebugConnsFromCache(
2705 afs_status_t tst = 0;
2706 rxdebug_conn_get_p t = (rxdebug_conn_get_p)rpc_specific;
2708 memcpy(dest, (const void *)&t->items[slot],
2709 sizeof(rxdebug_conn_item_t));
2719 * util_RXDebugConnectionsBegin - Begin listing rxdebug connection information
2724 * IN handle - an rxdebug handle for the process to be queried
2726 * IN allcons - non-zero to list all connections. If zero, only
2727 * "interesting" connections will be listed.
2729 * OUT iterationIdP - an iteration id that can be passed to
2730 * util_RXDebugConnectionsNext.
2734 * No locks are obtained or released by this function
2738 * Returns != 0 upon successful completion.
2742 int ADMINAPI util_RXDebugConnectionsBegin(
2743 rxdebugHandle_p handle,
2745 void **iterationIdP,
2750 afs_uint32 tsupported;
2751 afs_status_t tst = 0;
2752 afs_admin_iterator_p iter;
2753 rxdebug_conn_get_p t;
2755 if (handle == NULL) {
2756 tst = ADMRXDEBUGHANDLENULL;
2757 goto fail_util_RXDebugConnectionsBegin;
2760 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
2763 goto fail_util_RXDebugConnectionsBegin;
2766 if (handle->firstFlag) {
2767 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
2770 goto fail_util_RXDebugConnectionsBegin;
2775 !(handle->supportedStats & RX_SERVER_DEBUG_ALL_CONN)) {
2776 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
2777 goto fail_util_RXDebugConnectionsBegin;
2780 t = (rxdebug_conn_get_p) malloc(sizeof(rxdebug_conn_get_t));
2784 goto fail_util_RXDebugConnectionsBegin;
2787 t->allconns = allconns;
2790 if (!IteratorInit(iter, (void *)t, RXDebugConnsFromServer,
2791 RXDebugConnsFromCache, NULL, NULL, &tst)) {
2792 goto fail_util_RXDebugConnectionsBegin;
2794 *iterationIdP = (void *) iter;
2797 fail_util_RXDebugConnectionsBegin:
2807 * util_RXDebugConnectionsNext - Get rxdebug information for the next
2812 * IN iterationId - Iteration id created by util_RXDebugConnectionsNext.
2814 * OUT conn - Rxdebug information for the next connection.
2816 * OUT supportedValues - Bit mask of supported rxdebug values.
2820 * No locks are obtained or released by this function
2824 * Returns != 0 upon successful completion.
2828 int ADMINAPI util_RXDebugConnectionsNext(
2829 const void *iterationId,
2830 struct rx_debugConn *conn,
2831 afs_uint32 *supportedValues,
2835 afs_status_t tst = 0;
2836 rxdebug_conn_item_t item;
2837 afs_admin_iterator_p iter = (afs_admin_iterator_p)iterationId;
2839 if (iterationId == NULL) {
2840 tst = ADMITERATIONIDPNULL;
2841 goto fail_util_RXDebugConnectionsNext;
2845 tst = ADMRXDEBUGHANDLENULL;
2846 goto fail_util_RXDebugConnectionsNext;
2849 if (supportedValues == NULL) {
2850 tst = ADMRXDEBUGHANDLENULL;
2851 goto fail_util_RXDebugConnectionsNext;
2854 rc = IteratorNext(iter, (void *)&item, &tst);
2856 goto fail_util_RXDebugConnectionsNext;
2860 *supportedValues = item.supportedValues;
2862 fail_util_RXDebugConnectionsNext:
2872 * util_RXDebugConnectionsDone - Finish listing rxdebug connection information.
2876 * IN iterationId - Iteration id created by util_RXDebugConnectionsBegin.
2880 * No locks are obtained or released by this function
2884 * Returns != 0 upon successful completion.
2888 int ADMINAPI util_RXDebugConnectionsDone(
2889 const void *iterationId,
2893 afs_status_t tst = 0;
2894 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2897 * Validate parameters
2901 tst = ADMITERATORNULL;
2902 goto fail_util_RXDebugConnectionsDone;
2905 rc = IteratorDone(iter, &tst);
2907 fail_util_RXDebugConnectionsDone:
2917 * The iterator for listing RXDebug peer
2920 typedef struct rxdebug_peer_item {
2921 struct rx_debugPeer peer;
2922 afs_uint32 supportedValues;
2923 } rxdebug_peer_item_t, *rxdebug_peer_item_p;
2925 typedef struct rxdebug_peer_get {
2926 rxdebugHandle_p handle;
2928 rxdebug_peer_item_t items[CACHED_ITEMS];
2929 } rxdebug_peer_get_t, *rxdebug_peer_get_p;
2931 static int RXDebugPeersFromServer(
2935 int *last_item_contains_data,
2940 afs_status_t tst = 0;
2941 rxdebug_peer_get_p t = (rxdebug_peer_get_p) rpc_specific;
2944 * Get the next entry the list of peers
2946 code = rx_GetServerPeers(t->handle->sock,
2950 t->handle->supportedStats,
2951 &t->items[slot].peer,
2952 &t->items[slot].supportedValues);
2954 tst = ADMCLIENTRXDEBUGTIMEOUT;
2955 goto fail_ListCellsRPC;
2959 * See if we've processed all the entries
2961 if (t->items[slot].peer.host == 0xffffffff) {
2963 *last_item_contains_data = 0;
2975 static int RXDebugPeersFromCache(
2982 afs_status_t tst = 0;
2983 rxdebug_peer_get_p t = (rxdebug_peer_get_p)rpc_specific;
2985 memcpy(dest, (const void *)&t->items[slot],
2986 sizeof(rxdebug_peer_item_t));
2997 * util_RXDebugPeersBegin - Begin listing rxdebug peer information for
3002 * IN handle - an rxdebug handle for the process to be queried
3004 * OUT iterationIdP - an iteration id that can be passed to
3005 * util_RXDebugPeersNext.
3009 * No locks are obtained or released by this function
3013 * Returns != 0 upon successful completion.
3017 int ADMINAPI util_RXDebugPeersBegin(
3018 rxdebugHandle_p handle,
3019 void **iterationIdP,
3024 afs_uint32 tsupported;
3025 afs_status_t tst = 0;
3026 afs_admin_iterator_p iter;
3027 rxdebug_peer_get_p t;
3029 if (handle == NULL) {
3030 tst = ADMRXDEBUGHANDLENULL;
3031 goto fail_util_RXDebugPeersBegin;
3034 iter = (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
3037 goto fail_util_RXDebugPeersBegin;
3040 if (handle->firstFlag) {
3041 trc = util_RXDebugSupportedStats(handle, &tsupported, &tst);
3044 goto fail_util_RXDebugPeersBegin;
3048 if(!(handle->supportedStats & RX_SERVER_DEBUG_ALL_PEER)) {
3049 tst = ADMCLIENTRXDEBUGNOTSUPPORTED;
3050 goto fail_util_RXDebugPeersBegin;
3053 t = (rxdebug_peer_get_p) malloc(sizeof(rxdebug_peer_get_t));
3057 goto fail_util_RXDebugPeersBegin;
3062 if (!IteratorInit(iter, (void *)t, RXDebugPeersFromServer,
3063 RXDebugPeersFromCache, NULL, NULL, &tst)) {
3064 goto fail_util_RXDebugPeersBegin;
3066 *iterationIdP = (void *) iter;
3069 fail_util_RXDebugPeersBegin:
3078 * util_RXDebugPeersNext - Get rxdebug information for the next peer.
3082 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3084 * OUT peer - Rxdebug information for the next peer.
3086 * OUT supportedValues - Bit mask of supported rxdebug values.
3090 * No locks are obtained or released by this function
3094 * Returns != 0 upon successful completion.
3097 int ADMINAPI util_RXDebugPeersNext(
3098 const void *iterationId,
3099 struct rx_debugPeer *peer,
3100 afs_uint32 *supportedValues,
3104 afs_status_t tst = 0;
3105 rxdebug_peer_item_t item;
3106 afs_admin_iterator_p iter = (afs_admin_iterator_p)iterationId;
3108 if (iterationId == NULL) {
3109 tst = ADMITERATIONIDPNULL;
3110 goto fail_util_RXDebugPeersNext;
3114 tst = ADMRXDEBUGHANDLENULL;
3115 goto fail_util_RXDebugPeersNext;
3118 if (supportedValues == NULL) {
3119 tst = ADMRXDEBUGHANDLENULL;
3120 goto fail_util_RXDebugPeersNext;
3123 rc = IteratorNext(iter, (void *)&item, &tst);
3125 goto fail_util_RXDebugPeersNext;
3129 *supportedValues = item.supportedValues;
3131 fail_util_RXDebugPeersNext:
3140 * util_RXDebugPeersDone - Finish listing rxdebug peer information.
3144 * IN iterationId - Iteration id created by util_RXDebugPeersBegin.
3148 * No locks are obtained or released by this function
3152 * Returns != 0 upon successful completion.
3156 int ADMINAPI util_RXDebugPeersDone(
3157 const void *iterationId,
3161 afs_status_t tst = 0;
3162 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
3165 * Validate parameters
3169 tst = ADMITERATORNULL;
3170 goto fail_util_RXDebugPeersDone;
3173 rc = IteratorDone(iter, &tst);
3175 fail_util_RXDebugPeersDone: