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 /* This file implements configuration functions in the following categories:
11 * cfg_CellServDb*() - manage the cell-wide server CellServDb database.
14 #include <afsconfig.h>
15 #include <afs/param.h>
29 #include <rx/rxstat.h>
31 #include <afs/afs_Admin.h>
32 #include <afs/afs_AdminErrors.h>
33 #include <afs/afs_bosAdmin.h>
34 #include <afs/afs_clientAdmin.h>
35 #include <afs/afs_utilAdmin.h>
37 #include <afs/cellconfig.h>
38 #include <afs/bnode.h>
40 #include "cfginternal.h"
41 #include "afs_cfgAdmin.h"
44 /* Local declarations and definitions */
46 #define CSDB_OP_ADD 0 /* add a server CellServDB entry */
47 #define CSDB_OP_REM 1 /* remove a server CellServDB entry */
49 #define CSDB_WAIT 0 /* wait to begin CellServDB update operations */
50 #define CSDB_GO 1 /* begin CellServDB update operations */
51 #define CSDB_ABORT 2 /* abort CellServDB update operations */
53 #define SERVER_NAME_BLOCK_SIZE 20 /* number of server names in a block */
56 /* server name iterator */
58 int dbOnly; /* enumerate database servers only */
59 void *iterationId; /* underlying iteration handle */
60 } cfg_server_iteration_t;
63 /* CellServDB update control block */
65 /* control block invariants */
66 cfg_host_p cfg_host; /* host configuration handle */
67 int op; /* CellServDB update operation type */
68 char opHostAlias[MAXHOSTCHARS]; /* CellServDB alias for config host */
69 cfg_cellServDbUpdateCallBack_t callBack; /* CellServDB update callback */
70 void *callBackId; /* CellServDB update callback cookie */
72 /* control block synchronization objects */
73 pthread_cond_t event; /* disposition change event */
74 pthread_mutex_t mutex; /* protects disposition and workersActive */
75 int disposition; /* wait, go, or abort operation */
76 int workersActive; /* count of active worker threads */
77 } cfg_csdb_update_ctrl_t;
79 /* CellServDB update name block */
81 cfg_csdb_update_ctrl_t *ctrl; /* pointer to common control block */
82 int serverCount; /* number of entries in serverName array */
83 char serverName[SERVER_NAME_BLOCK_SIZE][AFS_MAX_SERVER_NAME_LEN];
84 } cfg_csdb_update_name_t;
86 /* name block iterator */
88 void *serverIter; /* server name iterator */
89 cfg_csdb_update_ctrl_t *ctrlBlockp; /* update control block */
90 const char *cfgHost; /* configuration host name */
91 const char *sysControlHost; /* system control host name (if any) */
92 short cfgInBlock; /* configuration host in a name block */
93 short sysInBlock; /* system control host in a name block */
94 short serverIterDone; /* server name enumeration complete */
95 } cfg_csdb_nameblock_iteration_t;
100 CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost,
101 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId,
102 int *maxUpdates, afs_status_p st);
105 StartUpdateWorkerThread(cfg_csdb_update_name_t * nameBlockp,
108 static void *UpdateWorkerThread(void *argp);
111 CfgHostGetCellServDbAlias(cfg_host_p cfg_host, char *cfgHostAlias,
115 NameBlockGetBegin(cfg_host_p cfg_host, const char *sysControlHost,
116 cfg_csdb_update_ctrl_t * ctrlBlockp, void **iterationIdP,
120 NameBlockGetNext(void *iterationId, cfg_csdb_update_name_t * nameBlockp,
124 NameBlockGetDone(void *iterationId, afs_status_p st);
127 ServerNameGetBegin(cfg_host_p cfg_host, short dbOnly, void **iterationIdP,
131 ServerNameGetNext(void *iterationId, char *serverName, afs_status_p st);
134 ServerNameGetDone(void *iterationId, afs_status_p st);
138 /* ---------------- Exported CellServDB functions ------------------ */
142 * cfg_cellServDbUpdateCallBack_t -- prototype for status callback that is
143 * invoked by functions that update the CellServDB.
145 * Implementation provided by library user.
148 * callBackId - user-supplied context identifier; used by caller to
149 * distinguish results from different functions (or different
150 * invocations of the same function) that utilize the same callback.
152 * statusItemP - pointer to status information returned by a function
153 * via this callback; an statusItemP value of NULL indicates
154 * termination of status callbacks for a given function invocation;
155 * the termination callback will not occur until all other callbacks
156 * in the set have completed.
158 * status - if statusItemP is NULL then this argument indicates whether
159 * termination of status callbacks is due to logical completion
163 * The callback thread is not permitted to reenter the configuration
164 * library except to deallocate returned storage.
169 * cfg_CellServDbAddHost() -- Add host being configured to server
170 * CellServDB on all fileserver and database machines in cell and to
171 * host's server CellServDB.
173 * If a System Control machine has been configured, sysControlHost must
174 * specify the host name; otherwise, sysControlHost must be NULL.
177 cfg_CellServDbAddHost(void *hostHandle, /* host config handle */
178 const char *sysControlHost, /* sys control host */
179 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId, int *maxUpdates, /* max servers to update */
181 { /* completion status */
182 return CellServDbUpdate(CSDB_OP_ADD, hostHandle, sysControlHost, callBack,
183 callBackId, maxUpdates, st);
188 * cfg_CellServDbRemoveHost() -- Remove host being configured from server
189 * CellServDB on all fileserver and database machines in cell and from
190 * host's server CellServDB.
192 * If a System Control machine has been configured, sysControlHost must
193 * specify the host name; otherwise, sysControlHost must be NULL.
196 cfg_CellServDbRemoveHost(void *hostHandle, /* host config handle */
197 const char *sysControlHost, /* sys control host */
198 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId, int *maxUpdates, /* max servers to update */
200 { /* completion status */
201 return CellServDbUpdate(CSDB_OP_REM, hostHandle, sysControlHost, callBack,
202 callBackId, maxUpdates, st);
207 * cfg_CellServDbEnumerate() -- Enumerate database machines known to the
208 * specified database or fileserver machine. Enumeration is returned
212 cfg_CellServDbEnumerate(const char *fsDbHost, /* fileserver or database host */
213 char **cellName, /* cell name for cellDbHosts */
214 char **cellDbHosts, /* cell database hosts */
216 { /* completion status */
218 afs_status_t tst2, tst = 0;
220 /* validate parameters */
222 if (fsDbHost == NULL || *fsDbHost == '\0') {
223 tst = ADMCFGHOSTNAMENULL;
224 } else if (cellName == NULL) {
225 tst = ADMCFGCELLNAMENULL;
226 } else if (cellDbHosts == NULL) {
227 tst = ADMCFGCELLDBHOSTSNULL;
230 /* enumerate server CellServDB on specified host, along with cell name */
235 char dbhostName[MAXHOSTSPERCELL][BOS_MAX_NAME_LEN];
236 char dbhostCell[BOS_MAX_NAME_LEN];
239 if (!afsclient_NullCellOpen(&cellHandle, &tst2)) {
242 if (!bos_ServerOpen(cellHandle, fsDbHost, &bosHandle, &tst2)) {
247 if (!bos_HostGetBegin(bosHandle, &dbIter, &tst2)) {
250 for (dbhostCount = 0;; dbhostCount++) {
251 char dbhostNameTemp[BOS_MAX_NAME_LEN];
253 if (!bos_HostGetNext(dbIter, dbhostNameTemp, &tst2)) {
254 /* no more entries (or failure) */
255 if (tst2 != ADMITERATORDONE) {
259 } else if (dbhostCount >= MAXHOSTSPERCELL) {
260 /* more entries than expected */
261 tst = ADMCFGCELLSERVDBTOOMANYENTRIES;
264 strcpy(dbhostName[dbhostCount], dbhostNameTemp);
268 if (!bos_HostGetDone(dbIter, &tst2)) {
273 /* got database servers; now get cell name */
274 if (!bos_CellGet(bosHandle, dbhostCell, &tst2)) {
280 if (!bos_ServerClose(bosHandle, &tst2)) {
285 if (!afsclient_CellClose(cellHandle, &tst2)) {
291 /* return database hosts to caller */
295 for (i = 0; i < dbhostCount; i++) {
296 bufSize += strlen(dbhostName[i]) + 1;
298 bufSize++; /* end multistring */
300 *cellDbHosts = (char *)malloc(bufSize);
302 if (*cellDbHosts == NULL) {
305 char *bufp = *cellDbHosts;
307 for (i = 0; i < dbhostCount; i++) {
308 strcpy(bufp, dbhostName[i]);
309 bufp += strlen(bufp) + 1;
314 /* return cell name to caller */
316 *cellName = (char *)malloc(strlen(dbhostCell) + 1);
318 if (*cellName == NULL) {
323 strcpy(*cellName, dbhostCell);
330 /* indicate failure */
341 /* ---------------- Exported Utility functions ------------------ */
345 * cfg_CellServDbStatusDeallocate() -- Deallocate CellServDB update status
346 * record returned by library.
349 cfg_CellServDbStatusDeallocate(cfg_cellServDbStatus_t * statusItempP,
353 free((void *)statusItempP);
365 /* ---------------- Local functions ------------------ */
369 * CellServDbUpdate() -- add or remove a server CellServDB entry.
371 * Common function implementing cfg_CellServDb{Add/Remove}Host().
374 CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost,
375 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId,
376 int *maxUpdates, afs_status_p st)
379 afs_status_t tst2, tst = 0;
380 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
381 char fullSysHostName[MAXHOSTCHARS];
383 /* validate parameters */
385 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
387 } else if (sysControlHost != NULL && *sysControlHost == '\0') {
388 tst = ADMCFGHOSTNAMENULL;
389 } else if (callBack == NULL) {
390 tst = ADMCFGCALLBACKNULL;
391 } else if (maxUpdates == NULL) {
392 tst = ADMCFGUPDATECOUNTNULL;
395 /* resolve sys ctrl host to fully qualified name (if extant) */
398 if (sysControlHost != NULL) {
399 if (!cfgutil_HostNameGetFull
400 (sysControlHost, fullSysHostName, &tst2)) {
403 sysControlHost = fullSysHostName;
408 /* Update cell-wide server CellServDb as follows:
410 * 1) If system control machine is in use then update the following:
411 * system control host + database server hosts + configuration host
413 * Updating the system control machine is theoretically sufficient,
414 * as all server hosts should be getting configuration information
415 * from there. However, we don't want to have to delay further
416 * configuration until this update occurs (which could be set for
417 * any time interval). Therefore, we compromise by manually
418 * updating the database server hosts and the host being configured.
420 * 2) If no system control machine is in use then update the following:
421 * fileserver hosts + database server hosts + configuration host
424 * We create a set of server name blocks, with one thread per name
425 * block that is responsible for updating the servers in that block.
426 * All server name blocks share a single control block that stores
427 * common data and coordinates start/abort and cleanup activities.
428 * All threads wait for the start/abort signal before performing
429 * update operations so that this function is atomic.
433 cfg_csdb_update_ctrl_t *ctrlBlockp = NULL;
437 /* create control block */
439 ctrlBlockp = (cfg_csdb_update_ctrl_t *) malloc(sizeof(*ctrlBlockp));
441 if (ctrlBlockp == NULL) {
444 ctrlBlockp->cfg_host = cfg_host;
445 ctrlBlockp->op = updateOp;
446 ctrlBlockp->callBack = callBack;
447 ctrlBlockp->callBackId = callBackId;
448 ctrlBlockp->disposition = CSDB_WAIT;
449 ctrlBlockp->workersActive = 0;
451 if (pthread_mutex_init(&ctrlBlockp->mutex, NULL)) {
453 } else if (pthread_cond_init(&ctrlBlockp->event, NULL)) {
456 /* Unfortunately the bosserver adds/removes entries from
457 * the server CellServDB based on a case-sensitive string
458 * comparison, rather than using an address comparison
459 * to handle aliasing. So we must use the name for the
460 * configuration host exactly as listed in the CellServDB.
462 * Of course the 3.5 bosserver can and should be modified to
463 * handle aliases, but we still have to deal with down-level
464 * servers in this library.
466 * To get reasonable performance, the presumption is made
467 * that all server CellServDB are identical. This way we
468 * can look up the configuration host alias once and use
469 * it everywhere. If this proves to be insufficient then
470 * this lookup will have to be done for every server to be
471 * updated which will be very costly; such individual lookups
472 * would naturally be handled by the update worker threads.
474 * A final presumption is that we can just look at the
475 * server CellServDB on the current database servers to
476 * get the configuration host alias. The only time this
477 * might get us into trouble is in a re-do scenario.
479 if (!CfgHostGetCellServDbAlias
480 (cfg_host, ctrlBlockp->opHostAlias, &tst2)) {
482 } else if (*ctrlBlockp->opHostAlias == '\0') {
483 /* no alias found; go with config host working name */
484 strcpy(ctrlBlockp->opHostAlias, cfg_host->hostName);
491 /* fill name blocks, handing each to a worker thread */
492 void *nameBlockIter = NULL;
493 short workersStarted = 0;
495 if (!NameBlockGetBegin
496 (cfg_host, sysControlHost, ctrlBlockp, &nameBlockIter,
500 cfg_csdb_update_name_t *nameBlockp = NULL;
501 short nameBlockDone = 0;
503 while (!nameBlockDone) {
504 nameBlockp = ((cfg_csdb_update_name_t *)
505 malloc(sizeof(*nameBlockp)));
507 if (nameBlockp == NULL) {
512 if (!NameBlockGetNext
513 (nameBlockIter, nameBlockp, &tst2)) {
514 /* no more entries (or failure) */
515 if (tst2 != ADMITERATORDONE) {
522 *maxUpdates += nameBlockp->serverCount;
524 if (StartUpdateWorkerThread(nameBlockp, &tst2)) {
525 /* increment worker count; lock not required
526 * until workers given start/abort signal.
528 ctrlBlockp->workersActive++;
538 if (!NameBlockGetDone(nameBlockIter, &tst2)) {
543 if (workersStarted) {
544 /* worker threads started; set disposition and signal */
545 if (pthread_mutex_lock(&ctrlBlockp->mutex)) {
549 /* tell workers to proceed with updates */
550 ctrlBlockp->disposition = CSDB_GO;
552 /* tell workers to abort */
553 ctrlBlockp->disposition = CSDB_ABORT;
556 if (pthread_mutex_unlock(&ctrlBlockp->mutex)) {
557 tst = ADMMUTEXUNLOCK;
559 if (pthread_cond_broadcast(&ctrlBlockp->event)) {
564 /* no worker threads started */
572 /* indicate failure */
583 * StartUpdateWorkerThread() -- start an update worker thread for the
584 * given server name block
586 * RETURN CODES: 1 success, 0 failure (st indicates why)
589 StartUpdateWorkerThread(cfg_csdb_update_name_t * nameBlockp, afs_status_p st)
592 afs_status_t tst = 0;
593 pthread_attr_t tattr;
596 if (pthread_attr_init(&tattr)) {
597 tst = ADMTHREADATTRINIT;
599 } else if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED)) {
600 tst = ADMTHREADATTRSETDETACHSTATE;
604 (&tid, &tattr, UpdateWorkerThread, (void *)nameBlockp)) {
605 tst = ADMTHREADCREATE;
609 /* indicate failure */
620 * UpdateWorkerThread() -- thread for updating CellServDB of servers in
621 * a single name block.
624 UpdateWorkerThread(void *argp)
626 afs_status_t sync_tst = 0;
627 cfg_csdb_update_name_t *nameBlockp = (cfg_csdb_update_name_t *) argp;
630 /* Pthread mutex and condition variable functions should never fail,
631 * but if they do make a best effort attempt to report the problem;
632 * will not be able to avoid race conditions in the face of such failures.
635 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
636 sync_tst = ADMMUTEXLOCK;
639 while ((opDisposition = nameBlockp->ctrl->disposition) == CSDB_WAIT) {
640 /* wait for start/abort signal */
641 if (pthread_cond_wait
642 (&nameBlockp->ctrl->event, &nameBlockp->ctrl->mutex)) {
643 /* avoid tight loop if condition variable wait fails */
648 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
649 sync_tst = ADMMUTEXUNLOCK;
652 if (opDisposition == CSDB_GO) {
653 /* proceed with CellServDB update */
656 for (i = 0; i < nameBlockp->serverCount; i++) {
657 cfg_cellServDbStatus_t *statusp;
659 /* alloc memory for status information (including host name) */
661 while ((statusp = (cfg_cellServDbStatus_t *)
662 malloc(sizeof(*statusp) + AFS_MAX_SERVER_NAME_LEN)) ==
664 /* avoid tight loop while waiting for status storage */
668 statusp->fsDbHost = ((char *)statusp + sizeof(*statusp));
670 /* make update and set status information */
672 strcpy(statusp->fsDbHost, nameBlockp->serverName[i]);
675 /* report pthread problem */
676 statusp->status = sync_tst;
678 /* attempt update and report update status */
680 afs_status_t tst2, tst = 0;
683 (nameBlockp->ctrl->cfg_host->cellHandle,
684 nameBlockp->serverName[i], &bosHandle, &tst2)) {
688 char *opHost = nameBlockp->ctrl->opHostAlias;
690 if (nameBlockp->ctrl->op == CSDB_OP_ADD) {
691 if (!bos_HostCreate(bosHandle, opHost, &tst2)) {
695 if (!bos_HostDelete(bosHandle, opHost, &tst2)) {
696 if (tst2 != BZNOENT) {
702 if (!bos_ServerClose(bosHandle, &tst2)) {
706 statusp->status = tst;
709 /* make call back to return update status */
711 (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId,
716 /* last worker makes termination call back and deallocates control block */
718 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
719 sync_tst = ADMMUTEXLOCK;
722 nameBlockp->ctrl->workersActive--;
724 if (nameBlockp->ctrl->workersActive == 0) {
725 if (opDisposition == CSDB_GO) {
726 (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId, NULL,
729 free(nameBlockp->ctrl);
732 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
733 sync_tst = ADMMUTEXUNLOCK;
736 /* all workers deallocate their own name block */
744 * CfgHostGetCellServDbAlias() -- Get alias for configuration host name
745 * as listed in the server CellServDB. If no alias is found then
746 * cfgHostAlias is set to the empty string.
748 * Note: cfgHostAlias is presumed to be a buffer of size MAXHOSTCHARS.
749 * Presumes all server CellServDB are identical.
750 * Only checks server CellServDB of database servers.
752 * RETURN CODES: 1 success, 0 failure (st indicates why)
755 CfgHostGetCellServDbAlias(cfg_host_p cfg_host, char *cfgHostAlias,
759 afs_status_t tst2, tst = 0;
762 if (!util_DatabaseServerGetBegin(cfg_host->cellName, &dbIter, &tst2)) {
765 util_databaseServerEntry_t dbhostEntry;
766 afs_status_t dbhostSt = 0;
767 short dbhostDone = 0;
768 short dbhostFound = 0;
770 while (!dbhostDone) {
771 if (!util_DatabaseServerGetNext(dbIter, &dbhostEntry, &tst2)) {
772 /* no more entries (or failure) */
773 if (tst2 != ADMITERATORDONE) {
779 if (!cfgutil_HostNameGetCellServDbAlias
780 (dbhostEntry.serverName, cfg_host->hostName, cfgHostAlias,
782 /* save failure status but keep trying */
785 } else if (*cfgHostAlias != '\0') {
792 *cfgHostAlias = '\0';
799 if (!util_DatabaseServerGetDone(dbIter, &tst2)) {
805 /* indicate failure */
816 * NameBlockGetBegin() -- initialize name block iteration
818 * RETURN CODES: 1 success, 0 failure (st indicates why)
821 NameBlockGetBegin(cfg_host_p cfg_host, const char *sysControlHost,
822 cfg_csdb_update_ctrl_t * ctrlBlockp, void **iterationIdP,
826 afs_status_t tst2, tst = 0;
827 cfg_csdb_nameblock_iteration_t *nbIterp;
829 nbIterp = (cfg_csdb_nameblock_iteration_t *) malloc(sizeof(*nbIterp));
831 if (nbIterp == NULL) {
834 short dbOnly = (sysControlHost != NULL);
836 nbIterp->ctrlBlockp = ctrlBlockp;
837 nbIterp->cfgHost = cfg_host->hostName;
838 nbIterp->sysControlHost = sysControlHost;
839 nbIterp->cfgInBlock = 0;
840 nbIterp->sysInBlock = 0;
841 nbIterp->serverIterDone = 0;
843 if (!ServerNameGetBegin
844 (cfg_host, dbOnly, &nbIterp->serverIter, &tst2)) {
849 *iterationIdP = nbIterp;
856 /* indicate failure */
867 * NameBlockGetNext() -- fill next name block
869 * RETURN CODES: 1 success, 0 failure (st indicates why)
872 NameBlockGetNext(void *iterationId, cfg_csdb_update_name_t * nameBlockp,
876 afs_status_t tst2, tst = 0;
877 cfg_csdb_nameblock_iteration_t *nbIterp;
880 nbIterp = (cfg_csdb_nameblock_iteration_t *) iterationId;
882 nameBlockp->ctrl = nbIterp->ctrlBlockp;
883 nameBlockp->serverCount = 0;
885 for (i = 0; i < SERVER_NAME_BLOCK_SIZE; i++) {
886 short nameEntered = 0;
888 if (!nbIterp->serverIterDone) {
889 if (ServerNameGetNext
890 (nbIterp->serverIter, nameBlockp->serverName[i], &tst2)) {
891 /* Got server name; check if matches cfg or sys control host.
892 * Do a simple string compare, rather than making an expensive
893 * cfgutil_HostNameIsAlias() call because it will not cause
894 * any problems to have a duplicate in the list.
898 if (!nbIterp->cfgInBlock) {
900 (nbIterp->cfgHost, nameBlockp->serverName[i])) {
901 nbIterp->cfgInBlock = 1;
905 if (!nbIterp->sysInBlock && nbIterp->sysControlHost != NULL) {
907 (nbIterp->sysControlHost,
908 nameBlockp->serverName[i])) {
909 nbIterp->sysInBlock = 1;
914 /* no more entries (or failure) */
915 if (tst2 == ADMITERATORDONE) {
916 nbIterp->serverIterDone = 1;
925 /* include config host and (possibly) sys control host */
926 if (!nbIterp->cfgInBlock) {
927 /* shouldn't be duplicate, but OK if is */
928 strcpy(nameBlockp->serverName[i], nbIterp->cfgHost);
929 nbIterp->cfgInBlock = 1;
932 } else if (!nbIterp->sysInBlock
933 && nbIterp->sysControlHost != NULL) {
934 /* shouldn't be duplicate, but OK if is */
935 strcpy(nameBlockp->serverName[i], nbIterp->sysControlHost);
936 nbIterp->sysInBlock = 1;
942 nameBlockp->serverCount++;
944 /* no more server names */
945 if (nameBlockp->serverCount == 0) {
946 tst = ADMITERATORDONE;
953 /* indicate failure */
964 * NameBlockGetDone() -- finalize name block iteration
966 * RETURN CODES: 1 success, 0 failure (st indicates why)
969 NameBlockGetDone(void *iterationId, afs_status_p st)
972 afs_status_t tst2, tst = 0;
973 cfg_csdb_nameblock_iteration_t *nbIterp;
975 nbIterp = (cfg_csdb_nameblock_iteration_t *) iterationId;
977 if (!ServerNameGetDone(nbIterp->serverIter, &tst2)) {
984 /* indicate failure */
995 * ServerNameGetBegin() -- begin database server and (optionally) fileserver
998 * RETURN CODES: 1 success, 0 failure (st indicates why)
1001 ServerNameGetBegin(cfg_host_p cfg_host, short dbOnly, void **iterationIdP,
1005 afs_status_t tst2, tst = 0;
1006 cfg_server_iteration_t *serverIterp;
1008 serverIterp = (cfg_server_iteration_t *) malloc(sizeof(*serverIterp));
1010 if (serverIterp == NULL) {
1013 serverIterp->dbOnly = dbOnly;
1016 if (!util_DatabaseServerGetBegin
1017 (cfg_host->cellName, &serverIterp->iterationId, &tst2)) {
1021 if (!afsclient_AFSServerGetBegin
1022 (cfg_host->cellHandle, &serverIterp->iterationId, &tst2)) {
1028 *iterationIdP = serverIterp;
1035 /* indicate failure */
1046 * ServerNameGetNext() -- get next server name
1048 * RETURN CODES: 1 success, 0 failure (st indicates why)
1051 ServerNameGetNext(void *iterationId, char *serverName, afs_status_p st)
1054 afs_status_t tst2, tst = 0;
1055 cfg_server_iteration_t *serverIterp;
1057 serverIterp = (cfg_server_iteration_t *) iterationId;
1059 if (serverIterp->dbOnly) {
1060 util_databaseServerEntry_t serverEntry;
1062 if (!util_DatabaseServerGetNext
1063 (serverIterp->iterationId, &serverEntry, &tst2)) {
1066 strcpy(serverName, serverEntry.serverName);
1069 afs_serverEntry_t serverEntry;
1071 if (!afsclient_AFSServerGetNext
1072 (serverIterp->iterationId, &serverEntry, &tst2)) {
1075 strcpy(serverName, serverEntry.serverName);
1080 /* indicate failure */
1091 * ServerNameGetDone() -- terminate server enumeration
1093 * RETURN CODES: 1 success, 0 failure (st indicates why)
1096 ServerNameGetDone(void *iterationId, afs_status_p st)
1099 afs_status_t tst2, tst = 0;
1100 cfg_server_iteration_t *serverIterp;
1102 serverIterp = (cfg_server_iteration_t *) iterationId;
1104 if (serverIterp->dbOnly) {
1105 if (!util_DatabaseServerGetDone(serverIterp->iterationId, &tst2)) {
1109 if (!afsclient_AFSServerGetDone(serverIterp->iterationId, &tst2)) {
1117 /* indicate failure */