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 <afs/param.h>
15 #include <afsconfig.h>
29 #include <afs/afs_Admin.h>
30 #include <afs/afs_AdminErrors.h>
31 #include <afs/afs_bosAdmin.h>
32 #include <afs/afs_clientAdmin.h>
33 #include <afs/afs_utilAdmin.h>
35 #include <afs/cellconfig.h>
36 #include <afs/bnode.h>
38 #include "cfginternal.h"
39 #include "afs_cfgAdmin.h"
42 /* Local declarations and definitions */
44 #define CSDB_OP_ADD 0 /* add a server CellServDB entry */
45 #define CSDB_OP_REM 1 /* remove a server CellServDB entry */
47 #define CSDB_WAIT 0 /* wait to begin CellServDB update operations */
48 #define CSDB_GO 1 /* begin CellServDB update operations */
49 #define CSDB_ABORT 2 /* abort CellServDB update operations */
51 #define SERVER_NAME_BLOCK_SIZE 20 /* number of server names in a block */
54 /* server name iterator */
56 int dbOnly; /* enumerate database servers only */
57 void *iterationId; /* underlying iteration handle */
58 } cfg_server_iteration_t;
61 /* CellServDB update control block */
63 /* control block invariants */
64 cfg_host_p cfg_host; /* host configuration handle */
65 int op; /* CellServDB update operation type */
66 char opHostAlias[MAXHOSTCHARS]; /* CellServDB alias for config host */
67 cfg_cellServDbUpdateCallBack_t callBack; /* CellServDB update callback */
68 void *callBackId; /* CellServDB update callback cookie */
70 /* control block synchronization objects */
71 pthread_cond_t event; /* disposition change event */
72 pthread_mutex_t mutex; /* protects disposition and workersActive */
73 int disposition; /* wait, go, or abort operation */
74 int workersActive; /* count of active worker threads */
75 } cfg_csdb_update_ctrl_t;
77 /* CellServDB update name block */
79 cfg_csdb_update_ctrl_t *ctrl; /* pointer to common control block */
80 int serverCount; /* number of entries in serverName array */
81 char serverName[SERVER_NAME_BLOCK_SIZE][AFS_MAX_SERVER_NAME_LEN];
82 } cfg_csdb_update_name_t;
84 /* name block iterator */
86 void *serverIter; /* server name iterator */
87 cfg_csdb_update_ctrl_t *ctrlBlockp; /* update control block */
88 const char *cfgHost; /* configuration host name */
89 const char *sysControlHost; /* system control host name (if any) */
90 short cfgInBlock; /* configuration host in a name block */
91 short sysInBlock; /* system control host in a name block */
92 short serverIterDone; /* server name enumeration complete */
93 } cfg_csdb_nameblock_iteration_t;
98 CellServDbUpdate(int updateOp,
100 const char *sysControlHost,
101 cfg_cellServDbUpdateCallBack_t callBack,
107 StartUpdateWorkerThread(cfg_csdb_update_name_t *nameBlockp,
111 UpdateWorkerThread(void *argp);
114 CfgHostGetCellServDbAlias(cfg_host_p cfg_host,
119 NameBlockGetBegin(cfg_host_p cfg_host,
120 const char *sysControlHost,
121 cfg_csdb_update_ctrl_t *ctrlBlockp,
126 NameBlockGetNext(void *iterationId,
127 cfg_csdb_update_name_t *nameBlockp,
131 NameBlockGetDone(void *iterationId,
135 ServerNameGetBegin(cfg_host_p cfg_host,
141 ServerNameGetNext(void *iterationId,
146 ServerNameGetDone(void *iterationId,
151 /* ---------------- Exported CellServDB functions ------------------ */
155 * cfg_cellServDbUpdateCallBack_t -- prototype for status callback that is
156 * invoked by functions that update the CellServDB.
158 * Implementation provided by library user.
161 * callBackId - user-supplied context identifier; used by caller to
162 * distinguish results from different functions (or different
163 * invocations of the same function) that utilize the same callback.
165 * statusItemP - pointer to status information returned by a function
166 * via this callback; an statusItemP value of NULL indicates
167 * termination of status callbacks for a given function invocation;
168 * the termination callback will not occur until all other callbacks
169 * in the set have completed.
171 * status - if statusItemP is NULL then this argument indicates whether
172 * termination of status callbacks is due to logical completion
176 * The callback thread is not permitted to reenter the configuration
177 * library except to deallocate returned storage.
182 * cfg_CellServDbAddHost() -- Add host being configured to server
183 * CellServDB on all fileserver and database machines in cell and to
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_CellServDbAddHost(void *hostHandle, /* host config handle */
191 const char *sysControlHost, /* sys control host */
192 cfg_cellServDbUpdateCallBack_t callBack,
194 int *maxUpdates, /* max servers to update */
195 afs_status_p st) /* completion status */
197 return CellServDbUpdate(CSDB_OP_ADD,
208 * cfg_CellServDbRemoveHost() -- Remove host being configured from server
209 * CellServDB on all fileserver and database machines in cell and from
210 * host's server CellServDB.
212 * If a System Control machine has been configured, sysControlHost must
213 * specify the host name; otherwise, sysControlHost must be NULL.
216 cfg_CellServDbRemoveHost(void *hostHandle, /* host config handle */
217 const char *sysControlHost, /* sys control host */
218 cfg_cellServDbUpdateCallBack_t callBack,
220 int *maxUpdates, /* max servers to update */
221 afs_status_p st) /* completion status */
223 return CellServDbUpdate(CSDB_OP_REM,
234 * cfg_CellServDbEnumerate() -- Enumerate database machines known to the
235 * specified database or fileserver machine. Enumeration is returned
239 cfg_CellServDbEnumerate(const char *fsDbHost, /* fileserver or database host */
240 char **cellName, /* cell name for cellDbHosts */
241 char **cellDbHosts, /* cell database hosts */
242 afs_status_p st) /* completion status */
245 afs_status_t tst2, tst = 0;
247 /* validate parameters */
249 if (fsDbHost == NULL || *fsDbHost == '\0') {
250 tst = ADMCFGHOSTNAMENULL;
251 } else if (cellName == NULL) {
252 tst = ADMCFGCELLNAMENULL;
253 } else if (cellDbHosts == NULL) {
254 tst = ADMCFGCELLDBHOSTSNULL;
257 /* enumerate server CellServDB on specified host, along with cell name */
262 char dbhostName[MAXHOSTSPERCELL][BOS_MAX_NAME_LEN];
263 char dbhostCell[BOS_MAX_NAME_LEN];
266 if (!afsclient_NullCellOpen(&cellHandle, &tst2)) {
269 if (!bos_ServerOpen(cellHandle, fsDbHost, &bosHandle, &tst2)) {
274 if (!bos_HostGetBegin(bosHandle, &dbIter, &tst2)) {
277 for (dbhostCount = 0; ; dbhostCount++) {
278 char dbhostNameTemp[BOS_MAX_NAME_LEN];
280 if (!bos_HostGetNext(dbIter,
281 dbhostNameTemp, &tst2)) {
282 /* no more entries (or failure) */
283 if (tst2 != ADMITERATORDONE) {
287 } else if (dbhostCount >= MAXHOSTSPERCELL) {
288 /* more entries than expected */
289 tst = ADMCFGCELLSERVDBTOOMANYENTRIES;
292 strcpy(dbhostName[dbhostCount], dbhostNameTemp);
296 if (!bos_HostGetDone(dbIter, &tst2)) {
301 /* got database servers; now get cell name */
302 if (!bos_CellGet(bosHandle, dbhostCell, &tst2)) {
308 if (!bos_ServerClose(bosHandle, &tst2)) {
313 if (!afsclient_CellClose(cellHandle, &tst2)) {
319 /* return database hosts to caller */
323 for (i = 0; i < dbhostCount; i++) {
324 bufSize += strlen(dbhostName[i]) + 1;
326 bufSize++; /* end multistring */
328 *cellDbHosts = (char *)malloc(bufSize);
330 if (*cellDbHosts == NULL) {
333 char *bufp = *cellDbHosts;
335 for (i = 0; i < dbhostCount; i++) {
336 strcpy(bufp, dbhostName[i]);
337 bufp += strlen(bufp) + 1;
342 /* return cell name to caller */
344 *cellName = (char *)malloc(strlen(dbhostCell) + 1);
346 if (*cellName == NULL) {
350 strcpy(*cellName, dbhostCell);
357 /* indicate failure */
368 /* ---------------- Exported Utility functions ------------------ */
372 * cfg_CellServDbStatusDeallocate() -- Deallocate CellServDB update status
373 * record returned by library.
376 cfg_CellServDbStatusDeallocate(cfg_cellServDbStatus_t *statusItempP,
379 free((void *)statusItempP);
391 /* ---------------- Local functions ------------------ */
395 * CellServDbUpdate() -- add or remove a server CellServDB entry.
397 * Common function implementing cfg_CellServDb{Add/Remove}Host().
400 CellServDbUpdate(int updateOp,
402 const char *sysControlHost,
403 cfg_cellServDbUpdateCallBack_t callBack,
409 afs_status_t tst2, tst = 0;
410 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
411 char fullSysHostName[MAXHOSTCHARS];
413 /* validate parameters */
415 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
417 } else if (sysControlHost != NULL && *sysControlHost == '\0') {
418 tst = ADMCFGHOSTNAMENULL;
419 } else if (callBack == NULL) {
420 tst = ADMCFGCALLBACKNULL;
421 } else if (maxUpdates == NULL) {
422 tst = ADMCFGUPDATECOUNTNULL;
425 /* resolve sys ctrl host to fully qualified name (if extant) */
428 if (sysControlHost != NULL) {
429 if (!cfgutil_HostNameGetFull(sysControlHost,
430 fullSysHostName, &tst2)) {
433 sysControlHost = fullSysHostName;
438 /* Update cell-wide server CellServDb as follows:
440 * 1) If system control machine is in use then update the following:
441 * system control host + database server hosts + configuration host
443 * Updating the system control machine is theoretically sufficient,
444 * as all server hosts should be getting configuration information
445 * from there. However, we don't want to have to delay further
446 * configuration until this update occurs (which could be set for
447 * any time interval). Therefore, we compromise by manually
448 * updating the database server hosts and the host being configured.
450 * 2) If no system control machine is in use then update the following:
451 * fileserver hosts + database server hosts + configuration host
454 * We create a set of server name blocks, with one thread per name
455 * block that is responsible for updating the servers in that block.
456 * All server name blocks share a single control block that stores
457 * common data and coordinates start/abort and cleanup activities.
458 * All threads wait for the start/abort signal before performing
459 * update operations so that this function is atomic.
463 cfg_csdb_update_ctrl_t *ctrlBlockp;
467 /* create control block */
469 ctrlBlockp = (cfg_csdb_update_ctrl_t *)malloc(sizeof(*ctrlBlockp));
471 if (ctrlBlockp == NULL) {
474 ctrlBlockp->cfg_host = cfg_host;
475 ctrlBlockp->op = updateOp;
476 ctrlBlockp->callBack = callBack;
477 ctrlBlockp->callBackId = callBackId;
478 ctrlBlockp->disposition = CSDB_WAIT;
479 ctrlBlockp->workersActive = 0;
481 if (pthread_mutex_init(&ctrlBlockp->mutex, NULL)) {
483 } else if (pthread_cond_init(&ctrlBlockp->event, NULL)) {
486 /* Unfortunately the bosserver adds/removes entries from
487 * the server CellServDB based on a case-sensitive string
488 * comparison, rather than using an address comparison
489 * to handle aliasing. So we must use the name for the
490 * configuration host exactly as listed in the CellServDB.
492 * Of course the 3.5 bosserver can and should be modified to
493 * handle aliases, but we still have to deal with down-level
494 * servers in this library.
496 * To get reasonable performance, the presumption is made
497 * that all server CellServDB are identical. This way we
498 * can look up the configuration host alias once and use
499 * it everywhere. If this proves to be insufficient then
500 * this lookup will have to be done for every server to be
501 * updated which will be very costly; such individual lookups
502 * would naturally be handled by the update worker threads.
504 * A final presumption is that we can just look at the
505 * server CellServDB on the current database servers to
506 * get the configuration host alias. The only time this
507 * might get us into trouble is in a re-do scenario.
509 if (!CfgHostGetCellServDbAlias(cfg_host,
510 ctrlBlockp->opHostAlias,
513 } else if (*ctrlBlockp->opHostAlias == '\0') {
514 /* no alias found; go with config host working name */
515 strcpy(ctrlBlockp->opHostAlias, cfg_host->hostName);
522 /* fill name blocks, handing each to a worker thread */
524 short workersStarted = 0;
526 if (!NameBlockGetBegin(cfg_host,
533 cfg_csdb_update_name_t *nameBlockp;
534 short nameBlockDone = 0;
536 while (!nameBlockDone) {
537 nameBlockp = ((cfg_csdb_update_name_t *)
538 malloc(sizeof(*nameBlockp)));
540 if (nameBlockp == NULL) {
544 } else if (!NameBlockGetNext(nameBlockIter,
547 /* no more entries (or failure) */
548 if (tst2 != ADMITERATORDONE) {
555 *maxUpdates += nameBlockp->serverCount;
557 if (StartUpdateWorkerThread(nameBlockp, &tst2)) {
558 /* increment worker count; lock not required
559 * until workers given start/abort signal.
561 ctrlBlockp->workersActive++;
571 if (!NameBlockGetDone(nameBlockIter, &tst2)) {
576 if (workersStarted) {
577 /* worker threads started; set disposition and signal */
578 if (pthread_mutex_lock(&ctrlBlockp->mutex)) {
582 /* tell workers to proceed with updates */
583 ctrlBlockp->disposition = CSDB_GO;
585 /* tell workers to abort */
586 ctrlBlockp->disposition = CSDB_ABORT;
589 if (pthread_mutex_unlock(&ctrlBlockp->mutex)) {
590 tst = ADMMUTEXUNLOCK;
592 if (pthread_cond_broadcast(&ctrlBlockp->event)) {
597 /* no worker threads started */
605 /* indicate failure */
616 * StartUpdateWorkerThread() -- start an update worker thread for the
617 * given server name block
619 * RETURN CODES: 1 success, 0 failure (st indicates why)
622 StartUpdateWorkerThread(cfg_csdb_update_name_t *nameBlockp,
626 afs_status_t tst = 0;
627 pthread_attr_t tattr;
630 if (pthread_attr_init(&tattr)) {
631 tst = ADMTHREADATTRINIT;
633 } else if (pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED)) {
634 tst = ADMTHREADATTRSETDETACHSTATE;
636 } else if (pthread_create(&tid,
638 UpdateWorkerThread, (void *) nameBlockp)) {
639 tst = ADMTHREADCREATE;
643 /* indicate failure */
654 * UpdateWorkerThread() -- thread for updating CellServDB of servers in
655 * a single name block.
658 UpdateWorkerThread(void *argp)
660 afs_status_t sync_tst = 0;
661 cfg_csdb_update_name_t *nameBlockp = (cfg_csdb_update_name_t *)argp;
664 /* Pthread mutex and condition variable functions should never fail,
665 * but if they do make a best effort attempt to report the problem;
666 * will not be able to avoid race conditions in the face of such failures.
669 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
670 sync_tst = ADMMUTEXLOCK;
673 while ((opDisposition = nameBlockp->ctrl->disposition) == CSDB_WAIT) {
674 /* wait for start/abort signal */
675 if (pthread_cond_wait(&nameBlockp->ctrl->event,
676 &nameBlockp->ctrl->mutex)) {
677 /* avoid tight loop if condition variable wait fails */
682 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
683 sync_tst = ADMMUTEXUNLOCK;
686 if (opDisposition == CSDB_GO) {
687 /* proceed with CellServDB update */
690 for (i = 0; i < nameBlockp->serverCount; i++) {
691 cfg_cellServDbStatus_t *statusp;
693 /* alloc memory for status information (including host name) */
695 while ((statusp = (cfg_cellServDbStatus_t *)
696 malloc(sizeof(*statusp) +
697 AFS_MAX_SERVER_NAME_LEN)) == NULL) {
698 /* avoid tight loop while waiting for status storage */
702 statusp->fsDbHost = ((char *)statusp + sizeof(*statusp));
704 /* make update and set status information */
706 strcpy(statusp->fsDbHost, nameBlockp->serverName[i]);
709 /* report pthread problem */
710 statusp->status = sync_tst;
712 /* attempt update and report update status */
714 afs_status_t tst2, tst = 0;
716 if (!bos_ServerOpen(nameBlockp->ctrl->cfg_host->cellHandle,
717 nameBlockp->serverName[i],
723 char *opHost = nameBlockp->ctrl->opHostAlias;
725 if (nameBlockp->ctrl->op == CSDB_OP_ADD) {
726 if (!bos_HostCreate(bosHandle, opHost, &tst2)) {
730 if (!bos_HostDelete(bosHandle, opHost, &tst2)) {
731 if (tst2 != BZNOENT) {
737 if (!bos_ServerClose(bosHandle, &tst2)) {
741 statusp->status = tst;
744 /* make call back to return update status */
746 (*nameBlockp->ctrl->callBack)(nameBlockp->ctrl->callBackId,
752 /* last worker makes termination call back and deallocates control block */
754 if (pthread_mutex_lock(&nameBlockp->ctrl->mutex)) {
755 sync_tst = ADMMUTEXLOCK;
758 nameBlockp->ctrl->workersActive--;
760 if (nameBlockp->ctrl->workersActive == 0) {
761 if (opDisposition == CSDB_GO) {
762 (*nameBlockp->ctrl->callBack)(nameBlockp->ctrl->callBackId,
766 free(nameBlockp->ctrl);
769 if (pthread_mutex_unlock(&nameBlockp->ctrl->mutex)) {
770 sync_tst = ADMMUTEXUNLOCK;
773 /* all workers deallocate their own name block */
781 * CfgHostGetCellServDbAlias() -- Get alias for configuration host name
782 * as listed in the server CellServDB. If no alias is found then
783 * cfgHostAlias is set to the empty string.
785 * Note: cfgHostAlias is presumed to be a buffer of size MAXHOSTCHARS.
786 * Presumes all server CellServDB are identical.
787 * Only checks server CellServDB of database servers.
789 * RETURN CODES: 1 success, 0 failure (st indicates why)
792 CfgHostGetCellServDbAlias(cfg_host_p cfg_host,
797 afs_status_t tst2, tst = 0;
800 if (!util_DatabaseServerGetBegin(cfg_host->cellName, &dbIter, &tst2)) {
803 util_databaseServerEntry_t dbhostEntry;
804 afs_status_t dbhostSt = 0;
805 short dbhostDone = 0;
806 short dbhostFound = 0;
808 while (!dbhostDone) {
809 if (!util_DatabaseServerGetNext(dbIter, &dbhostEntry, &tst2)) {
810 /* no more entries (or failure) */
811 if (tst2 != ADMITERATORDONE) {
816 } else if (!cfgutil_HostNameGetCellServDbAlias(dbhostEntry.serverName,
820 /* save failure status but keep trying */
823 } else if (*cfgHostAlias != '\0') {
830 *cfgHostAlias = '\0';
837 if (!util_DatabaseServerGetDone(dbIter, &tst2)) {
843 /* indicate failure */
854 * NameBlockGetBegin() -- initialize name block iteration
856 * RETURN CODES: 1 success, 0 failure (st indicates why)
859 NameBlockGetBegin(cfg_host_p cfg_host,
860 const char *sysControlHost,
861 cfg_csdb_update_ctrl_t *ctrlBlockp,
866 afs_status_t tst2, tst = 0;
867 cfg_csdb_nameblock_iteration_t *nbIterp;
869 nbIterp = (cfg_csdb_nameblock_iteration_t *)malloc(sizeof(*nbIterp));
871 if (nbIterp == NULL) {
874 short dbOnly = (sysControlHost != NULL);
876 nbIterp->ctrlBlockp = ctrlBlockp;
877 nbIterp->cfgHost = cfg_host->hostName;
878 nbIterp->sysControlHost = sysControlHost;
879 nbIterp->cfgInBlock = 0;
880 nbIterp->sysInBlock = 0;
881 nbIterp->serverIterDone = 0;
883 if (!ServerNameGetBegin(cfg_host,
884 dbOnly, &nbIterp->serverIter, &tst2)) {
889 *iterationIdP = nbIterp;
896 /* indicate failure */
907 * NameBlockGetNext() -- fill next name block
909 * RETURN CODES: 1 success, 0 failure (st indicates why)
912 NameBlockGetNext(void *iterationId,
913 cfg_csdb_update_name_t *nameBlockp,
917 afs_status_t tst2, tst = 0;
918 cfg_csdb_nameblock_iteration_t *nbIterp;
921 nbIterp = (cfg_csdb_nameblock_iteration_t *)iterationId;
923 nameBlockp->ctrl = nbIterp->ctrlBlockp;
924 nameBlockp->serverCount = 0;
926 for (i = 0; i < SERVER_NAME_BLOCK_SIZE; i++) {
927 short nameEntered = 0;
929 if (!nbIterp->serverIterDone) {
930 if (ServerNameGetNext(nbIterp->serverIter,
931 nameBlockp->serverName[i],
933 /* Got server name; check if matches cfg or sys control host.
934 * Do a simple string compare, rather than making an expensive
935 * cfgutil_HostNameIsAlias() call because it will not cause
936 * any problems to have a duplicate in the list.
940 if (!nbIterp->cfgInBlock) {
941 if (!strcasecmp(nbIterp->cfgHost,
942 nameBlockp->serverName[i])) {
943 nbIterp->cfgInBlock = 1;
947 if (!nbIterp->sysInBlock && nbIterp->sysControlHost != NULL) {
948 if (!strcasecmp(nbIterp->sysControlHost,
949 nameBlockp->serverName[i])) {
950 nbIterp->sysInBlock = 1;
955 /* no more entries (or failure) */
956 if (tst2 == ADMITERATORDONE) {
957 nbIterp->serverIterDone = 1;
966 /* include config host and (possibly) sys control host */
967 if (!nbIterp->cfgInBlock) {
968 /* shouldn't be duplicate, but OK if is */
969 strcpy(nameBlockp->serverName[i], nbIterp->cfgHost);
970 nbIterp->cfgInBlock = 1;
973 } else if (!nbIterp->sysInBlock &&
974 nbIterp->sysControlHost != NULL) {
975 /* shouldn't be duplicate, but OK if is */
976 strcpy(nameBlockp->serverName[i], nbIterp->sysControlHost);
977 nbIterp->sysInBlock = 1;
983 nameBlockp->serverCount++;
985 /* no more server names */
986 if (nameBlockp->serverCount == 0) {
987 tst = ADMITERATORDONE;
994 /* indicate failure */
1005 * NameBlockGetDone() -- finalize name block iteration
1007 * RETURN CODES: 1 success, 0 failure (st indicates why)
1010 NameBlockGetDone(void *iterationId,
1014 afs_status_t tst2, tst = 0;
1015 cfg_csdb_nameblock_iteration_t *nbIterp;
1017 nbIterp = (cfg_csdb_nameblock_iteration_t *)iterationId;
1019 if (!ServerNameGetDone(nbIterp->serverIter, &tst2)) {
1026 /* indicate failure */
1037 * ServerNameGetBegin() -- begin database server and (optionally) fileserver
1040 * RETURN CODES: 1 success, 0 failure (st indicates why)
1043 ServerNameGetBegin(cfg_host_p cfg_host,
1045 void **iterationIdP,
1049 afs_status_t tst2, tst = 0;
1050 cfg_server_iteration_t *serverIterp;
1052 serverIterp = (cfg_server_iteration_t *)malloc(sizeof(*serverIterp));
1054 if (serverIterp == NULL) {
1057 serverIterp->dbOnly = dbOnly;
1060 if (!util_DatabaseServerGetBegin(cfg_host->cellName,
1061 &serverIterp->iterationId,
1066 if (!afsclient_AFSServerGetBegin(cfg_host->cellHandle,
1067 &serverIterp->iterationId,
1074 *iterationIdP = serverIterp;
1081 /* indicate failure */
1092 * ServerNameGetNext() -- get next server name
1094 * RETURN CODES: 1 success, 0 failure (st indicates why)
1097 ServerNameGetNext(void *iterationId,
1102 afs_status_t tst2, tst = 0;
1103 cfg_server_iteration_t *serverIterp;
1105 serverIterp = (cfg_server_iteration_t *)iterationId;
1107 if (serverIterp->dbOnly) {
1108 util_databaseServerEntry_t serverEntry;
1110 if (!util_DatabaseServerGetNext(serverIterp->iterationId,
1115 strcpy(serverName, serverEntry.serverName);
1118 afs_serverEntry_t serverEntry;
1120 if (!afsclient_AFSServerGetNext(serverIterp->iterationId,
1125 strcpy(serverName, serverEntry.serverName);
1130 /* indicate failure */
1141 * ServerNameGetDone() -- terminate server enumeration
1143 * RETURN CODES: 1 success, 0 failure (st indicates why)
1146 ServerNameGetDone(void *iterationId,
1150 afs_status_t tst2, tst = 0;
1151 cfg_server_iteration_t *serverIterp;
1153 serverIterp = (cfg_server_iteration_t *)iterationId;
1155 if (serverIterp->dbOnly) {
1156 if (!util_DatabaseServerGetDone(serverIterp->iterationId, &tst2)) {
1160 if (!afsclient_AFSServerGetDone(serverIterp->iterationId, &tst2)) {
1168 /* indicate failure */