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>
23 #include <rx/rxstat.h>
25 #include <afs/afs_Admin.h>
26 #include <afs/afs_AdminErrors.h>
27 #include <afs/afs_bosAdmin.h>
28 #include <afs/afs_clientAdmin.h>
29 #include <afs/afs_utilAdmin.h>
31 #include <afs/cellconfig.h>
32 #include <afs/bnode.h>
34 #include "cfginternal.h"
35 #include "afs_cfgAdmin.h"
38 /* Local declarations and definitions */
40 #define CSDB_OP_ADD 0 /* add a server CellServDB entry */
41 #define CSDB_OP_REM 1 /* remove a server CellServDB entry */
43 #define CSDB_WAIT 0 /* wait to begin CellServDB update operations */
44 #define CSDB_GO 1 /* begin CellServDB update operations */
45 #define CSDB_ABORT 2 /* abort CellServDB update operations */
47 #define SERVER_NAME_BLOCK_SIZE 20 /* number of server names in a block */
50 /* server name iterator */
52 int dbOnly; /* enumerate database servers only */
53 void *iterationId; /* underlying iteration handle */
54 } cfg_server_iteration_t;
57 /* CellServDB update control block */
59 /* control block invariants */
60 cfg_host_p cfg_host; /* host configuration handle */
61 int op; /* CellServDB update operation type */
62 char opHostAlias[MAXHOSTCHARS]; /* CellServDB alias for config host */
63 cfg_cellServDbUpdateCallBack_t callBack; /* CellServDB update callback */
64 void *callBackId; /* CellServDB update callback cookie */
66 /* control block synchronization objects */
67 pthread_cond_t event; /* disposition change event */
68 pthread_mutex_t mutex; /* protects disposition and workersActive */
69 int disposition; /* wait, go, or abort operation */
70 int workersActive; /* count of active worker threads */
71 } cfg_csdb_update_ctrl_t;
73 /* CellServDB update name block */
75 cfg_csdb_update_ctrl_t *ctrl; /* pointer to common control block */
76 int serverCount; /* number of entries in serverName array */
77 char serverName[SERVER_NAME_BLOCK_SIZE][AFS_MAX_SERVER_NAME_LEN];
78 } cfg_csdb_update_name_t;
80 /* name block iterator */
82 void *serverIter; /* server name iterator */
83 cfg_csdb_update_ctrl_t *ctrlBlockp; /* update control block */
84 const char *cfgHost; /* configuration host name */
85 const char *sysControlHost; /* system control host name (if any) */
86 short cfgInBlock; /* configuration host in a name block */
87 short sysInBlock; /* system control host in a name block */
88 short serverIterDone; /* server name enumeration complete */
89 } cfg_csdb_nameblock_iteration_t;
94 CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost,
95 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId,
96 int *maxUpdates, afs_status_p st);
99 StartUpdateWorkerThread(cfg_csdb_update_name_t * nameBlockp,
102 static void *UpdateWorkerThread(void *argp);
105 CfgHostGetCellServDbAlias(cfg_host_p cfg_host, char *cfgHostAlias,
109 NameBlockGetBegin(cfg_host_p cfg_host, const char *sysControlHost,
110 cfg_csdb_update_ctrl_t * ctrlBlockp, void **iterationIdP,
114 NameBlockGetNext(void *iterationId, cfg_csdb_update_name_t * nameBlockp,
118 NameBlockGetDone(void *iterationId, afs_status_p st);
121 ServerNameGetBegin(cfg_host_p cfg_host, short dbOnly, void **iterationIdP,
125 ServerNameGetNext(void *iterationId, char *serverName, afs_status_p st);
128 ServerNameGetDone(void *iterationId, afs_status_p st);
132 /* ---------------- Exported CellServDB functions ------------------ */
136 * cfg_cellServDbUpdateCallBack_t -- prototype for status callback that is
137 * invoked by functions that update the CellServDB.
139 * Implementation provided by library user.
142 * callBackId - user-supplied context identifier; used by caller to
143 * distinguish results from different functions (or different
144 * invocations of the same function) that utilize the same callback.
146 * statusItemP - pointer to status information returned by a function
147 * via this callback; an statusItemP value of NULL indicates
148 * termination of status callbacks for a given function invocation;
149 * the termination callback will not occur until all other callbacks
150 * in the set have completed.
152 * status - if statusItemP is NULL then this argument indicates whether
153 * termination of status callbacks is due to logical completion
157 * The callback thread is not permitted to reenter the configuration
158 * library except to deallocate returned storage.
163 * cfg_CellServDbAddHost() -- Add host being configured to server
164 * CellServDB on all fileserver and database machines in cell and to
165 * host's server CellServDB.
167 * If a System Control machine has been configured, sysControlHost must
168 * specify the host name; otherwise, sysControlHost must be NULL.
171 cfg_CellServDbAddHost(void *hostHandle, /* host config handle */
172 const char *sysControlHost, /* sys control host */
173 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId, int *maxUpdates, /* max servers to update */
175 { /* completion status */
176 return CellServDbUpdate(CSDB_OP_ADD, hostHandle, sysControlHost, callBack,
177 callBackId, maxUpdates, st);
182 * cfg_CellServDbRemoveHost() -- Remove host being configured from server
183 * CellServDB on all fileserver and database machines in cell and from
184 * host's server CellServDB.
186 * If a System Control machine has been configured, sysControlHost must
187 * specify the host name; otherwise, sysControlHost must be NULL.
190 cfg_CellServDbRemoveHost(void *hostHandle, /* host config handle */
191 const char *sysControlHost, /* sys control host */
192 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId, int *maxUpdates, /* max servers to update */
194 { /* completion status */
195 return CellServDbUpdate(CSDB_OP_REM, hostHandle, sysControlHost, callBack,
196 callBackId, maxUpdates, st);
201 * cfg_CellServDbEnumerate() -- Enumerate database machines known to the
202 * specified database or fileserver machine. Enumeration is returned
206 cfg_CellServDbEnumerate(const char *fsDbHost, /* fileserver or database host */
207 char **cellName, /* cell name for cellDbHosts */
208 char **cellDbHosts, /* cell database hosts */
210 { /* completion status */
212 afs_status_t tst2, tst = 0;
214 /* validate parameters */
216 if (fsDbHost == NULL || *fsDbHost == '\0') {
217 tst = ADMCFGHOSTNAMENULL;
218 } else if (cellName == NULL) {
219 tst = ADMCFGCELLNAMENULL;
220 } else if (cellDbHosts == NULL) {
221 tst = ADMCFGCELLDBHOSTSNULL;
224 /* enumerate server CellServDB on specified host, along with cell name */
229 char dbhostName[MAXHOSTSPERCELL][BOS_MAX_NAME_LEN];
230 char dbhostCell[BOS_MAX_NAME_LEN];
233 if (!afsclient_NullCellOpen(&cellHandle, &tst2)) {
236 if (!bos_ServerOpen(cellHandle, fsDbHost, &bosHandle, &tst2)) {
241 if (!bos_HostGetBegin(bosHandle, &dbIter, &tst2)) {
244 for (dbhostCount = 0;; dbhostCount++) {
245 char dbhostNameTemp[BOS_MAX_NAME_LEN];
247 if (!bos_HostGetNext(dbIter, dbhostNameTemp, &tst2)) {
248 /* no more entries (or failure) */
249 if (tst2 != ADMITERATORDONE) {
253 } else if (dbhostCount >= MAXHOSTSPERCELL) {
254 /* more entries than expected */
255 tst = ADMCFGCELLSERVDBTOOMANYENTRIES;
258 strcpy(dbhostName[dbhostCount], dbhostNameTemp);
262 if (!bos_HostGetDone(dbIter, &tst2)) {
267 /* got database servers; now get cell name */
268 if (!bos_CellGet(bosHandle, dbhostCell, &tst2)) {
274 if (!bos_ServerClose(bosHandle, &tst2)) {
279 if (!afsclient_CellClose(cellHandle, &tst2)) {
285 /* return database hosts to caller */
289 for (i = 0; i < dbhostCount; i++) {
290 bufSize += strlen(dbhostName[i]) + 1;
292 bufSize++; /* end multistring */
294 *cellDbHosts = malloc(bufSize);
296 if (*cellDbHosts == NULL) {
299 char *bufp = *cellDbHosts;
301 for (i = 0; i < dbhostCount; i++) {
302 strcpy(bufp, dbhostName[i]);
303 bufp += strlen(bufp) + 1;
308 /* return cell name to caller */
310 *cellName = strdup(dbhostCell);
312 if (*cellName == NULL) {
322 /* indicate failure */
333 /* ---------------- Exported Utility functions ------------------ */
337 * cfg_CellServDbStatusDeallocate() -- Deallocate CellServDB update status
338 * record returned by library.
341 cfg_CellServDbStatusDeallocate(cfg_cellServDbStatus_t * statusItempP,
357 /* ---------------- Local functions ------------------ */
361 * CellServDbUpdate() -- add or remove a server CellServDB entry.
363 * Common function implementing cfg_CellServDb{Add/Remove}Host().
366 CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost,
367 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId,
368 int *maxUpdates, afs_status_p st)
371 afs_status_t tst2, tst = 0;
372 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
373 char fullSysHostName[MAXHOSTCHARS];
375 /* validate parameters */
377 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
379 } else if (sysControlHost != NULL && *sysControlHost == '\0') {
380 tst = ADMCFGHOSTNAMENULL;
381 } else if (callBack == NULL) {
382 tst = ADMCFGCALLBACKNULL;
383 } else if (maxUpdates == NULL) {
384 tst = ADMCFGUPDATECOUNTNULL;
387 /* resolve sys ctrl host to fully qualified name (if extant) */
390 if (sysControlHost != NULL) {
391 if (!cfgutil_HostNameGetFull
392 (sysControlHost, fullSysHostName, &tst2)) {
395 sysControlHost = fullSysHostName;
400 /* Update cell-wide server CellServDb as follows:
402 * 1) If system control machine is in use then update the following:
403 * system control host + database server hosts + configuration host
405 * Updating the system control machine is theoretically sufficient,
406 * as all server hosts should be getting configuration information
407 * from there. However, we don't want to have to delay further
408 * configuration until this update occurs (which could be set for
409 * any time interval). Therefore, we compromise by manually
410 * updating the database server hosts and the host being configured.
412 * 2) If no system control machine is in use then update the following:
413 * fileserver hosts + database server hosts + configuration host
416 * We create a set of server name blocks, with one thread per name
417 * block that is responsible for updating the servers in that block.
418 * All server name blocks share a single control block that stores
419 * common data and coordinates start/abort and cleanup activities.
420 * All threads wait for the start/abort signal before performing
421 * update operations so that this function is atomic.
425 cfg_csdb_update_ctrl_t *ctrlBlockp = NULL;
429 /* create control block */
431 ctrlBlockp = malloc(sizeof(*ctrlBlockp));
433 if (ctrlBlockp == NULL) {
436 ctrlBlockp->cfg_host = cfg_host;
437 ctrlBlockp->op = updateOp;
438 ctrlBlockp->callBack = callBack;
439 ctrlBlockp->callBackId = callBackId;
440 ctrlBlockp->disposition = CSDB_WAIT;
441 ctrlBlockp->workersActive = 0;
443 if (pthread_mutex_init(&ctrlBlockp->mutex, NULL)) {
445 } else if (pthread_cond_init(&ctrlBlockp->event, NULL)) {
448 /* Unfortunately the bosserver adds/removes entries from
449 * the server CellServDB based on a case-sensitive string
450 * comparison, rather than using an address comparison
451 * to handle aliasing. So we must use the name for the
452 * configuration host exactly as listed in the CellServDB.
454 * Of course the 3.5 bosserver can and should be modified to
455 * handle aliases, but we still have to deal with down-level
456 * servers in this library.
458 * To get reasonable performance, the presumption is made
459 * that all server CellServDB are identical. This way we
460 * can look up the configuration host alias once and use
461 * it everywhere. If this proves to be insufficient then
462 * this lookup will have to be done for every server to be
463 * updated which will be very costly; such individual lookups
464 * would naturally be handled by the update worker threads.
466 * A final presumption is that we can just look at the
467 * server CellServDB on the current database servers to
468 * get the configuration host alias. The only time this
469 * might get us into trouble is in a re-do scenario.
471 if (!CfgHostGetCellServDbAlias
472 (cfg_host, ctrlBlockp->opHostAlias, &tst2)) {
474 } else if (*ctrlBlockp->opHostAlias == '\0') {
475 /* no alias found; go with config host working name */
476 strcpy(ctrlBlockp->opHostAlias, cfg_host->hostName);
483 /* fill name blocks, handing each to a worker thread */
484 void *nameBlockIter = NULL;
485 short workersStarted = 0;
487 if (!NameBlockGetBegin
488 (cfg_host, sysControlHost, ctrlBlockp, &nameBlockIter,
492 cfg_csdb_update_name_t *nameBlockp = NULL;
493 short nameBlockDone = 0;
495 while (!nameBlockDone) {
496 nameBlockp = malloc(sizeof(*nameBlockp));
498 if (nameBlockp == NULL) {
503 if (!NameBlockGetNext
504 (nameBlockIter, nameBlockp, &tst2)) {
505 /* no more entries (or failure) */
506 if (tst2 != ADMITERATORDONE) {
513 *maxUpdates += nameBlockp->serverCount;
515 if (StartUpdateWorkerThread(nameBlockp, &tst2)) {
516 /* increment worker count; lock not required
517 * until workers given start/abort signal.
519 ctrlBlockp->workersActive++;
529 if (!NameBlockGetDone(nameBlockIter, &tst2)) {
534 if (workersStarted) {
535 /* worker threads started; set disposition and signal */
536 if (pthread_mutex_lock(&ctrlBlockp->mutex)) {
540 /* tell workers to proceed with updates */
541 ctrlBlockp->disposition = CSDB_GO;
543 /* tell workers to abort */
544 ctrlBlockp->disposition = CSDB_ABORT;
547 if (pthread_mutex_unlock(&ctrlBlockp->mutex)) {
548 tst = ADMMUTEXUNLOCK;
550 if (pthread_cond_broadcast(&ctrlBlockp->event)) {
555 /* no worker threads started */
563 /* indicate failure */
574 * StartUpdateWorkerThread() -- start an update worker thread for the
575 * given server name block
577 * RETURN CODES: 1 success, 0 failure (st indicates why)
580 StartUpdateWorkerThread(cfg_csdb_update_name_t * nameBlockp, afs_status_p st)
583 afs_status_t tst = 0;
584 pthread_attr_t tattr;
587 if (pthread_attr_init(&tattr)) {
588 tst = ADMTHREADATTRINIT;
590 } else if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED)) {
591 tst = ADMTHREADATTRSETDETACHSTATE;
595 (&tid, &tattr, UpdateWorkerThread, (void *)nameBlockp)) {
596 tst = ADMTHREADCREATE;
600 /* indicate failure */
611 * UpdateWorkerThread() -- thread for updating CellServDB of servers in
612 * a single name block.
615 UpdateWorkerThread(void *argp)
617 afs_status_t sync_tst = 0;
618 cfg_csdb_update_name_t *nameBlockp = (cfg_csdb_update_name_t *) argp;
621 /* Pthread mutex and condition variable functions should never fail,
622 * but if they do make a best effort attempt to report the problem;
623 * will not be able to avoid race conditions in the face of such failures.
626 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
627 sync_tst = ADMMUTEXLOCK;
630 while ((opDisposition = nameBlockp->ctrl->disposition) == CSDB_WAIT) {
631 /* wait for start/abort signal */
632 if (pthread_cond_wait
633 (&nameBlockp->ctrl->event, &nameBlockp->ctrl->mutex)) {
634 /* avoid tight loop if condition variable wait fails */
639 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
640 sync_tst = ADMMUTEXUNLOCK;
643 if (opDisposition == CSDB_GO) {
644 /* proceed with CellServDB update */
647 for (i = 0; i < nameBlockp->serverCount; i++) {
648 cfg_cellServDbStatus_t *statusp;
650 /* alloc memory for status information (including host name) */
653 malloc(sizeof(*statusp) + AFS_MAX_SERVER_NAME_LEN)) ==
655 /* avoid tight loop while waiting for status storage */
659 statusp->fsDbHost = ((char *)statusp + sizeof(*statusp));
661 /* make update and set status information */
663 strcpy(statusp->fsDbHost, nameBlockp->serverName[i]);
666 /* report pthread problem */
667 statusp->status = sync_tst;
669 /* attempt update and report update status */
671 afs_status_t tst2, tst = 0;
674 (nameBlockp->ctrl->cfg_host->cellHandle,
675 nameBlockp->serverName[i], &bosHandle, &tst2)) {
679 char *opHost = nameBlockp->ctrl->opHostAlias;
681 if (nameBlockp->ctrl->op == CSDB_OP_ADD) {
682 if (!bos_HostCreate(bosHandle, opHost, &tst2)) {
686 if (!bos_HostDelete(bosHandle, opHost, &tst2)) {
687 if (tst2 != BZNOENT) {
693 if (!bos_ServerClose(bosHandle, &tst2)) {
697 statusp->status = tst;
700 /* make call back to return update status */
702 (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId,
707 /* last worker makes termination call back and deallocates control block */
709 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
710 sync_tst = ADMMUTEXLOCK;
713 nameBlockp->ctrl->workersActive--;
715 if (nameBlockp->ctrl->workersActive == 0) {
716 if (opDisposition == CSDB_GO) {
717 (*nameBlockp->ctrl->callBack) (nameBlockp->ctrl->callBackId, NULL,
720 free(nameBlockp->ctrl);
723 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
724 sync_tst = ADMMUTEXUNLOCK;
727 /* all workers deallocate their own name block */
735 * CfgHostGetCellServDbAlias() -- Get alias for configuration host name
736 * as listed in the server CellServDB. If no alias is found then
737 * cfgHostAlias is set to the empty string.
739 * Note: cfgHostAlias is presumed to be a buffer of size MAXHOSTCHARS.
740 * Presumes all server CellServDB are identical.
741 * Only checks server CellServDB of database servers.
743 * RETURN CODES: 1 success, 0 failure (st indicates why)
746 CfgHostGetCellServDbAlias(cfg_host_p cfg_host, char *cfgHostAlias,
750 afs_status_t tst2, tst = 0;
753 if (!util_DatabaseServerGetBegin(cfg_host->cellName, &dbIter, &tst2)) {
756 util_databaseServerEntry_t dbhostEntry;
757 afs_status_t dbhostSt = 0;
758 short dbhostDone = 0;
759 short dbhostFound = 0;
761 while (!dbhostDone) {
762 if (!util_DatabaseServerGetNext(dbIter, &dbhostEntry, &tst2)) {
763 /* no more entries (or failure) */
764 if (tst2 != ADMITERATORDONE) {
770 if (!cfgutil_HostNameGetCellServDbAlias
771 (dbhostEntry.serverName, cfg_host->hostName, cfgHostAlias,
773 /* save failure status but keep trying */
776 } else if (*cfgHostAlias != '\0') {
783 *cfgHostAlias = '\0';
790 if (!util_DatabaseServerGetDone(dbIter, &tst2)) {
796 /* indicate failure */
807 * NameBlockGetBegin() -- initialize name block iteration
809 * RETURN CODES: 1 success, 0 failure (st indicates why)
812 NameBlockGetBegin(cfg_host_p cfg_host, const char *sysControlHost,
813 cfg_csdb_update_ctrl_t * ctrlBlockp, void **iterationIdP,
817 afs_status_t tst2, tst = 0;
818 cfg_csdb_nameblock_iteration_t *nbIterp;
820 nbIterp = malloc(sizeof(*nbIterp));
822 if (nbIterp == NULL) {
825 short dbOnly = (sysControlHost != NULL);
827 nbIterp->ctrlBlockp = ctrlBlockp;
828 nbIterp->cfgHost = cfg_host->hostName;
829 nbIterp->sysControlHost = sysControlHost;
830 nbIterp->cfgInBlock = 0;
831 nbIterp->sysInBlock = 0;
832 nbIterp->serverIterDone = 0;
834 if (!ServerNameGetBegin
835 (cfg_host, dbOnly, &nbIterp->serverIter, &tst2)) {
840 *iterationIdP = nbIterp;
847 /* indicate failure */
858 * NameBlockGetNext() -- fill next name block
860 * RETURN CODES: 1 success, 0 failure (st indicates why)
863 NameBlockGetNext(void *iterationId, cfg_csdb_update_name_t * nameBlockp,
867 afs_status_t tst2, tst = 0;
868 cfg_csdb_nameblock_iteration_t *nbIterp;
871 nbIterp = (cfg_csdb_nameblock_iteration_t *) iterationId;
873 nameBlockp->ctrl = nbIterp->ctrlBlockp;
874 nameBlockp->serverCount = 0;
876 for (i = 0; i < SERVER_NAME_BLOCK_SIZE; i++) {
877 short nameEntered = 0;
879 if (!nbIterp->serverIterDone) {
880 if (ServerNameGetNext
881 (nbIterp->serverIter, nameBlockp->serverName[i], &tst2)) {
882 /* Got server name; check if matches cfg or sys control host.
883 * Do a simple string compare, rather than making an expensive
884 * cfgutil_HostNameIsAlias() call because it will not cause
885 * any problems to have a duplicate in the list.
889 if (!nbIterp->cfgInBlock) {
891 (nbIterp->cfgHost, nameBlockp->serverName[i])) {
892 nbIterp->cfgInBlock = 1;
896 if (!nbIterp->sysInBlock && nbIterp->sysControlHost != NULL) {
898 (nbIterp->sysControlHost,
899 nameBlockp->serverName[i])) {
900 nbIterp->sysInBlock = 1;
905 /* no more entries (or failure) */
906 if (tst2 == ADMITERATORDONE) {
907 nbIterp->serverIterDone = 1;
916 /* include config host and (possibly) sys control host */
917 if (!nbIterp->cfgInBlock) {
918 /* shouldn't be duplicate, but OK if is */
919 strcpy(nameBlockp->serverName[i], nbIterp->cfgHost);
920 nbIterp->cfgInBlock = 1;
923 } else if (!nbIterp->sysInBlock
924 && nbIterp->sysControlHost != NULL) {
925 /* shouldn't be duplicate, but OK if is */
926 strcpy(nameBlockp->serverName[i], nbIterp->sysControlHost);
927 nbIterp->sysInBlock = 1;
933 nameBlockp->serverCount++;
935 /* no more server names */
936 if (nameBlockp->serverCount == 0) {
937 tst = ADMITERATORDONE;
944 /* indicate failure */
955 * NameBlockGetDone() -- finalize name block iteration
957 * RETURN CODES: 1 success, 0 failure (st indicates why)
960 NameBlockGetDone(void *iterationId, afs_status_p st)
963 afs_status_t tst2, tst = 0;
964 cfg_csdb_nameblock_iteration_t *nbIterp;
966 nbIterp = (cfg_csdb_nameblock_iteration_t *) iterationId;
968 if (!ServerNameGetDone(nbIterp->serverIter, &tst2)) {
975 /* indicate failure */
986 * ServerNameGetBegin() -- begin database server and (optionally) fileserver
989 * RETURN CODES: 1 success, 0 failure (st indicates why)
992 ServerNameGetBegin(cfg_host_p cfg_host, short dbOnly, void **iterationIdP,
996 afs_status_t tst2, tst = 0;
997 cfg_server_iteration_t *serverIterp;
999 serverIterp = malloc(sizeof(*serverIterp));
1001 if (serverIterp == NULL) {
1004 serverIterp->dbOnly = dbOnly;
1007 if (!util_DatabaseServerGetBegin
1008 (cfg_host->cellName, &serverIterp->iterationId, &tst2)) {
1012 if (!afsclient_AFSServerGetBegin
1013 (cfg_host->cellHandle, &serverIterp->iterationId, &tst2)) {
1019 *iterationIdP = serverIterp;
1026 /* indicate failure */
1037 * ServerNameGetNext() -- get next server name
1039 * RETURN CODES: 1 success, 0 failure (st indicates why)
1042 ServerNameGetNext(void *iterationId, char *serverName, afs_status_p st)
1045 afs_status_t tst2, tst = 0;
1046 cfg_server_iteration_t *serverIterp;
1048 serverIterp = (cfg_server_iteration_t *) iterationId;
1050 if (serverIterp->dbOnly) {
1051 util_databaseServerEntry_t serverEntry;
1053 if (!util_DatabaseServerGetNext
1054 (serverIterp->iterationId, &serverEntry, &tst2)) {
1057 strcpy(serverName, serverEntry.serverName);
1060 afs_serverEntry_t serverEntry;
1062 if (!afsclient_AFSServerGetNext
1063 (serverIterp->iterationId, &serverEntry, &tst2)) {
1066 strcpy(serverName, serverEntry.serverName);
1071 /* indicate failure */
1082 * ServerNameGetDone() -- terminate server enumeration
1084 * RETURN CODES: 1 success, 0 failure (st indicates why)
1087 ServerNameGetDone(void *iterationId, afs_status_p st)
1090 afs_status_t tst2, tst = 0;
1091 cfg_server_iteration_t *serverIterp;
1093 serverIterp = (cfg_server_iteration_t *) iterationId;
1095 if (serverIterp->dbOnly) {
1096 if (!util_DatabaseServerGetDone(serverIterp->iterationId, &tst2)) {
1100 if (!afsclient_AFSServerGetDone(serverIterp->iterationId, &tst2)) {
1108 /* indicate failure */