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 */