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

📄 db_am.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
	memset(&data, 0, sizeof(data));	F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL);	/*	 * If locking (and we haven't already acquired CDB locks), set the	 * read-modify-write flag.	 */	f_init = DB_SET;	f_next = DB_NEXT_DUP;	if (STD_LOCKING(dbc)) {		f_init |= DB_RMW;		f_next |= DB_RMW;	}	/* Walk through the set of key/data pairs, deleting as we go. */	if ((ret = __db_c_get(dbc, key, &data, f_init)) != 0)		goto err;	/*	 * Hash permits an optimization in DB->del:  since on-page	 * duplicates are stored in a single HKEYDATA structure, it's	 * possible to delete an entire set of them at once, and as	 * the HKEYDATA has to be rebuilt and re-put each time it	 * changes, this is much faster than deleting the duplicates	 * one by one.  Thus, if we're not pointing at an off-page	 * duplicate set, and we're not using secondary indices (in	 * which case we'd have to examine the items one by one anyway),	 * let hash do this "quick delete".	 *	 * !!!	 * Note that this is the only application-executed delete call in	 * Berkeley DB that does not go through the __db_c_del function.	 * If anything other than the delete itself (like a secondary index	 * update) has to happen there in a particular situation, the	 * conditions here should be modified not to call __ham_quick_delete.	 * The ordinary AM-independent alternative will work just fine with	 * a hash;  it'll just be slower.	 */	if (dbp->type == DB_HASH)		if (LIST_FIRST(&dbp->s_secondaries) == NULL &&		    !F_ISSET(dbp, DB_AM_SECONDARY) &&		    dbc->internal->opd == NULL) {			ret = __ham_quick_delete(dbc);			goto done;		}	for (;;) {		if ((ret = __db_c_del(dbc, 0)) != 0)			break;		if ((ret = __db_c_get(dbc, &lkey, &data, f_next)) != 0) {			if (ret == DB_NOTFOUND)				ret = 0;			break;		}	}done:err:	/* Discard the cursor. */	if ((t_ret = __db_c_close(dbc)) != 0 && ret == 0)		ret = t_ret;	return (ret);}/* * __db_sync -- *	Flush the database cache. * * PUBLIC: int __db_sync __P((DB *)); */int__db_sync(dbp)	DB *dbp;{	int ret, t_ret;	ret = 0;	/* If the database was read-only, we're done. */	if (F_ISSET(dbp, DB_AM_RDONLY))		return (0);	/* If it's a Recno tree, write the backing source text file. */	if (dbp->type == DB_RECNO)		ret = __ram_writeback(dbp);	/* If the database was never backed by a database file, we're done. */	if (F_ISSET(dbp, DB_AM_INMEM))		return (ret);	if (dbp->type == DB_QUEUE)		ret = __qam_sync(dbp);	else		/* Flush any dirty pages from the cache to the backing file. */		if ((t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0)			ret = t_ret;	return (ret);}/* * __db_associate -- *	Associate another database as a secondary index to this one. * * PUBLIC: int __db_associate __P((DB *, DB_TXN *, DB *, * PUBLIC:     int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); */int__db_associate(dbp, txn, sdbp, callback, flags)	DB *dbp, *sdbp;	DB_TXN *txn;	int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));	u_int32_t flags;{	DB_ENV *dbenv;	DBC *pdbc, *sdbc;	DBT skey, key, data;	int build, ret, t_ret;	dbenv = dbp->dbenv;	pdbc = sdbc = NULL;	ret = 0;	sdbp->s_callback = callback;	sdbp->s_primary = dbp;	sdbp->stored_get = sdbp->get;	sdbp->get = __db_secondary_get;	sdbp->stored_close = sdbp->close;	sdbp->close = __db_secondary_close_pp;	F_SET(sdbp, DB_AM_SECONDARY);	/*	 * Check to see if the secondary is empty--and thus if we should	 * build it--before we link it in and risk making it show up in	 * other threads.	 */	build = 0;	if (LF_ISSET(DB_CREATE)) {		if ((ret = __db_cursor(sdbp, txn, &sdbc, 0)) != 0)			goto err;		/*		 * We don't care about key or data;  we're just doing		 * an existence check.		 */		memset(&key, 0, sizeof(DBT));		memset(&data, 0, sizeof(DBT));		F_SET(&key, DB_DBT_PARTIAL | DB_DBT_USERMEM);		F_SET(&data, DB_DBT_PARTIAL | DB_DBT_USERMEM);		if ((ret = __db_c_get(sdbc, &key, &data,		    (STD_LOCKING(sdbc) ? DB_RMW : 0) |		    DB_FIRST)) == DB_NOTFOUND) {			build = 1;			ret = 0;		}		/*		 * Secondary cursors have special refcounting close		 * methods.  Be careful.		 */		if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)			ret = t_ret;		/* Reset for later error check. */		sdbc = NULL;		if (ret != 0)			goto err;	}	/*	 * Add the secondary to the list on the primary.  Do it here	 * so that we see any updates that occur while we're walking	 * the primary.	 */	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);	/* See __db_s_next for an explanation of secondary refcounting. */	DB_ASSERT(sdbp->s_refcnt == 0);	sdbp->s_refcnt = 1;	LIST_INSERT_HEAD(&dbp->s_secondaries, sdbp, s_links);	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);	if (build) {		/*		 * We loop through the primary, putting each item we		 * find into the new secondary.		 *		 * If we're using CDB, opening these two cursors puts us		 * in a bit of a locking tangle:  CDB locks are done on the		 * primary, so that we stay deadlock-free, but that means		 * that updating the secondary while we have a read cursor		 * open on the primary will self-block.  To get around this,		 * we force the primary cursor to use the same locker ID		 * as the secondary, so they won't conflict.  This should		 * be harmless even if we're not using CDB.		 */		if ((ret = __db_cursor(sdbp, txn, &sdbc,		    CDB_LOCKING(sdbp->dbenv) ? DB_WRITECURSOR : 0)) != 0)			goto err;		if ((ret = __db_cursor_int(dbp,		    txn, dbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0)			goto err;		/* Lock out other threads, now that we have a locker ID. */		dbp->associate_lid = sdbc->locker;		memset(&key, 0, sizeof(DBT));		memset(&data, 0, sizeof(DBT));		while ((ret = __db_c_get(pdbc, &key, &data, DB_NEXT)) == 0) {			memset(&skey, 0, sizeof(DBT));			if ((ret = callback(sdbp, &key, &data, &skey)) != 0) {				if (ret == DB_DONOTINDEX)					continue;				goto err;			}			if ((ret = __db_c_put(sdbc,			    &skey, &key, DB_UPDATE_SECONDARY)) != 0) {				FREE_IF_NEEDED(sdbp, &skey);				goto err;			}			FREE_IF_NEEDED(sdbp, &skey);		}		if (ret == DB_NOTFOUND)			ret = 0;	}err:	if (sdbc != NULL && (t_ret = __db_c_close(sdbc)) != 0 && ret == 0)		ret = t_ret;	if (pdbc != NULL && (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)		ret = t_ret;	dbp->associate_lid = DB_LOCK_INVALIDID;	return (ret);}/* * __db_secondary_get -- *	This wrapper function for DB->pget() is the DB->get() function *	on a database which has been made into a secondary index. */static int__db_secondary_get(sdbp, txn, skey, data, flags)	DB *sdbp;	DB_TXN *txn;	DBT *skey, *data;	u_int32_t flags;{	DB_ASSERT(F_ISSET(sdbp, DB_AM_SECONDARY));	return (__db_pget_pp(sdbp, txn, skey, NULL, data, flags));}/* * __db_secondary_close -- *	Wrapper function for DB->close() which we use on secondaries to *	manage refcounting and make sure we don't close them underneath *	a primary that is updating. * * PUBLIC: int __db_secondary_close __P((DB *, u_int32_t)); */int__db_secondary_close(sdbp, flags)	DB *sdbp;	u_int32_t flags;{	DB *primary;	int doclose;	doclose = 0;	primary = sdbp->s_primary;	MUTEX_THREAD_LOCK(primary->dbenv, primary->mutexp);	/*	 * Check the refcount--if it was at 1 when we were called, no	 * thread is currently updating this secondary through the primary,	 * so it's safe to close it for real.	 *	 * If it's not safe to do the close now, we do nothing;  the	 * database will actually be closed when the refcount is decremented,	 * which can happen in either __db_s_next or __db_s_done.	 */	DB_ASSERT(sdbp->s_refcnt != 0);	if (--sdbp->s_refcnt == 0) {		LIST_REMOVE(sdbp, s_links);		/* We don't want to call close while the mutex is held. */		doclose = 1;	}	MUTEX_THREAD_UNLOCK(primary->dbenv, primary->mutexp);	/*	 * sdbp->close is this function;  call the real one explicitly if	 * need be.	 */	return (doclose ? __db_close(sdbp, NULL, flags) : 0);}/* * __db_append_primary -- *	Perform the secondary index updates necessary to put(DB_APPEND) *	a record to a primary database. */static int__db_append_primary(dbc, key, data)	DBC *dbc;	DBT *key, *data;{	DB *dbp, *sdbp;	DBC *sdbc, *pdbc;	DBT oldpkey, pkey, pdata, skey;	int cmp, ret, t_ret;	dbp = dbc->dbp;	sdbp = NULL;	ret = 0;	/*	 * Worrying about partial appends seems a little like worrying	 * about Linear A character encodings.  But we support those	 * too if your application understands them.	 */	pdbc = NULL;	if (F_ISSET(data, DB_DBT_PARTIAL) || F_ISSET(key, DB_DBT_PARTIAL)) {		/*		 * The dbc we were passed is all set to pass things		 * back to the user;  we can't safely do a call on it.		 * Dup the cursor, grab the real data item (we don't		 * care what the key is--we've been passed it directly),		 * and use that instead of the data DBT we were passed.		 *		 * Note that we can get away with this simple get because		 * an appended item is by definition new, and the		 * correctly-constructed full data item from this partial		 * put is on the page waiting for us.		 */		if ((ret = __db_c_idup(dbc, &pdbc, DB_POSITION)) != 0)			return (ret);		memset(&pkey, 0, sizeof(DBT));		memset(&pdata, 0, sizeof(DBT));		if ((ret = __db_c_get(pdbc, &pkey, &pdata, DB_CURRENT)) != 0)			goto err;		key = &pkey;		data = &pdata;	}	/*	 * Loop through the secondary indices, putting a new item in	 * each that points to the appended item.	 *	 * This is much like the loop in "step 3" in __db_c_put, so	 * I'm not commenting heavily here;  it was unclean to excerpt	 * just that section into a common function, but the basic	 * overview is the same here.	 */	for (sdbp = __db_s_first(dbp);	    sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp)) {		memset(&skey, 0, sizeof(DBT));		if ((ret = sdbp->s_callback(sdbp, key, data, &skey)) != 0) {			if (ret == DB_DONOTINDEX)				continue;			else				goto err;		}		if ((ret = __db_cursor_int(sdbp, dbc->txn, sdbp->type,		    PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) {			FREE_IF_NEEDED(sdbp, &skey);			goto err;		}		if (CDB_LOCKING(sdbp->dbenv)) {			DB_ASSERT(sdbc->mylock.off == LOCK_INVALID);			F_SET(sdbc, DBC_WRITER);		}		/*		 * Since we know we have a new primary key, it can't be a		 * duplicate duplicate in the secondary.  It can be a		 * duplicate in a secondary that doesn't support duplicates,		 * however, so we need to be careful to avoid an overwrite		 * (which would corrupt our index).		 */		if (!F_ISSET(sdbp, DB_AM_DUP)) {			memset(&oldpkey, 0, sizeof(DBT));			F_SET(&oldpkey, DB_DBT_MALLOC);			ret = __db_c_get(sdbc, &skey, &oldpkey,			    DB_SET | (STD_LOCKING(dbc) ? DB_RMW : 0));			if (ret == 0) {				cmp = __bam_defcmp(sdbp, &oldpkey, key);				/*				 * XXX				 * This needs to use the right free function				 * as soon as this is possible.				 */				__os_ufree(sdbp->dbenv,				    oldpkey.data);				if (cmp != 0) {					__db_err(sdbp->dbenv, "%s%s",			    "Append results in a non-unique secondary key in",			    " an index not configured to support duplicates");					ret = EINVAL;					goto err1;				}			} else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)				goto err1;		}		ret = __db_c_put(sdbc, &skey, key, DB_UPDATE_SECONDARY);err1:		FREE_IF_NEEDED(sdbp, &skey);		if ((t_ret = __db_c_close(sdbc)) != 0 && ret == 0)			ret = t_ret;		if (ret != 0)			goto err;	}err:	if (pdbc != NULL && (t_ret = __db_c_close(pdbc)) != 0 && ret == 0)		ret = t_ret;	if (sdbp != NULL && (t_ret = __db_s_done(sdbp)) != 0 && ret == 0)		ret = t_ret;	return (ret);}

⌨️ 快捷键说明

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