Ejemplo n.º 1
0
/*
 * CellServDbUpdate() -- add or remove a server CellServDB entry.
 *
 *     Common function implementing cfg_CellServDb{Add/Remove}Host().
 */
static int
CellServDbUpdate(int updateOp, void *hostHandle, const char *sysControlHost,
		 cfg_cellServDbUpdateCallBack_t callBack, void *callBackId,
		 int *maxUpdates, afs_status_p st)
{
    int rc = 1;
    afs_status_t tst2, tst = 0;
    cfg_host_p cfg_host = (cfg_host_p) hostHandle;
    char fullSysHostName[MAXHOSTCHARS];

    /* validate parameters */

    if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
	tst = tst2;
    } else if (sysControlHost != NULL && *sysControlHost == '\0') {
	tst = ADMCFGHOSTNAMENULL;
    } else if (callBack == NULL) {
	tst = ADMCFGCALLBACKNULL;
    } else if (maxUpdates == NULL) {
	tst = ADMCFGUPDATECOUNTNULL;
    }

    /* resolve sys ctrl host to fully qualified name (if extant) */

    if (tst == 0) {
	if (sysControlHost != NULL) {
	    if (!cfgutil_HostNameGetFull
		(sysControlHost, fullSysHostName, &tst2)) {
		tst = tst2;
	    } else {
		sysControlHost = fullSysHostName;
	    }
	}
    }

    /* Update cell-wide server CellServDb as follows:
     *
     *   1) If system control machine is in use then update the following:
     *      system control host + database server hosts + configuration host
     *
     *      Updating the system control machine is theoretically sufficient,
     *      as all server hosts should be getting configuration information
     *      from there.  However, we don't want to have to delay further
     *      configuration until this update occurs (which could be set for
     *      any time interval).  Therefore, we compromise by manually
     *      updating the database server hosts and the host being configured.
     *
     *   2) If no system control machine is in use then update the following:
     *      fileserver hosts + database server hosts + configuration host
     *
     *   General algorithm:
     *     We create a set of server name blocks, with one thread per name
     *     block that is responsible for updating the servers in that block.
     *     All server name blocks share a single control block that stores
     *     common data and coordinates start/abort and cleanup activities.
     *     All threads wait for the start/abort signal before performing
     *     update operations so that this function is atomic.
     */

    if (tst == 0) {
	cfg_csdb_update_ctrl_t *ctrlBlockp = NULL;

	*maxUpdates = 0;

	/* create control block */

	ctrlBlockp = (cfg_csdb_update_ctrl_t *) malloc(sizeof(*ctrlBlockp));

	if (ctrlBlockp == NULL) {
	    tst = ADMNOMEM;
	} else {
	    ctrlBlockp->cfg_host = cfg_host;
	    ctrlBlockp->op = updateOp;
	    ctrlBlockp->callBack = callBack;
	    ctrlBlockp->callBackId = callBackId;
	    ctrlBlockp->disposition = CSDB_WAIT;
	    ctrlBlockp->workersActive = 0;

	    if (pthread_mutex_init(&ctrlBlockp->mutex, NULL)) {
		tst = ADMMUTEXINIT;
	    } else if (pthread_cond_init(&ctrlBlockp->event, NULL)) {
		tst = ADMCONDINIT;
	    } else {
		/* Unfortunately the bosserver adds/removes entries from
		 * the server CellServDB based on a case-sensitive string
		 * comparison, rather than using an address comparison
		 * to handle aliasing.  So we must use the name for the
		 * configuration host exactly as listed in the CellServDB.
		 *
		 * Of course the 3.5 bosserver can and should be modified to
		 * handle aliases, but we still have to deal with down-level
		 * servers in this library.
		 *
		 * To get reasonable performance, the presumption is made
		 * that all server CellServDB are identical.  This way we
		 * can look up the configuration host alias once and use
		 * it everywhere.  If this proves to be insufficient then
		 * this lookup will have to be done for every server to be
		 * updated which will be very costly; such individual lookups
		 * would naturally be handled by the update worker threads.
		 *
		 * A final presumption is that we can just look at the
		 * server CellServDB on the current database servers to
		 * get the configuration host alias.  The only time this
		 * might get us into trouble is in a re-do scenario.
		 */
		if (!CfgHostGetCellServDbAlias
		    (cfg_host, ctrlBlockp->opHostAlias, &tst2)) {
		    tst = tst2;
		} else if (*ctrlBlockp->opHostAlias == '\0') {
		    /* no alias found; go with config host working name */
		    strcpy(ctrlBlockp->opHostAlias, cfg_host->hostName);
		}
	    }

	    if (tst != 0) {
		free(ctrlBlockp);
	    } else {
		/* fill name blocks, handing each to a worker thread */
		void *nameBlockIter = NULL;
		short workersStarted = 0;

		if (!NameBlockGetBegin
		    (cfg_host, sysControlHost, ctrlBlockp, &nameBlockIter,
		     &tst2)) {
		    tst = tst2;
		} else {
		    cfg_csdb_update_name_t *nameBlockp = NULL;
		    short nameBlockDone = 0;

		    while (!nameBlockDone) {
			nameBlockp = ((cfg_csdb_update_name_t *)
				      malloc(sizeof(*nameBlockp)));

			if (nameBlockp == NULL) {
			    tst = ADMNOMEM;
			    nameBlockDone = 1;

			} else
			    if (!NameBlockGetNext
				(nameBlockIter, nameBlockp, &tst2)) {
			    /* no more entries (or failure) */
			    if (tst2 != ADMITERATORDONE) {
				tst = tst2;
			    }
			    free(nameBlockp);
			    nameBlockDone = 1;

			} else {
			    *maxUpdates += nameBlockp->serverCount;

			    if (StartUpdateWorkerThread(nameBlockp, &tst2)) {
				/* increment worker count; lock not required
				 * until workers given start/abort signal.
				 */
				ctrlBlockp->workersActive++;
				workersStarted = 1;
			    } else {
				tst = tst2;
				free(nameBlockp);
				nameBlockDone = 1;
			    }
			}
		    }

		    if (!NameBlockGetDone(nameBlockIter, &tst2)) {
			tst = tst2;
		    }
		}

		if (workersStarted) {
		    /* worker threads started; set disposition and signal */
		    if (pthread_mutex_lock(&ctrlBlockp->mutex)) {
			tst = ADMMUTEXLOCK;
		    } else {
			if (tst == 0) {
			    /* tell workers to proceed with updates */
			    ctrlBlockp->disposition = CSDB_GO;
			} else {
			    /* tell workers to abort */
			    ctrlBlockp->disposition = CSDB_ABORT;
			}

			if (pthread_mutex_unlock(&ctrlBlockp->mutex)) {
			    tst = ADMMUTEXUNLOCK;
			}
			if (pthread_cond_broadcast(&ctrlBlockp->event)) {
			    tst = ADMCONDSIGNAL;
			}
		    }
		} else {
		    /* no worker threads started */
		    free(ctrlBlockp);
		}
	    }
	}
    }

    if (tst != 0) {
	/* indicate failure */
	rc = 0;
    }
    if (st != NULL) {
	*st = tst;
    }
    return rc;
}
Ejemplo n.º 2
0
/*
 * ClientCellServDbUpdate() -- add or remove a client CellServDB entry.
 *
 *     Common function implementing cfg_ClientCellServDb{Add/Remove}().
 */
static int
ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
		       const char *dbentry, afs_status_p st)
{
    int rc = 1;
    afs_status_t tst2, tst = 0;
    cfg_host_p cfg_host = (cfg_host_p) hostHandle;
    char dbentryFull[MAXHOSTCHARS];

    /* validate parameters and resolve dbentry to fully qualified name */

    if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
	tst = tst2;
    } else if (cellName == NULL || *cellName == '\0') {
	tst = ADMCFGCELLNAMENULL;
    } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
	tst = ADMCFGCELLNAMETOOLONG;
    } else if (dbentry == NULL || *dbentry == '\0') {
	tst = ADMCFGHOSTNAMENULL;
    } else if (strlen(dbentry) > (MAXHOSTCHARS - 1)) {
	tst = ADMCFGHOSTNAMETOOLONG;
    } else if (!cfgutil_HostNameGetFull(dbentry, dbentryFull, &tst2)) {
	tst = tst2;
    }

    /* remote configuration not yet supported in this function */

    if (tst == 0) {
	if (!cfg_host->is_local) {
	    tst = ADMCFGNOTSUPPORTED;
	}
    }

    /* modify local client CellServDB entry for specified cell */

#ifdef AFS_NT40_ENV
    if (tst == 0) {
	CELLSERVDB clientDb;

	if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
	    tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
	} else {
	    CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
	    CELLDBLINE *serverLinep = NULL;
	    int serverLineCount = 0;

	    if (cellLinep != NULL) {
		/* found cellName, now find server to add/remove */
		CELLDBLINE *workingLinep;

		for (workingLinep = cellLinep->pNext; workingLinep != NULL;
		     workingLinep = workingLinep->pNext) {
		    CELLDBLINEINFO lineInfo;

		    if (!CSDB_CrackLine(&lineInfo, workingLinep->szLine)) {
			/* not a server (or cell) line; perhaps a comment */
			continue;
		    } else if (lineInfo.szCell[0] != '\0') {
			/* hit a new cell line */
			break;
		    } else {
			/* found a server line; check if is host of interest */
			short isValid;
			int dbentryAddr = ntohl(lineInfo.ipServer);

			serverLineCount++;

			if (!cfgutil_HostAddressIsValid
			    (dbentryFull, dbentryAddr, &isValid, &tst2)) {
			    tst = tst2;
			    break;
			} else if (isValid) {
			    /* found server of interest */
			    serverLinep = workingLinep;
			    break;
			}
		    }
		}
	    }

	    if (tst == 0) {
		if (updateOp == CSDB_OP_ADD && serverLinep == NULL) {
		    if (cellLinep == NULL) {
			cellLinep =
			    CSDB_AddCell(&clientDb, cellName, NULL, NULL);
		    }

		    if (cellLinep == NULL) {
			tst = ADMNOMEM;
		    } else if (serverLineCount >= MAXHOSTSPERCELL) {
			tst = ADMCFGCLIENTCELLSERVDBNOSPACE;
		    } else {
			const char *dbentryAddrStr;

			if (!cfgutil_HostNameGetAddressString
			    (dbentryFull, &dbentryAddrStr, &tst2)) {
			    tst = tst2;
			} else {
			    serverLinep =
				CSDB_AddCellServer(&clientDb, cellLinep,
						   dbentryAddrStr,
						   dbentryFull);
			    if (serverLinep == NULL) {
				tst = ADMNOMEM;
			    }
			}
		    }
		} else if (updateOp == CSDB_OP_REM && serverLinep != NULL) {
		    (void)CSDB_RemoveLine(&clientDb, serverLinep);
		}

		if (tst == 0) {
		    if (!CSDB_WriteFile(&clientDb)) {
			tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
		    }
		}
	    }

	    CSDB_FreeFile(&clientDb);
	}
    }
#else
    if (tst == 0) {
	/* function not yet implemented for Unix */
	tst = ADMCFGNOTSUPPORTED;
    }
#endif /* AFS_NT40_ENV */

    if (tst != 0) {
	/* indicate failure */
	rc = 0;
    }
    if (st != NULL) {
	*st = tst;
    }
    return rc;
}
Ejemplo n.º 3
0
/*
 * cfg_HostOpen() -- Obtain host configuration handle.
 */
int ADMINAPI
cfg_HostOpen(void *cellHandle,	/* cell handle */
	     const char *hostName,	/* name of host to configure */
	     void **hostHandleP,	/* host config handle */
	     afs_status_p st)
{				/* completion status */
    int rc = 1;
    afs_status_t tst2, tst = 0;
    cfg_host_p cfg_host;
    char fullHostName[MAXHOSTCHARS];

    /* validate parameters and resolve host name to fully qualified name */

    if (!CellHandleIsValid(cellHandle, &tst2)) {
	tst = tst2;
    } else if (hostName == NULL || *hostName == '\0') {
	tst = ADMCFGHOSTNAMENULL;
    } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) {
	tst = ADMCFGHOSTNAMETOOLONG;
    } else if (hostHandleP == NULL) {
	tst = ADMCFGHOSTHANDLEPNULL;
    } else if (!cfgutil_HostNameGetFull(hostName, fullHostName, &tst2)) {
	tst = tst2;
    }

    /* remote configuration not yet supported; hostName must be local host */

    if (tst == 0) {
	short isLocal;

	if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) {
	    tst = tst2;
	} else if (!isLocal) {
	    tst = ADMCFGNOTSUPPORTED;
	}
    }

    /* allocate a host configuration handle */

    if (tst == 0) {
	char *localHostName;

	if ((cfg_host = (cfg_host_p) malloc(sizeof(cfg_host_t))) == NULL) {
	    tst = ADMNOMEM;
	} else if ((localHostName = (char *)malloc(strlen(fullHostName) + 1))
		   == NULL) {
	    free(cfg_host);
	    tst = ADMNOMEM;
	} else {
	    /* initialize handle */
	    cfg_host->begin_magic = BEGIN_MAGIC;
	    cfg_host->is_valid = 1;
	    cfg_host->hostName = localHostName;
	    cfg_host->is_local = 1;	/* not yet supporting remote config */
	    cfg_host->cellHandle = cellHandle;
	    cfg_host->bosHandle = NULL;
	    cfg_host->end_magic = END_MAGIC;

	    strcpy(localHostName, fullHostName);

	    if (!afsclient_CellNameGet
		(cfg_host->cellHandle, &cfg_host->cellName, &tst2)) {
		tst = tst2;
	    } else if (pthread_mutex_init(&cfg_host->mutex, NULL)) {
		tst = ADMMUTEXINIT;
	    }

	    if (tst != 0) {
		/* cell name lookup or mutex initialization failed */
		free(localHostName);
		free(cfg_host);
	    }
	}
    }

    if (tst == 0) {
	/* success; return host config handle to user */
	*hostHandleP = cfg_host;
    } else {
	/* indicate failure */
	rc = 0;
    }
    if (st != NULL) {
	*st = tst;
    }
    return rc;
}