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

📄 fop_util.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
			dbp->lid = txn->txnid;		else if (dbp->lid == DB_LOCK_INVALIDID) {			if ((ret = __lock_id(dbenv, &dbp->lid)) != 0)				goto err;		}	}	/*	 * We are about to open a file handle and then possibly close it.	 * We cannot close handles if we are doing FCNTL locking.  However,	 * there is no way to pass the FCNTL flag into this routine via the	 * user API.  The only way we can get in here and be doing FCNTL	 * locking is if we are trying to clean up an open that was called	 * with FCNTL locking.  In that case, the save_fhp should already be	 * set.  So, we use that field to tell us if we need to make sure	 * that we shouldn't close the handle.	 */	fhp = dbp->saved_open_fhp;	DB_ASSERT(LF_ISSET(DB_FCNTL_LOCKING) || fhp == NULL);	/*	 * Lock environment to protect file open.  That will enable us to	 * read the meta-data page and get the fileid so that we can lock	 * the handle.	 */	GET_ENVLOCK(dbenv, dbp->lid, &elock);	if (fhp == NULL &&	    (ret = __os_open(dbenv, name, DB_OSO_RDONLY, 0, &fhp)) != 0)		goto err;	if ((ret = __fop_read_meta(dbenv,	    name, mbuf, sizeof(mbuf), fhp, 0, NULL)) != 0)		goto err;	if ((ret =	    __db_meta_setup(dbenv, dbp, name, (DBMETA *)mbuf, flags, 1)) != 0)		goto err;	/*	 * Now, get the handle lock.  We first try with NOWAIT, because if	 * we have to wait, we're going to have to close the file and reopen	 * it, so that if there is someone else removing it, our open doesn't	 * prevent that.	 */	if ((ret = __fop_lock_handle(dbenv,	    dbp, dbp->lid, DB_LOCK_WRITE, NULL, DB_LOCK_NOWAIT)) != 0) {		/*		 * Close the file, block on the lock, clean up the dbp, and		 * then start all over again.		 */		if (!LF_ISSET(DB_FCNTL_LOCKING)) {			(void)__os_closehandle(dbenv, fhp);			fhp = NULL;		}		if (ret == DB_LOCK_NOTEXIST) {			if ((ret = __ENV_LPUT(dbenv, elock, 0)) != 0)				goto err;		} else if (ret != DB_LOCK_NOTGRANTED ||		    (txn != NULL && F_ISSET(txn, TXN_NOWAIT)))			goto err;		else if ((ret = __fop_lock_handle(dbenv,		    dbp, dbp->lid, DB_LOCK_WRITE, &elock, 0)) != 0 &&		    ret != DB_LOCK_NOTEXIST)			goto err;		if (txn != NULL)			dbp->lid = DB_LOCK_INVALIDID;		(void)__db_refresh(dbp, txn, DB_NOSYNC, NULL);		goto retry;	} else if ((ret = __ENV_LPUT(dbenv, elock, 0)) != 0)		goto err;	/* Check if the file is already open. */	if ((ret = __memp_get_refcnt(dbenv, dbp->fileid, &refcnt)) != 0)		goto err;	/*	 * Now, error check.  If the file is already open (refcnt != 0), then	 * we must have it open (since we got the lock) and we need to panic,	 * because this is a self deadlock and the application has a bug.	 * If the file isn't open, but it's in the midst of a rename then	 * this file doesn't really exist.	 */	if (refcnt != 0) {		__db_err(dbenv,"Attempting to remove file open in current transaction causing self-deadlock");		ret = __db_panic(dbenv, DB_LOCK_DEADLOCK);	} else if (F_ISSET(dbp, DB_AM_IN_RENAME))		ret = ENOENT;	if (0) {err:		(void)__ENV_LPUT(dbenv, elock, 0);	}	if (fhp != NULL && !LF_ISSET(DB_FCNTL_LOCKING))		(void)__os_closehandle(dbenv, fhp);	/*	 * If we are going to proceed with the removal, then we need to make	 * sure that we don't leave any pages around in the mpool.	 */	if (ret == 0)		F_SET(dbp, DB_AM_DISCARD);	return (ret);}/* * __fop_read_meta -- *	Read the meta-data page from a file and return it in buf. * * PUBLIC: int __fop_read_meta __P((DB_ENV *, const char *, * PUBLIC:     u_int8_t *, size_t, DB_FH *, int, size_t *)); */int__fop_read_meta(dbenv, name, buf, size, fhp, errok, nbytesp)	DB_ENV *dbenv;	const char *name;	u_int8_t *buf;	size_t size;	DB_FH *fhp;	int errok;	size_t *nbytesp;{	size_t nr;	int ret;	/*	 * Our caller wants to know the number of bytes read, even if we	 * return an error.	 */	if (nbytesp != NULL)		*nbytesp = 0;	nr = 0;	ret = __os_read(dbenv, fhp, buf, size, &nr);	if (nbytesp != NULL)		*nbytesp = nr;	if (ret != 0) {		if (!errok)			__db_err(dbenv, "%s: %s", name, db_strerror(ret));		goto err;	}	if (nr != size) {		if (!errok)			__db_err(dbenv,			    "%s: unexpected file type or format", name);		ret = EINVAL;	}err:	return (ret);}/* * __fop_dummy -- *	This implements the creation and name swapping of dummy files that * we use for remove and rename (remove is simply a rename with a delayed * remove). * * PUBLIC: int __fop_dummy __P((DB *, * PUBLIC:     DB_TXN *, const char *, const char *, u_int32_t)); */int__fop_dummy(dbp, txn, old, new, flags)	DB *dbp;	DB_TXN *txn;	const char *old, *new;	u_int32_t flags;{	DB *tmpdbp, *t2dbp;	DB_ENV *dbenv;	DB_FH *fhp;	DB_LOCK elock;	DB_LSN lsn;	DBT fiddbt, namedbt, tmpdbt;	DB_TXN *stxn;	char *back;	char *realback, *realnew, *realold;	int ret, t_ret;	size_t len;	u_int8_t mbuf[DBMETASIZE];	u_int32_t dflags, locker, stxnid;	dbenv = dbp->dbenv;	LOCK_INIT(elock);	realback = NULL;	realnew = NULL;	realold = NULL;	back = NULL;	stxn = NULL;	tmpdbp = t2dbp = NULL;	fhp = NULL;	dflags = F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0;	DB_ASSERT(txn != NULL);	locker = txn->txnid;	/* Begin sub transaction to encapsulate the rename. */	if (TXN_ON(dbenv) && (ret = __txn_begin(dbenv, txn, &stxn, 0)) != 0)		goto err;	/* We need to create a dummy file as a place holder. */	if ((ret = __db_backup_name(dbenv, new, stxn, &back)) != 0)		goto err;	if ((ret = __db_appname(dbenv,	    DB_APP_DATA, back, flags, NULL, &realback)) != 0)		goto err;	if ((ret = __fop_create(dbenv,	    stxn, NULL, back, DB_APP_DATA, 0, dflags)) != 0)		goto err;	memset(mbuf, 0, sizeof(mbuf));	if ((ret =	    __os_fileid(dbenv, realback, 1, ((DBMETA *)mbuf)->uid)) != 0)		goto err;	((DBMETA *)mbuf)->magic = DB_RENAMEMAGIC;	if ((ret = __fop_write(dbenv, stxn, back,	    DB_APP_DATA, NULL, 0, 0, 0, mbuf, DBMETASIZE, 1, dflags)) != 0)		goto err;	/* Create a dummy dbp handle. */	if ((ret = db_create(&tmpdbp, dbenv, 0)) != 0)		goto err;	memcpy(tmpdbp->fileid, ((DBMETA *)mbuf)->uid, DB_FILE_ID_LEN);	/* Now, lock the name space while we initialize this file. */	if ((ret = __db_appname(dbenv,	    DB_APP_DATA, new, 0, NULL, &realnew)) != 0)		goto err;	GET_ENVLOCK(dbenv, locker, &elock);	if (__os_exists(realnew, NULL) == 0) {		/*		 * It is possible that the only reason this file exists is		 * because we've done a previous rename of it and we have		 * left a placeholder here.  We need to check for that case		 * and allow this rename to succeed if that's the case.		 */		if ((ret = db_create(&t2dbp, dbenv, 0)) != 0)			goto err;		if ((ret = __os_open(dbenv, realnew, 0, 0, &fhp)) != 0)			goto err;		if ((ret = __fop_read_meta(dbenv,		    realnew, mbuf, sizeof(mbuf), fhp, 0, &len)) != 0 ||		    (ret = __db_meta_setup(dbenv,		    t2dbp, realnew, (DBMETA *)mbuf, 0, 1)) != 0) {			ret = EEXIST;			goto err;		}		/*		 * Now, try to acquire the handle lock.  If it's from our txn,		 * then we'll get the lock.  If it's not, then someone else has		 * it locked,  and we need to report this as an error.  If we		 * know we can get the lock, we can immediately release it,		 * which we need to do since this is a temporary handle.		 */		if ((ret = __fop_lock_handle(dbenv,		    t2dbp, locker, DB_LOCK_WRITE, NULL, DB_LOCK_NOWAIT)) != 0)			ret = EEXIST;		else {			(void)__lock_put(dbenv, &t2dbp->handle_lock, 0);			if (!F_ISSET(t2dbp, DB_AM_IN_RENAME))				ret = EEXIST;		}		if ((t_ret = __os_closehandle(dbenv, fhp)) != 0 && ret == 0)			ret = t_ret;		fhp = NULL;		if (ret != 0)			goto err;	}	/*	 * While we have the namespace locked, do the renames and then	 * swap for the handle lock.	 */	if ((ret = __fop_rename(dbenv,	    stxn, old, new, dbp->fileid, DB_APP_DATA, dflags)) != 0)		goto err;	if ((ret = __fop_rename(dbenv,	    stxn, back, old, tmpdbp->fileid, DB_APP_DATA, dflags)) != 0)		goto err;	if ((ret = __fop_lock_handle(dbenv,	    tmpdbp, locker, DB_LOCK_WRITE, &elock, NOWAIT_FLAG(txn))) != 0)		goto err;	/*	 * We just acquired a transactional lock on the tmp handle.	 * We need to null out the tmp handle's lock so that it	 * doesn't create problems for us in the close path.	 */	LOCK_INIT(tmpdbp->handle_lock);	if (stxn != NULL) {		/* Commit the child. */		stxnid = stxn->txnid;		ret = __txn_commit(stxn, 0);		stxn = NULL;		/* Now log the child information in the parent. */		memset(&fiddbt, 0, sizeof(fiddbt));		memset(&tmpdbt, 0, sizeof(fiddbt));		memset(&namedbt, 0, sizeof(namedbt));		fiddbt.data = dbp->fileid;		fiddbt.size = DB_FILE_ID_LEN;		tmpdbt.data = tmpdbp->fileid;		tmpdbt.size = DB_FILE_ID_LEN;		namedbt.data = (void *)old;		namedbt.size = (u_int32_t)strlen(old) + 1;		if ((t_ret =		    __fop_file_remove_log(dbenv, txn, &lsn, 0, &fiddbt,		    &tmpdbt, &namedbt, DB_APP_DATA, stxnid)) != 0 && ret == 0)			ret = t_ret;	}	/* This is a delayed delete of the dummy file. */	if ((ret = __db_appname(dbenv,	    DB_APP_DATA, old, flags, NULL, &realold)) != 0)		goto err;	if ((ret = __txn_remevent(dbenv, txn, realold, NULL)) != 0)		goto err;err:	(void)__ENV_LPUT(dbenv, elock, 0);	if (stxn != NULL)		(void)__txn_abort(stxn);	if (tmpdbp != NULL &&	    (t_ret = __db_close(tmpdbp, NULL, 0)) != 0 && ret == 0)		ret = t_ret;	if (t2dbp != NULL &&	    (t_ret = __db_close(t2dbp, NULL, 0)) != 0 && ret == 0)		ret = t_ret;	if (fhp != NULL)		(void)__os_closehandle(dbenv, fhp);	if (realold != NULL)		__os_free(dbenv, realold);	if (realnew != NULL)		__os_free(dbenv, realnew);	if (realback != NULL)		__os_free(dbenv, realback);	if (back != NULL)		__os_free(dbenv, back);	return (ret);}/* * __fop_dbrename -- *	Do the appropriate file locking and file system operations * to effect a dbrename in the absence of transactions (__fop_dummy * and the subsequent calls in __db_rename do the work for the * transactional case). * * PUBLIC: int __fop_dbrename __P((DB *, const char *, const char *)); */int__fop_dbrename(dbp, old, new)	DB *dbp;	const char *old, *new;{	DB_ENV *dbenv;	DB_LOCK elock;	char *real_new, *real_old;	int ret, t_ret;	dbenv = dbp->dbenv;	real_new = NULL;	real_old = NULL;	LOCK_INIT(elock);	/* Find the real newname of the file. */	if ((ret = __db_appname(dbenv,	    DB_APP_DATA, new, 0, NULL, &real_new)) != 0)		goto err;	/*	 * It is an error to rename a file over one that already exists,	 * as that wouldn't be transaction-safe.	 */	GET_ENVLOCK(dbenv, dbp->lid, &elock);	if (__os_exists(real_new, NULL) == 0) {		ret = EEXIST;		__db_err(dbenv, "rename: file %s exists", real_new);		goto err;	}	if ((ret = __db_appname(dbenv,	    DB_APP_DATA, old, 0, NULL, &real_old)) != 0)		goto err;	ret = __memp_nameop(dbenv, dbp->fileid, new, real_old, real_new);err:	if ((t_ret = __ENV_LPUT(dbenv, elock, 0)) != 0 && ret == 0)		ret = t_ret;	if (real_old != NULL)		__os_free(dbenv, real_old);	if (real_new != NULL)		__os_free(dbenv, real_new);	return (ret);}

⌨️ 快捷键说明

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