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>
30 #include <rx/rxstat.h>
32 #include <afs/afs_Admin.h>
33 #include <afs/afs_AdminErrors.h>
34 #include <afs/afs_bosAdmin.h>
35 #include <afs/afs_clientAdmin.h>
36 #include <afs/afs_utilAdmin.h>
38 #include <afs/cellconfig.h>
39 #include <afs/bnode.h>
41 #include "cfginternal.h"
42 #include "afs_cfgAdmin.h"
45 /* Local declarations and definitions */
47 #define CSDB_OP_ADD 0 /* add a server CellServDB entry */
48 #define CSDB_OP_REM 1 /* remove a server CellServDB entry */
50 #define CSDB_WAIT 0 /* wait to begin CellServDB update operations */
51 #define CSDB_GO 1 /* begin CellServDB update operations */
52 #define CSDB_ABORT 2 /* abort CellServDB update operations */
54 #define SERVER_NAME_BLOCK_SIZE 20 /* number of server names in a block */
57 /* server name iterator */
59 int dbOnly; /* enumerate database servers only */
60 void *iterationId; /* underlying iteration handle */
61 } cfg_server_iteration_t;
64 /* CellServDB update control block */
66 /* control block invariants */
67 cfg_host_p cfg_host; /* host configuration handle */
68 int op; /* CellServDB update operation type */
69 char opHostAlias[MAXHOSTCHARS]; /* CellServDB alias for config host */
70 cfg_cellServDbUpdateCallBack_t callBack; /* CellServDB update callback */
71 void *callBackId; /* CellServDB update callback cookie */
73 /* control block synchronization objects */
74 pthread_cond_t event; /* disposition change event */
75 pthread_mutex_t mutex; /* protects disposition and workersActive */
76 int disposition; /* wait, go, or abort operation */
77 int workersActive; /* count of active worker threads */
78 } cfg_csdb_update_ctrl_t;
80 /* CellServDB update name block */
82 cfg_csdb_update_ctrl_t *ctrl; /* pointer to common control block */
83 int serverCount; /* number of entries in serverName array */
84 char serverName[SERVER_NAME_BLOCK_SIZE][AFS_MAX_SERVER_NAME_LEN];
85 } cfg_csdb_update_name_t;
87 /* name block iterator */
89 void *serverIter; /* server name iterator */
90 cfg_csdb_update_ctrl_t *ctrlBlockp; /* update control block */
91 const char *cfgHost; /* configuration host name */
92 const char *sysControlHost; /* system control host name (if any) */
93 short cfgInBlock; /* configuration host in a name block */
94 short sysInBlock; /* system control host in a name block */
95 short serverIterDone; /* server name enumeration complete */
96 } cfg_csdb_nameblock_iteration_t;
101 CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost,
102 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId,
103 int *maxUpdates, afs_status_p st);
106 StartUpdateWorkerThread(cfg_csdb_update_name_t * nameBlockp,
109 static void *UpdateWorkerThread(void *argp);
112 CfgHostGetCellServDbAlias(cfg_host_p cfg_host, char *cfgHostAlias,
116 NameBlockGetBegin(cfg_host_p cfg_host, const char *sysControlHost,
117 cfg_csdb_update_ctrl_t * ctrlBlockp, void **iterationIdP,
121 NameBlockGetNext(void *iterationId, cfg_csdb_update_name_t * nameBlockp,
125 NameBlockGetDone(void *iterationId, afs_status_p st);
128 ServerNameGetBegin(cfg_host_p cfg_host, short dbOnly, void **iterationIdP,
132 ServerNameGetNext(void *iterationId, char *serverName, afs_status_p st);
135 ServerNameGetDone(void *iterationId, afs_status_p st);
139 /* ---------------- Exported CellServDB functions ------------------ */
143 * cfg_cellServDbUpdateCallBack_t -- prototype for status callback that is
144 * invoked by functions that update the CellServDB.
146 * Implementation provided by library user.
149 * callBackId - user-supplied context identifier; used by caller to
150 * distinguish results from different functions (or different
151 * invocations of the same function) that utilize the same callback.
153 * statusItemP - pointer to status information returned by a function
154 * via this callback; an statusItemP value of NULL indicates
155 * termination of status callbacks for a given function invocation;
156 * the termination callback will not occur until all other callbacks
157 * in the set have completed.
159 * status - if statusItemP is NULL then this argument indicates whether
160 * termination of status callbacks is due to logical completion
164 * The callback thread is not permitted to reenter the configuration
165 * library except to deallocate returned storage.
170 * cfg_CellServDbAddHost() -- Add host being configured to server
171 * CellServDB on all fileserver and database machines in cell and to
172 * host's server CellServDB.
174 * If a System Control machine has been configured, sysControlHost must
175 * specify the host name; otherwise, sysControlHost must be NULL.
178 cfg_CellServDbAddHost(void *hostHandle, /* host config handle */
179 const char *sysControlHost, /* sys control host */
180 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId, int *maxUpdates, /* max servers to update */
182 { /* completion status */
183 return CellServDbUpdate(CSDB_OP_ADD, hostHandle, sysControlHost, callBack,
184 callBackId, maxUpdates, st);
189 * cfg_CellServDbRemoveHost() -- Remove host being configured from server
190 * CellServDB on all fileserver and database machines in cell and from
191 * host's server CellServDB.
193 * If a System Control machine has been configured, sysControlHost must
194 * specify the host name; otherwise, sysControlHost must be NULL.
197 cfg_CellServDbRemoveHost(void *hostHandle, /* host config handle */
198 const char *sysControlHost, /* sys control host */
199 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId, int *maxUpdates, /* max servers to update */
201 { /* completion status */
202 return CellServDbUpdate(CSDB_OP_REM, hostHandle, sysControlHost, callBack,
203 callBackId, maxUpdates, st);
208 * cfg_CellServDbEnumerate() -- Enumerate database machines known to the
209 * specified database or fileserver machine. Enumeration is returned
213 cfg_CellServDbEnumerate(const char *fsDbHost, /* fileserver or database host */
214 char **cellName, /* cell name for cellDbHosts */
215 char **cellDbHosts, /* cell database hosts */
217 { /* completion status */
219 afs_status_t tst2, tst = 0;
221 /* validate parameters */
223 if (fsDbHost == NULL || *fsDbHost == '\0') {
224 tst = ADMCFGHOSTNAMENULL;
225 } else if (cellName == NULL) {
226 tst = ADMCFGCELLNAMENULL;
227 } else if (cellDbHosts == NULL) {
228 tst = ADMCFGCELLDBHOSTSNULL;
231 /* enumerate server CellServDB on specified host, along with cell name */
236 char dbhostName[MAXHOSTSPERCELL][BOS_MAX_NAME_LEN];
237 char dbhostCell[BOS_MAX_NAME_LEN];
240 if (!afsclient_NullCellOpen(&cellHandle, &tst2)) {
243 if (!bos_ServerOpen(cellHandle, fsDbHost, &bosHandle, &tst2)) {
248 if (!bos_HostGetBegin(bosHandle, &dbIter, &tst2)) {
251 for (dbhostCount = 0;; dbhostCount++) {
252 char dbhostNameTemp[BOS_MAX_NAME_LEN];
254 if (!bos_HostGetNext(dbIter, dbhostNameTemp, &tst2)) {
255 /* no more entries (or failure) */
256 if (tst2 != ADMITERATORDONE) {
260 } else if (dbhostCount >= MAXHOSTSPERCELL) {
261 /* more entries than expected */
262 tst = ADMCFGCELLSERVDBTOOMANYENTRIES;
265 strcpy(dbhostName[dbhostCount], dbhostNameTemp);
269 if (!bos_HostGetDone(dbIter, &tst2)) {
274 /* got database servers; now get cell name */
275 if (!bos_CellGet(bosHandle, dbhostCell, &tst2)) {
281 if (!bos_ServerClose(bosHandle, &tst2)) {
286 if (!afsclient_CellClose(cellHandle, &tst2)) {
292 /* return database hosts to caller */
296 for (i = 0; i < dbhostCount; i++) {
297 bufSize += strlen(dbhostName[i]) + 1;
299 bufSize++; /* end multistring */
301 *cellDbHosts = (char *)malloc(bufSize);
303 if (*cellDbHosts == NULL) {
306 char *bufp = *cellDbHosts;
308 for (i = 0; i < dbhostCount; i++) {
309 strcpy(bufp, dbhostName[i]);
310 bufp += strlen(bufp) + 1;
315 /* return cell name to caller */
317 *cellName = (char *)malloc(strlen(dbhostCell) + 1);
319 if (*cellName == NULL) {
324 strcpy(*cellName, dbhostCell);
331 /* indicate failure */
342 /* ---------------- Exported Utility functions ------------------ */
346 * cfg_CellServDbStatusDeallocate() -- Deallocate CellServDB update status
347 * record returned by library.
350 cfg_CellServDbStatusDeallocate(cfg_cellServDbStatus_t * statusItempP,
354 free((void *)statusItempP);
366 /* ---------------- Local functions ------------------ */
370 * CellServDbUpdate() -- add or remove a server CellServDB entry.
372 * Common function implementing cfg_CellServDb{Add/Remove}Host().
375 CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost,
376 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId,
377 int *maxUpdates, afs_status_p st)
380 afs_status_t tst2, tst = 0;
381 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
382 char fullSysHostName[MAXHOSTCHARS];
384 /* validate parameters */
386 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
388 } else if (sysControlHost != NULL && *sysControlHost == '\0') {
389 tst = ADMCFGHOSTNAMENULL;
390 } else if (callBack == NULL) {
391 tst = ADMCFGCALLBACKNULL;
392 } else if (maxUpdates == NULL) {
393 tst = ADMCFGUPDATECOUNTNULL;
396 /* resolve sys ctrl host to fully qualified name (if extant) */
399 if (sysControlHost != NULL) {
400 if (!cfgutil_HostNameGetFull
401 (sysControlHost, fullSysHostName, &tst2)) {
404 sysControlHost = fullSysHostName;
409 /* Update cell-wide server CellServDb as follows:
411 * 1) If system control machine is in use then update the following:
412 * system control host + database server hosts + configuration host
414 * Updating the system control machine is theoretically sufficient,
415 * as all server hosts should be getting configuration information
416 * from there. However, we don't want to have to delay further
417 * configuration until this update occurs (which could be set for
418 * any time interval). Therefore, we compromise by manually
419 * updating the database server hosts and the host being configured.
421 * 2) If no system control machine is in use then update the following:
422 * fileserver hosts + database server hosts + configuration host
425 * We create a set of server name blocks, with one thread per name
426 * block that is responsible for updating the servers in that block.
427 * All server name blocks share a single control block that stores
428 * common data and coordinates start/abort and cleanup activities.
429 * All threads wait for the start/abort signal before performing
430 * update operations so that this function is atomic.
434 cfg_csdb_update_ctrl_t *ctrlBlockp = NULL;
438 /* create control block */
440 ctrlBlockp = (cfg_csdb_update_ctrl_t *) malloc(sizeof(*ctrlBlockp));
442 if (ctrlBlockp == NULL) {
445 ctrlBlockp->cfg_host = cfg_host;
446 ctrlBlockp->op = updateOp;
447 ctrlBlockp->callBack = callBack;
448 ctrlBlockp->callBackId = callBackId;
449 ctrlBlockp->disposition = CSDB_WAIT;
450 ctrlBlockp->workersActive = 0;
452 if (pthread_mutex_init(&ctrlBlockp->mutex, NULL)) {
454 } else if (pthread_cond_init(&ctrlBlockp->event, NULL)) {
457 /* Unfortunately the bosserver adds/removes entries from
458 * the server CellServDB based on a case-sensitive string
459 * comparison, rather than using an address comparison
460 * to handle aliasing. So we must use the name for the
461 * configuration host exactly as listed in the CellServDB.
463 * Of course the 3.5 bosserver can and should be modified to
464 * handle aliases, but we still have to deal with down-level
465 * servers in this library.
467 * To get reasonable performance, the presumption is made
468 * that all server CellServDB are identical. This way we
469 * can look up the configuration host alias once and use
470 * it everywhere. If this proves to be insufficient then
471 * this lookup will have to be done for every server to be
472 * updated which will be very costly; such individual lookups
473 * would naturally be handled by the update worker threads.
475 * A final presumption is that we can just look at the
476 * server CellServDB on the current database servers to
477 * get the configuration host alias. The only time this
478 * might get us into trouble is in a re-do scenario.
480 if (!CfgHostGetCellServDbAlias
481 (cfg_host, ctrlBlockp->opHostAlias, &tst2)) {
483 } else if (*ctrlBlockp->opHostAlias == '\0') {
484 /* no alias found; go with config host working name */
485 strcpy(ctrlBlockp->opHostAlias, cfg_host->hostName);
492 /* fill name blocks, handing each to a worker thread */
493 void *nameBlockIter = NULL;
494 short workersStarted = 0;
496 if (!NameBlockGetBegin
497 (cfg_host, sysControlHost, ctrlBlockp, &nameBlockIter,
501 cfg_csdb_update_name_t *nameBlockp = NULL;
502 short nameBlockDone = 0;
504 while (!nameBlockDone) {
505 nameBlockp = ((cfg_csdb_update_name_t *)
506 malloc(sizeof(*nameBlockp)));
508 if (nameBlockp == NULL) {
513 if (!NameBlockGetNext
514 (nameBlockIter, nameBlockp, &tst2)) {
515 /* no more entries (or failure) */
516 if (tst2 != ADMITERATORDONE) {
523 *maxUpdates += nameBlockp->serverCount;
525 if (StartUpdateWorkerThread(nameBlockp, &tst2)) {
526 /* increment worker count; lock not required
527 * until workers given start/abort signal.
529 ctrlBlockp->workersActive++;
539 if (!NameBlockGetDone(nameBlockIter, &tst2)) {
544 if (workersStarted) {
545 /* worker threads started; set disposition and signal */
546 if (pthread_mutex_lock(&ctrlBlockp->mutex)) {
550 /* tell workers to proceed with updates */
551 ctrlBlockp->disposition = CSDB_GO;
553 /* tell workers to abort */
554 ctrlBlockp->disposition = CSDB_ABORT;
557 if (pthread_mutex_unlock(&ctrlBlockp->mutex)) {
558 tst = ADMMUTEXUNLOCK;
560 if (pthread_cond_broadcast(&ctrlBlockp->event)) {
565 /* no worker threads started */
573 /* indicate failure */
584 * StartUpdateWorkerThread() -- start an update worker thread for the
585 * given server name block
587 * RETURN CODES: 1 success, 0 failure (st indicates why)
590 StartUpdateWorkerThread(cfg_csdb_update_name_t * nameBlockp, afs_status_p st)
593 afs_status_t tst = 0;
594 pthread_attr_t tattr;
597 if (pthread_attr_init(&tattr)) {
598 tst = ADMTHREADATTRINIT;
600 } else if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED)) {
601 tst = ADMTHREADATTRSETDETACHSTATE;
605 (&tid, &tattr, UpdateWorkerThread, (void *)nameBlockp)) {
606 tst = ADMTHREADCREATE;
610 /* indicate failure */
621 * UpdateWorkerThread() -- thread for updating CellServDB of servers in
622 * a single name block.
625 UpdateWorkerThread(void *argp)
627 afs_status_t sync_tst = 0;
628 cfg_csdb_update_name_t *nameBlockp = (cfg_csdb_update_name_t *) argp;
631 /* Pthread mutex and condition variable functions should never fail,
632 * but if they do make a best effort attempt to report the problem;
633 * will not be able to avoid race conditions in the face of such failures.
636 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
637 sync_tst = ADMMUTEXLOCK;
640 while ((opDisposition = nameBlockp->ctrl->disposition) == CSDB_WAIT) {
641 /* wait for start/abort signal */
642 if (pthread_cond_wait
643 (&nameBlockp->ctrl->event, &nameBlockp->ctrl->mutex)) {
644 /* avoid tight loop if condition variable wait fails */
649 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
650 sync_tst = ADMMUTEXUNLOCK;
653 if (opDisposition == CSDB_GO) {
654 /* proceed with CellServDB update */
657 for (i = 0; i < nameBlockp->serverCount; i++) {
658 cfg_cellServDbStatus_t *statusp;
660 /* alloc memory for status information (including host name) */
662 while ((statusp = (cfg_cellServDbStatus_t *)
663 malloc(sizeof(*statusp) + AFS_MAX_SERVER_NAME_LEN)) ==
665 /* avoid tight loop while waiting for status storage */
669 statusp->fsDbHost = ((char *)statusp + sizeof(*statusp));
671 /* make update and set status information */
673 strcpy(statusp->fsDbHost, nameBlockp->serverName[i]);
676 /* report pthread problem */
677 statusp->status = sync_tst;
679 /* attempt update and report update status */
681 afs_status_t tst2, tst = 0;
684 (nameBlockp->ctrl->cfg_host->cellHandle,
685 nameBlockp->serverName[i], &bosHandle, &tst2)) {
689 char *opHost = nameBlockp->ctrl->opHostAlias;
691 if (nameBlockp->ctrl->op == CSDB_OP_ADD) {
692 if (!bos_HostCreate(bosHandle, opHost, &tst2)) {
696 if (!bos_HostDelete(bosHandle, opHost, &tst2)) {
697 if (tst2 != BZNOENT) {
703 if (!bos_ServerClose(bosHandle, &tst2)) {
707 statusp->status = tst;
710 /* make call back to return update status */
712 (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId,
717 /* last worker makes termination call back and deallocates control block */
719 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
720 sync_tst = ADMMUTEXLOCK;
723 nameBlockp->ctrl->workersActive--;
725 if (nameBlockp->ctrl->workersActive == 0) {
726 if (opDisposition == CSDB_GO) {
727 (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId, NULL,
730 free(nameBlockp->ctrl);
733 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
734 sync_tst = ADMMUTEXUNLOCK;
737 /* all workers deallocate their own name block */
745 * CfgHostGetCellServDbAlias() -- Get alias for configuration host name
746 * as listed in the server CellServDB. If no alias is found then
747 * cfgHostAlias is set to the empty string.
749 * Note: cfgHostAlias is presumed to be a buffer of size MAXHOSTCHARS.
750 * Presumes all server CellServDB are identical.
751 * Only checks server CellServDB of database servers.
753 * RETURN CODES: 1 success, 0 failure (st indicates why)
756 CfgHostGetCellServDbAlias(cfg_host_p cfg_host, char *cfgHostAlias,
760 afs_status_t tst2, tst = 0;
763 if (!util_DatabaseServerGetBegin(cfg_host->cellName, &dbIter, &tst2)) {
766 util_databaseServerEntry_t dbhostEntry;
767 afs_status_t dbhostSt = 0;
768 short dbhostDone = 0;
769 short dbhostFound = 0;
771 while (!dbhostDone) {
772 if (!util_DatabaseServerGetNext(dbIter, &dbhostEntry, &tst2)) {
773 /* no more entries (or failure) */
774 if (tst2 != ADMITERATORDONE) {
780 if (!cfgutil_HostNameGetCellServDbAlias
781 (dbhostEntry.serverName, cfg_host->hostName, cfgHostAlias,
783 /* save failure status but keep trying */
786 } else if (*cfgHostAlias != '\0') {
793 *cfgHostAlias = '\0';
800 if (!util_DatabaseServerGetDone(dbIter, &tst2)) {
806 /* indicate failure */
817 * NameBlockGetBegin() -- initialize name block iteration
819 * RETURN CODES: 1 success, 0 failure (st indicates why)
822 NameBlockGetBegin(cfg_host_p cfg_host, const char *sysControlHost,
823 cfg_csdb_update_ctrl_t * ctrlBlockp, void **iterationIdP,
827 afs_status_t tst2, tst = 0;
828 cfg_csdb_nameblock_iteration_t *nbIterp;
830 nbIterp = (cfg_csdb_nameblock_iteration_t *) malloc(sizeof(*nbIterp));
832 if (nbIterp == NULL) {
835 short dbOnly = (sysControlHost != NULL);
837 nbIterp->ctrlBlockp = ctrlBlockp;
838 nbIterp->cfgHost = cfg_host->hostName;
839 nbIterp->sysControlHost = sysControlHost;
840 nbIterp->cfgInBlock = 0;
841 nbIterp->sysInBlock = 0;
842 nbIterp->serverIterDone = 0;
844 if (!ServerNameGetBegin
845 (cfg_host, dbOnly, &nbIterp->serverIter, &tst2)) {
850 *iterationIdP = nbIterp;
857 /* indicate failure */
868 * NameBlockGetNext() -- fill next name block
870 * RETURN CODES: 1 success, 0 failure (st indicates why)
873 NameBlockGetNext(void *iterationId, cfg_csdb_update_name_t * nameBlockp,
877 afs_status_t tst2, tst = 0;
878 cfg_csdb_nameblock_iteration_t *nbIterp;
881 nbIterp = (cfg_csdb_nameblock_iteration_t *) iterationId;
883 nameBlockp->ctrl = nbIterp->ctrlBlockp;
884 nameBlockp->serverCount = 0;
886 for (i = 0; i < SERVER_NAME_BLOCK_SIZE; i++) {
887 short nameEntered = 0;
889 if (!nbIterp->serverIterDone) {
890 if (ServerNameGetNext
891 (nbIterp->serverIter, nameBlockp->serverName[i], &tst2)) {
892 /* Got server name; check if matches cfg or sys control host.
893 * Do a simple string compare, rather than making an expensive
894 * cfgutil_HostNameIsAlias() call because it will not cause
895 * any problems to have a duplicate in the list.
899 if (!nbIterp->cfgInBlock) {
901 (nbIterp->cfgHost, nameBlockp->serverName[i])) {
902 nbIterp->cfgInBlock = 1;
906 if (!nbIterp->sysInBlock && nbIterp->sysControlHost != NULL) {
908 (nbIterp->sysControlHost,
909 nameBlockp->serverName[i])) {
910 nbIterp->sysInBlock = 1;
915 /* no more entries (or failure) */
916 if (tst2 == ADMITERATORDONE) {
917 nbIterp->serverIterDone = 1;
926 /* include config host and (possibly) sys control host */
927 if (!nbIterp->cfgInBlock) {
928 /* shouldn't be duplicate, but OK if is */
929 strcpy(nameBlockp->serverName[i], nbIterp->cfgHost);
930 nbIterp->cfgInBlock = 1;
933 } else if (!nbIterp->sysInBlock
934 && nbIterp->sysControlHost != NULL) {
935 /* shouldn't be duplicate, but OK if is */
936 strcpy(nameBlockp->serverName[i], nbIterp->sysControlHost);
937 nbIterp->sysInBlock = 1;
943 nameBlockp->serverCount++;
945 /* no more server names */
946 if (nameBlockp->serverCount == 0) {
947 tst = ADMITERATORDONE;
954 /* indicate failure */
965 * NameBlockGetDone() -- finalize name block iteration
967 * RETURN CODES: 1 success, 0 failure (st indicates why)
970 NameBlockGetDone(void *iterationId, afs_status_p st)
973 afs_status_t tst2, tst = 0;
974 cfg_csdb_nameblock_iteration_t *nbIterp;
976 nbIterp = (cfg_csdb_nameblock_iteration_t *) iterationId;
978 if (!ServerNameGetDone(nbIterp->serverIter, &tst2)) {
985 /* indicate failure */
996 * ServerNameGetBegin() -- begin database server and (optionally) fileserver
999 * RETURN CODES: 1 success, 0 failure (st indicates why)
1002 ServerNameGetBegin(cfg_host_p cfg_host, short dbOnly, void **iterationIdP,
1006 afs_status_t tst2, tst = 0;
1007 cfg_server_iteration_t *serverIterp;
1009 serverIterp = (cfg_server_iteration_t *) malloc(sizeof(*serverIterp));
1011 if (serverIterp == NULL) {
1014 serverIterp->dbOnly = dbOnly;
1017 if (!util_DatabaseServerGetBegin
1018 (cfg_host->cellName, &serverIterp->iterationId, &tst2)) {
1022 if (!afsclient_AFSServerGetBegin
1023 (cfg_host->cellHandle, &serverIterp->iterationId, &tst2)) {
1029 *iterationIdP = serverIterp;
1036 /* indicate failure */
1047 * ServerNameGetNext() -- get next server name
1049 * RETURN CODES: 1 success, 0 failure (st indicates why)
1052 ServerNameGetNext(void *iterationId, char *serverName, afs_status_p st)
1055 afs_status_t tst2, tst = 0;
1056 cfg_server_iteration_t *serverIterp;
1058 serverIterp = (cfg_server_iteration_t *) iterationId;
1060 if (serverIterp->dbOnly) {
1061 util_databaseServerEntry_t serverEntry;
1063 if (!util_DatabaseServerGetNext
1064 (serverIterp->iterationId, &serverEntry, &tst2)) {
1067 strcpy(serverName, serverEntry.serverName);
1070 afs_serverEntry_t serverEntry;
1072 if (!afsclient_AFSServerGetNext
1073 (serverIterp->iterationId, &serverEntry, &tst2)) {
1076 strcpy(serverName, serverEntry.serverName);
1081 /* indicate failure */
1092 * ServerNameGetDone() -- terminate server enumeration
1094 * RETURN CODES: 1 success, 0 failure (st indicates why)
1097 ServerNameGetDone(void *iterationId, afs_status_p st)
1100 afs_status_t tst2, tst = 0;
1101 cfg_server_iteration_t *serverIterp;
1103 serverIterp = (cfg_server_iteration_t *) iterationId;
1105 if (serverIterp->dbOnly) {
1106 if (!util_DatabaseServerGetDone(serverIterp->iterationId, &tst2)) {
1110 if (!afsclient_AFSServerGetDone(serverIterp->iterationId, &tst2)) {
1118 /* indicate failure */