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

📄 db_cam.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 5 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2000-2004 *	Sleepycat Software.  All rights reserved. * * $Id: db_cam.c,v 11.156 2004/09/28 18:07:32 ubell Exp $ */#include "db_config.h"#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/db_shash.h"#include "dbinc/btree.h"#include "dbinc/hash.h"#include "dbinc/lock.h"#include "dbinc/mp.h"#include "dbinc/qam.h"static int __db_buildpartial __P((DB *, DBT *, DBT *, DBT *));static int __db_c_cleanup __P((DBC *, DBC *, int));static int __db_c_del_secondary __P((DBC *));static int __db_c_pget_recno __P((DBC *, DBT *, DBT *, u_int32_t));static int __db_wrlock_err __P((DB_ENV *));#define	CDB_LOCKING_INIT(dbp, dbc)					\	/*								\	 * If we are running CDB, this had better be either a write	\	 * cursor or an immediate writer.  If it's a regular writer,	\	 * that means we have an IWRITE lock and we need to upgrade	\	 * it to a write lock.						\	 */								\	if (CDB_LOCKING((dbp)->dbenv)) {				\		if (!F_ISSET(dbc, DBC_WRITECURSOR | DBC_WRITER))	\			return (__db_wrlock_err(dbp->dbenv));		\									\		if (F_ISSET(dbc, DBC_WRITECURSOR) &&			\		    (ret = __lock_get((dbp)->dbenv,			\		    (dbc)->locker, DB_LOCK_UPGRADE, &(dbc)->lock_dbt,	\		    DB_LOCK_WRITE, &(dbc)->mylock)) != 0)		\			return (ret);					\	}#define	CDB_LOCKING_DONE(dbp, dbc)					\	/* Release the upgraded lock. */				\	if (F_ISSET(dbc, DBC_WRITECURSOR))				\		(void)__lock_downgrade(					\		    (dbp)->dbenv, &(dbc)->mylock, DB_LOCK_IWRITE, 0);/* * __db_c_close -- *	DBC->c_close. * * PUBLIC: int __db_c_close __P((DBC *)); */int__db_c_close(dbc)	DBC *dbc;{	DB *dbp;	DBC *opd;	DBC_INTERNAL *cp;	DB_ENV *dbenv;	int ret, t_ret;	dbp = dbc->dbp;	dbenv = dbp->dbenv;	cp = dbc->internal;	opd = cp->opd;	ret = 0;	/*	 * Remove the cursor(s) from the active queue.  We may be closing two	 * cursors at once here, a top-level one and a lower-level, off-page	 * duplicate one.  The access-method specific cursor close routine must	 * close both of them in a single call.	 *	 * !!!	 * Cursors must be removed from the active queue before calling the	 * access specific cursor close routine, btree depends on having that	 * order of operations.	 */	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);	if (opd != NULL) {		F_CLR(opd, DBC_ACTIVE);		TAILQ_REMOVE(&dbp->active_queue, opd, links);	}	F_CLR(dbc, DBC_ACTIVE);	TAILQ_REMOVE(&dbp->active_queue, dbc, links);	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);	/* Call the access specific cursor close routine. */	if ((t_ret =	    dbc->c_am_close(dbc, PGNO_INVALID, NULL)) != 0 && ret == 0)		ret = t_ret;	/*	 * Release the lock after calling the access method specific close	 * routine, a Btree cursor may have had pending deletes.	 */	if (CDB_LOCKING(dbenv)) {		/*		 * Also, be sure not to free anything if mylock.off is		 * INVALID;  in some cases, such as idup'ed read cursors		 * and secondary update cursors, a cursor in a CDB		 * environment may not have a lock at all.		 */		if ((t_ret = __LPUT(dbc, dbc->mylock)) != 0 && ret == 0)			ret = t_ret;		/* For safety's sake, since this is going on the free queue. */		memset(&dbc->mylock, 0, sizeof(dbc->mylock));		if (opd != NULL)			memset(&opd->mylock, 0, sizeof(opd->mylock));	}	if (dbc->txn != NULL)		dbc->txn->cursors--;	/* Move the cursor(s) to the free queue. */	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);	if (opd != NULL) {		if (dbc->txn != NULL)			dbc->txn->cursors--;		TAILQ_INSERT_TAIL(&dbp->free_queue, opd, links);		opd = NULL;	}	TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links);	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);	return (ret);}/* * __db_c_destroy -- *	Destroy the cursor, called after DBC->c_close. * * PUBLIC: int __db_c_destroy __P((DBC *)); */int__db_c_destroy(dbc)	DBC *dbc;{	DB *dbp;	DB_ENV *dbenv;	int ret, t_ret;	dbp = dbc->dbp;	dbenv = dbp->dbenv;	/* Remove the cursor from the free queue. */	MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);	TAILQ_REMOVE(&dbp->free_queue, dbc, links);	MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp);	/* Free up allocated memory. */	if (dbc->my_rskey.data != NULL)		__os_free(dbenv, dbc->my_rskey.data);	if (dbc->my_rkey.data != NULL)		__os_free(dbenv, dbc->my_rkey.data);	if (dbc->my_rdata.data != NULL)		__os_free(dbenv, dbc->my_rdata.data);	/* Call the access specific cursor destroy routine. */	ret = dbc->c_am_destroy == NULL ? 0 : dbc->c_am_destroy(dbc);	/*	 * Release the lock id for this cursor.	 */	if (LOCKING_ON(dbenv) &&	    F_ISSET(dbc, DBC_OWN_LID) &&	    (t_ret = __lock_id_free(dbenv, dbc->lid)) != 0 && ret == 0)		ret = t_ret;	__os_free(dbenv, dbc);	return (ret);}/* * __db_c_count -- *	Return a count of duplicate data items. * * PUBLIC: int __db_c_count __P((DBC *, db_recno_t *)); */int__db_c_count(dbc, recnop)	DBC *dbc;	db_recno_t *recnop;{	DB_ENV *dbenv;	int ret;	dbenv = dbc->dbp->dbenv;	/*	 * Cursor Cleanup Note:	 * All of the cursors passed to the underlying access methods by this	 * routine are not duplicated and will not be cleaned up on return.	 * So, pages/locks that the cursor references must be resolved by the	 * underlying functions.	 */	switch (dbc->dbtype) {	case DB_QUEUE:	case DB_RECNO:		*recnop = 1;		break;	case DB_HASH:		if (dbc->internal->opd == NULL) {			if ((ret = __ham_c_count(dbc, recnop)) != 0)				return (ret);			break;		}		/* FALLTHROUGH */	case DB_BTREE:		if ((ret = __bam_c_count(dbc, recnop)) != 0)			return (ret);		break;	case DB_UNKNOWN:	default:		return (__db_unknown_type(dbenv, "__db_c_count", dbc->dbtype));	}	return (0);}/* * __db_c_del -- *	DBC->c_del. * * PUBLIC: int __db_c_del __P((DBC *, u_int32_t)); */int__db_c_del(dbc, flags)	DBC *dbc;	u_int32_t flags;{	DB *dbp;	DBC *opd;	int ret, t_ret;	dbp = dbc->dbp;	/*	 * Cursor Cleanup Note:	 * All of the cursors passed to the underlying access methods by this	 * routine are not duplicated and will not be cleaned up on return.	 * So, pages/locks that the cursor references must be resolved by the	 * underlying functions.	 */	CDB_LOCKING_INIT(dbp, dbc);	/*	 * If we're a secondary index, and DB_UPDATE_SECONDARY isn't set	 * (which it only is if we're being called from a primary update),	 * then we need to call through to the primary and delete the item.	 *	 * Note that this will delete the current item;  we don't need to	 * delete it ourselves as well, so we can just goto done.	 */	if (flags != DB_UPDATE_SECONDARY && F_ISSET(dbp, DB_AM_SECONDARY)) {		ret = __db_c_del_secondary(dbc);		goto done;	}	/*	 * If we are a primary and have secondary indices, go through	 * and delete any secondary keys that point at the current record.	 */	if (LIST_FIRST(&dbp->s_secondaries) != NULL &&	    (ret = __db_c_del_primary(dbc)) != 0)		goto done;	/*	 * Off-page duplicate trees are locked in the primary tree, that is,	 * we acquire a write lock in the primary tree and no locks in the	 * off-page dup tree.  If the del operation is done in an off-page	 * duplicate tree, call the primary cursor's upgrade routine first.	 */	opd = dbc->internal->opd;	if (opd == NULL)		ret = dbc->c_am_del(dbc);	else		if ((ret = dbc->c_am_writelock(dbc)) == 0)			ret = opd->c_am_del(opd);	/*	 * If this was an update that is supporting dirty reads	 * then we may have just swapped our read for a write lock	 * which is held by the surviving cursor.  We need	 * to explicitly downgrade this lock.  The closed cursor	 * may only have had a read lock.	 */	if (F_ISSET(dbc->dbp, DB_AM_DIRTY) &&	    dbc->internal->lock_mode == DB_LOCK_WRITE) {		if ((t_ret =		    __TLPUT(dbc, dbc->internal->lock)) != 0 && ret == 0)			ret = t_ret;		if (t_ret == 0)			dbc->internal->lock_mode = DB_LOCK_WWRITE;	}done:	CDB_LOCKING_DONE(dbp, dbc);	return (ret);}/* * __db_c_dup -- *	Duplicate a cursor * * PUBLIC: int __db_c_dup __P((DBC *, DBC **, u_int32_t)); */int__db_c_dup(dbc_orig, dbcp, flags)	DBC *dbc_orig;	DBC **dbcp;	u_int32_t flags;{	DBC *dbc_n, *dbc_nopd;	int ret;	dbc_n = dbc_nopd = NULL;	/* Allocate a new cursor and initialize it. */	if ((ret = __db_c_idup(dbc_orig, &dbc_n, flags)) != 0)		goto err;	*dbcp = dbc_n;	/*	 * If the cursor references an off-page duplicate tree, allocate a	 * new cursor for that tree and initialize it.	 */	if (dbc_orig->internal->opd != NULL) {		if ((ret =		   __db_c_idup(dbc_orig->internal->opd, &dbc_nopd, flags)) != 0)			goto err;		dbc_n->internal->opd = dbc_nopd;	}	return (0);err:	if (dbc_n != NULL)		(void)__db_c_close(dbc_n);	if (dbc_nopd != NULL)		(void)__db_c_close(dbc_nopd);	return (ret);}/* * __db_c_idup -- *	Internal version of __db_c_dup. * * PUBLIC: int __db_c_idup __P((DBC *, DBC **, u_int32_t)); */int__db_c_idup(dbc_orig, dbcp, flags)	DBC *dbc_orig, **dbcp;	u_int32_t flags;{	DB *dbp;	DBC *dbc_n;	DBC_INTERNAL *int_n, *int_orig;	int ret;	dbp = dbc_orig->dbp;	dbc_n = *dbcp;	if ((ret = __db_cursor_int(dbp, dbc_orig->txn, dbc_orig->dbtype,	    dbc_orig->internal->root, F_ISSET(dbc_orig, DBC_OPD),	    dbc_orig->locker, &dbc_n)) != 0)		return (ret);	/* Position the cursor if requested, acquiring the necessary locks. */	if (flags == DB_POSITION) {		int_n = dbc_n->internal;		int_orig = dbc_orig->internal;		dbc_n->flags |= dbc_orig->flags & ~DBC_OWN_LID;		int_n->indx = int_orig->indx;		int_n->pgno = int_orig->pgno;		int_n->root = int_orig->root;		int_n->lock_mode = int_orig->lock_mode;		switch (dbc_orig->dbtype) {		case DB_QUEUE:			if ((ret = __qam_c_dup(dbc_orig, dbc_n)) != 0)				goto err;			break;		case DB_BTREE:		case DB_RECNO:			if ((ret = __bam_c_dup(dbc_orig, dbc_n)) != 0)				goto err;			break;		case DB_HASH:			if ((ret = __ham_c_dup(dbc_orig, dbc_n)) != 0)				goto err;			break;		case DB_UNKNOWN:		default:			ret = __db_unknown_type(dbp->dbenv,			    "__db_c_idup", dbc_orig->dbtype);			goto err;		}	}	/* Copy the locking flags to the new cursor. */	F_SET(dbc_n,	    F_ISSET(dbc_orig, DBC_WRITECURSOR | DBC_DIRTY_READ | DBC_DEGREE_2));	/*	 * If we're in CDB and this isn't an offpage dup cursor, then	 * we need to get a lock for the duplicated cursor.	 */	if (CDB_LOCKING(dbp->dbenv) && !F_ISSET(dbc_n, DBC_OPD) &&	    (ret = __lock_get(dbp->dbenv, dbc_n->locker, 0,	    &dbc_n->lock_dbt, F_ISSET(dbc_orig, DBC_WRITECURSOR) ?	    DB_LOCK_IWRITE : DB_LOCK_READ, &dbc_n->mylock)) != 0)		goto err;	*dbcp = dbc_n;	return (0);err:	(void)__db_c_close(dbc_n);	return (ret);}/* * __db_c_newopd -- *	Create a new off-page duplicate cursor. * * PUBLIC: int __db_c_newopd __P((DBC *, db_pgno_t, DBC *, DBC **)); */int__db_c_newopd(dbc_parent, root, oldopd, dbcp)	DBC *dbc_parent;	db_pgno_t root;	DBC *oldopd;	DBC **dbcp;

⌨️ 快捷键说明

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