⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 env_region.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
	 * and acquire, and we have to know if it fails.  (It CAN fail, e.g.,	 * SunOS, when using fcntl(2) for locking and using an in-memory	 * filesystem as the database home.  But you knew that, I'm sure -- it	 * probably wasn't even worth mentioning.)	 */	if ((ret = __db_mutex_setup(dbenv, infop, &renv->mutex,	    MUTEX_NO_RECORD | MUTEX_NO_RLOCK)) != 0) {		__db_err(dbenv, "%s: unable to initialize environment lock: %s",		    infop->name, db_strerror(ret));		goto err;	}	if (!F_ISSET(&renv->mutex, MUTEX_IGNORE) &&	    (ret = __db_mutex_lock(dbenv, &renv->mutex)) != 0) {		__db_err(dbenv, "%s: unable to acquire environment lock: %s",		    infop->name, db_strerror(ret));		goto err;	}	/*	 * Get the underlying REGION structure for this environment.  Note,	 * we created the underlying OS region before we acquired the REGION	 * structure, which is backwards from the normal procedure.  Update	 * the REGION structure.	 */	if ((ret = __db_des_get(dbenv, infop, infop, &rp)) != 0) {find_err:	__db_err(dbenv,		    "%s: unable to find environment", infop->name);		if (ret == 0)			ret = EINVAL;		goto err;	}	infop->rp = rp;	rp->size = tregion.size;	rp->segid = tregion.segid;	/*	 * !!!	 * If we create an environment where regions are public and in system	 * memory, we have to inform processes joining the environment how to	 * attach to the shared memory segment.  So, we write the shared memory	 * identifier into the file, to be read by those other processes.	 *	 * XXX	 * This is really OS-layer information, but I can't see any easy way	 * to move it down there without passing down information that it has	 * no right to know, e.g., that this is the one-and-only REGENV region	 * and not some other random region.	 */	if (tregion.segid != INVALID_REGION_SEGID) {		ref.size = tregion.size;		ref.segid = tregion.segid;		if ((ret = __os_write(		    dbenv, dbenv->lockfhp, &ref, sizeof(ref), &nrw)) != 0) {			__db_err(dbenv,			    "%s: unable to write out public environment ID: %s",			    infop->name, db_strerror(ret));			goto err;		}	}	/*	 * If not doing thread locking, we need to save the file handle for	 * fcntl(2) locking.  Otherwise, discard the handle, we no longer	 * need it, and the less contact between the buffer cache and the VM,	 * the better.	 */#if defined(HAVE_MUTEX_THREADS)	if (dbenv->lockfhp != NULL) {		 (void)__os_closehandle(dbenv, dbenv->lockfhp);		 dbenv->lockfhp = NULL;	}#endif	/* Validate the file. */	renv->magic = DB_REGION_MAGIC;	/* Discard our lock. */	MUTEX_UNLOCK(dbenv, &renv->mutex);	/* Everything looks good, we're done. */	dbenv->reginfo = infop;	return (0);err:retry:	/* Close any open file handle. */	if (dbenv->lockfhp != NULL) {		(void)__os_closehandle(dbenv, dbenv->lockfhp);		dbenv->lockfhp = NULL;	}	/*	 * If we joined or created the region, detach from it.  If we created	 * it, destroy it.  Note, there's a path in the above code where we're	 * using a temporary REGION structure because we haven't yet allocated	 * the real one.  In that case the region address (addr) will be filled	 * in, but the REGION pointer (rp) won't.  Fix it.	 */	if (infop->addr != NULL) {		if (infop->rp == NULL)			infop->rp = &tregion;		/* Reset the addr value that we "corrected" above. */		infop->addr = infop->primary;		(void)__os_r_detach(dbenv,		    infop, F_ISSET(infop, REGION_CREATE));	}	/* Free the allocated name and/or REGINFO structure. */	if (infop->name != NULL)		__os_free(dbenv, infop->name);	__os_free(dbenv, infop);	/* If we had a temporary error, wait awhile and try again. */	if (ret == 0) {		if (++retry_cnt > 3) {			__db_err(dbenv, "unable to join the environment");			ret = EAGAIN;		} else {			__os_sleep(dbenv, retry_cnt * 3, 0);			goto loop;		}	}	return (ret);}/* * __db_e_detach -- *	Detach from the environment. * * PUBLIC: int __db_e_detach __P((DB_ENV *, int)); */int__db_e_detach(dbenv, destroy)	DB_ENV *dbenv;	int destroy;{	REGENV *renv;	REGINFO *infop;	infop = dbenv->reginfo;	renv = infop->primary;	if (F_ISSET(dbenv, DB_ENV_PRIVATE))		destroy = 1;	/* Lock the environment. */	MUTEX_LOCK(dbenv, &renv->mutex);	/* Decrement the reference count. */	if (renv->refcnt == 0) {		__db_err(dbenv,		    "region %lu (environment): reference count went negative",		    (u_long)infop->rp->id);	} else		--renv->refcnt;	/* Release the lock. */	MUTEX_UNLOCK(dbenv, &renv->mutex);	/* Close the locking file handle. */	if (dbenv->lockfhp != NULL) {		(void)__os_closehandle(dbenv, dbenv->lockfhp);		dbenv->lockfhp = NULL;	}	/*	 * If we are destroying the environment, destroy any system resources	 * the crypto and replication systems may have acquired and put in the	 * main region.	 */	if (destroy) {#ifdef HAVE_CRYPTO		(void)__crypto_region_destroy(dbenv);#endif		(void)__rep_region_destroy(dbenv);	}	/*	 * Release the region, and kill our reference.	 *	 * If we are destroying the environment, destroy any system resources	 * backing the mutex.	 */	if (destroy) {		(void)__db_mutex_destroy(&renv->mutex);		(void)__db_mutex_destroy(&infop->rp->mutex);		/*		 * Only free the REGION structure itself if it was separately		 * allocated from the heap.		 */		if (F_ISSET(dbenv, DB_ENV_PRIVATE))			__db_shalloc_free(infop, infop->rp);	}	/* Reset the addr value that we "corrected" above. */	infop->addr = infop->primary;	(void)__os_r_detach(dbenv, infop, destroy);	if (infop->name != NULL)		__os_free(dbenv, infop->name);	/*	 * We set the DB_ENV->reginfo field to NULL here and discard its memory.	 * DB_ENV->remove calls __dbenv_remove to do the region remove, and	 * __dbenv_remove attached and then detaches from the region.  We don't	 * want to return to DB_ENV->remove with a non-NULL DB_ENV->reginfo	 * field because it will attempt to detach again as part of its cleanup.	 */	__os_free(dbenv, dbenv->reginfo);	dbenv->reginfo = NULL;	return (0);}/* * __db_e_remove -- *	Discard an environment if it's not in use. * * PUBLIC: int __db_e_remove __P((DB_ENV *, u_int32_t)); */int__db_e_remove(dbenv, flags)	DB_ENV *dbenv;	u_int32_t flags;{	REGENV *renv;	REGINFO *infop, reginfo;	REGION *rp;	u_int32_t db_env_reset;	int force, ret;	force = LF_ISSET(DB_FORCE) ? 1 : 0;	/*	 * This routine has to walk a nasty line between not looking into	 * the environment (which may be corrupted after an app or system	 * crash), and removing everything that needs removing.  What we	 * do is:	 *	1. Connect to the environment (so it better be OK).	 *	2. If the environment is in use (reference count is non-zero),	 *	   return EBUSY.	 *	3. Overwrite the magic number so that any threads of control	 *	   attempting to connect will backoff and retry.	 *	4. Walk the list of regions.  Connect to each region and then	 *	   disconnect with the destroy flag set.  This shouldn't cause	 *	   any problems, even if the region is corrupted, because we	 *	   should never be looking inside the region.	 *	5. Walk the list of files in the directory, unlinking any	 *	   files that match a region name.  Unlink the environment	 *	   file last.	 *	 * If the force flag is set, we do not acquire any locks during this	 * process.	 */	db_env_reset = F_ISSET(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC);	if (force)		F_SET(dbenv, DB_ENV_NOLOCKING);	F_SET(dbenv, DB_ENV_NOPANIC);	/* Join the environment. */	if ((ret = __db_e_attach(dbenv, NULL)) != 0) {		/*		 * If we can't join it, we assume that's because it doesn't		 * exist.  It would be better to know why we failed, but it		 * probably isn't important.		 */		ret = 0;		if (force)			goto remfiles;		goto done;	}	infop = dbenv->reginfo;	renv = infop->primary;	/* Lock the environment. */	MUTEX_LOCK(dbenv, &renv->mutex);	/*	 * If it's in use, we're done unless we're forcing the issue or the	 * environment has panic'd.  (Presumably, if the environment panic'd,	 * the thread holding the reference count may not have cleaned up.)	 */	if (renv->refcnt == 1 || renv->envpanic == 1 || force) {		/*		 * Set the panic flag and overwrite the magic number.		 *		 * !!!		 * From this point on, there's no going back, we pretty		 * much ignore errors, and just whack on whatever we can.		 */		renv->envpanic = 1;		renv->magic = 0;		/*		 * Unlock the environment.  We should no longer need the lock		 * because we've poisoned the pool, but we can't continue to		 * hold it either, because other routines may want it.		 */		MUTEX_UNLOCK(dbenv, &renv->mutex);		/*		 * Attach to each sub-region and destroy it.		 *		 * !!!		 * The REGION_CREATE_OK flag is set for Windows/95 -- regions		 * are zero'd out when the last reference to the region goes		 * away, in which case the underlying OS region code requires		 * callers be prepared to create the region in order to join it.		 */		memset(&reginfo, 0, sizeof(reginfo));		for (rp = SH_LIST_FIRST(&renv->regionq, __db_region);		    rp != NULL; rp = SH_LIST_NEXT(rp, q, __db_region)) {			if (rp->type == REGION_TYPE_ENV)				continue;			/*			 * If we get here and can't attach and/or detach to the			 * region, it's a mess.  Ignore errors, there's nothing			 * we can do about them.			 */			reginfo.id = rp->id;			reginfo.flags = REGION_CREATE_OK;			if (__db_r_attach(dbenv, &reginfo, 0) == 0) {				R_UNLOCK(dbenv, &reginfo);				(void)__db_r_detach(dbenv, &reginfo, 1);			}		}		/* Destroy the environment's region. */		(void)__db_e_detach(dbenv, 1);		/* Discard any remaining physical files. */remfiles:	(void)__db_e_remfile(dbenv);	} else {		/* Unlock the environment. */		MUTEX_UNLOCK(dbenv, &renv->mutex);		/* Discard the environment. */		(void)__db_e_detach(dbenv, 0);		ret = EBUSY;	}done:	F_CLR(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC);	F_SET(dbenv, db_env_reset);	return (ret);}/* * __db_e_remfile -- *	Discard any region files in the filesystem. */static int__db_e_remfile(dbenv)	DB_ENV *dbenv;{	int cnt, fcnt, lastrm, ret;	const char *dir;	char saved_char, *p, **names, *path, buf[sizeof(DB_REGION_FMT) + 20];	/* Get the full path of a file in the environment. */	(void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);	if ((ret = __db_appname(dbenv, DB_APP_NONE, buf, 0, NULL, &path)) != 0)		return (ret);	/* Get the parent directory for the environment. */	if ((p = __db_rpath(path)) == NULL) {		p = path;		saved_char = *p;		dir = PATH_DOT;	} else {		saved_char = *p;		*p = '\0';		dir = path;	}	/* Get the list of file names. */	if ((ret = __os_dirlist(dbenv, dir, &names, &fcnt)) != 0)		__db_err(dbenv, "%s: %s", dir, db_strerror(ret));	/* Restore the path, and free it. */	*p = saved_char;	__os_free(dbenv, path);	if (ret != 0)		return (ret);	/*	 * Remove files from the region directory.	 */	for (lastrm = -1, cnt = fcnt; --cnt >= 0;) {		/* Skip anything outside our name space. */		if (strncmp(names[cnt],		    DB_REGION_PREFIX, sizeof(DB_REGION_PREFIX) - 1))			continue;		/* Skip queue extent files. */		if (strncmp(names[cnt], "__dbq.", 6) == 0)			continue;		/* Skip replication files. */		if (strncmp(names[cnt], "__db.rep.", 9) == 0)			continue;		/*		 * Remove the primary environment region last, because it's		 * the key to this whole mess.		 */		if (strcmp(names[cnt], DB_REGION_ENV) == 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -