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

📄 db_iface.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 4 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 *	Sleepycat Software.  All rights reserved. * * $Id: db_iface.c,v 11.121 2004/10/07 17:33:32 sue 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"			/* For __db_no_hash_am(). */#include "dbinc/qam.h"			/* For __db_no_queue_am(). */#include "dbinc/lock.h"#include "dbinc/log.h"#include "dbinc/mp.h"static int __db_associate_arg __P((DB *, DB *,	       int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t));static int __db_c_get_arg __P((DBC *, DBT *, DBT *, u_int32_t));static int __db_c_pget_arg __P((DBC *, DBT *, u_int32_t));static int __db_c_put_arg __P((DBC *, DBT *, DBT *, u_int32_t));static int __db_curinval __P((const DB_ENV *));static int __db_cursor_arg __P((DB *, u_int32_t));static int __db_del_arg __P((DB *, u_int32_t));static int __db_get_arg __P((const DB *, const DBT *, DBT *, u_int32_t));static int __db_join_arg __P((DB *, DBC **, u_int32_t));static int __db_open_arg __P((DB *,	       DB_TXN *, const char *, const char *, DBTYPE, u_int32_t));static int __db_pget_arg __P((DB *, DBT *, u_int32_t));static int __db_put_arg __P((DB *, DBT *, DBT *, u_int32_t));static int __db_rdonly __P((const DB_ENV *, const char *));static int __dbt_ferr __P((const DB *, const char *, const DBT *, int));/* * A database should be required to be readonly if it's been explicitly * specified as such or if we're a client in a replicated environment and * we don't have the special "client-writer" designation. */#define	IS_READONLY(dbp)						\    (F_ISSET(dbp, DB_AM_RDONLY) ||					\    (IS_REP_CLIENT((dbp)->dbenv) &&					\    !F_ISSET((dbp), DB_AM_CL_WRITER)))/* * These functions implement the Berkeley DB API.  They are organized in a * layered fashion.  The interface functions (XXX_pp) perform all generic * error checks (for example, PANIC'd region, replication state change * in progress, inconsistent transaction usage), call function-specific * check routines (_arg) to check for proper flag usage, etc., do pre-amble * processing (incrementing handle counts, handling auto-commit), call the * function and then do post-amble processing (DB_AUTO_COMMIT, dec handle * counts). * * So, the basic structure is: *	Check for generic errors *	Call function-specific check routine *	Increment handle count *	Create internal transaction if necessary *	Call underlying worker function *	Commit/abort internal transaction if necessary *	Decrement handle count *//* * __db_associate_pp -- *	DB->associate pre/post processing. * * PUBLIC: int __db_associate_pp __P((DB *, DB_TXN *, DB *, * PUBLIC:     int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); */int__db_associate_pp(dbp, txn, sdbp, callback, flags)	DB *dbp, *sdbp;	DB_TXN *txn;	int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));	u_int32_t flags;{	DBC *sdbc;	DB_ENV *dbenv;	int handle_check, ret, txn_local;	dbenv = dbp->dbenv;	PANIC_CHECK(dbenv);	if ((ret = __db_associate_arg(dbp, sdbp, callback, flags)) != 0)		return (ret);	/*	 * Secondary cursors may have the primary's lock file ID, so we need	 * to make sure that no older cursors are lying around when we make	 * the transition.	 */	if (TAILQ_FIRST(&sdbp->active_queue) != NULL ||	    TAILQ_FIRST(&sdbp->join_queue) != NULL) {		__db_err(dbenv,    "Databases may not become secondary indices while cursors are open");		return (EINVAL);	}	/*	 * Create a local transaction as necessary, check for consistent	 * transaction usage, and, if we have no transaction but do have	 * locking on, acquire a locker id for the handle lock acquisition.	 */	txn_local = 0;	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)			return (ret);		txn_local = 1;		LF_CLR(DB_AUTO_COMMIT);	} else if (txn != NULL && !TXN_ON(dbenv))		return (__db_not_txn_env(dbenv));	/* Check for consistent transaction usage. */	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)		goto err;	/* Check for replication block. */	handle_check = IS_REPLICATED(dbenv, dbp);	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)		goto err;	while ((sdbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL)		if ((ret = __db_c_destroy(sdbc)) != 0)			break;	if (ret == 0)		ret = __db_associate(dbp, txn, sdbp, callback, flags);	/* Release replication block. */	if (handle_check)		__env_db_rep_exit(dbenv);err:	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);}/* * __db_associate_arg -- *	Check DB->associate arguments. */static int__db_associate_arg(dbp, sdbp, callback, flags)	DB *dbp, *sdbp;	int (*callback) __P((DB *, const DBT *, const DBT *, DBT *));	u_int32_t flags;{	DB_ENV *dbenv;	int ret;	dbenv = dbp->dbenv;	if (F_ISSET(sdbp, DB_AM_SECONDARY)) {		__db_err(dbenv,		    "Secondary index handles may not be re-associated");		return (EINVAL);	}	if (F_ISSET(dbp, DB_AM_SECONDARY)) {		__db_err(dbenv,		    "Secondary indices may not be used as primary databases");		return (EINVAL);	}	if (F_ISSET(dbp, DB_AM_DUP)) {		__db_err(dbenv,		    "Primary databases may not be configured with duplicates");		return (EINVAL);	}	if (F_ISSET(dbp, DB_AM_RENUMBER)) {		__db_err(dbenv,	    "Renumbering recno databases may not be used as primary databases");		return (EINVAL);	}	if (dbp->dbenv != sdbp->dbenv &&	    (!F_ISSET(dbp->dbenv, DB_ENV_DBLOCAL) ||	     !F_ISSET(sdbp->dbenv, DB_ENV_DBLOCAL))) {		__db_err(dbenv,	    "The primary and secondary must be opened in the same environment");		return (EINVAL);	}	if ((DB_IS_THREADED(dbp) && !DB_IS_THREADED(sdbp)) ||	    (!DB_IS_THREADED(dbp) && DB_IS_THREADED(sdbp))) {		__db_err(dbenv,	    "The DB_THREAD setting must be the same for primary and secondary");		return (EINVAL);	}	if (callback == NULL &&	    (!F_ISSET(dbp, DB_AM_RDONLY) || !F_ISSET(sdbp, DB_AM_RDONLY))) {		__db_err(dbenv,    "Callback function may be NULL only when database handles are read-only");		return (EINVAL);	}	if ((ret = __db_fchk(dbenv,	    "DB->associate", flags, DB_CREATE | DB_AUTO_COMMIT)) != 0)		return (ret);	return (0);}/* * __db_close_pp -- *	DB->close pre/post processing. * * PUBLIC: int __db_close_pp __P((DB *, u_int32_t)); */int__db_close_pp(dbp, flags)	DB *dbp;	u_int32_t flags;{	DB_ENV *dbenv;	int handle_check, ret, t_ret;	dbenv = dbp->dbenv;	ret = 0;	PANIC_CHECK(dbenv);	/*	 * !!!	 * The actual argument checking is simple, do it inline.	 *	 * Validate arguments and complain if they're wrong, but as a DB	 * handle destructor, we can't fail.	 */	if (flags != 0 && flags != DB_NOSYNC &&	    (t_ret = __db_ferr(dbenv, "DB->close", 0)) != 0 && ret == 0)		ret = t_ret;	/* Check for replication block. */	handle_check = IS_REPLICATED(dbenv, dbp);	if (handle_check &&	    (t_ret = __db_rep_enter(dbp, 0, 0, 0)) != 0) {		handle_check = 0;		if (ret == 0)			ret = t_ret;	}	if ((t_ret = __db_close(dbp, NULL, flags)) != 0 && ret == 0)		ret = t_ret;	/* Release replication block. */	if (handle_check)		__env_db_rep_exit(dbenv);	return (ret);}/* * __db_cursor_pp -- *	DB->cursor pre/post processing. * * PUBLIC: int __db_cursor_pp __P((DB *, DB_TXN *, DBC **, u_int32_t)); */int__db_cursor_pp(dbp, txn, dbcp, flags)	DB *dbp;	DB_TXN *txn;	DBC **dbcp;	u_int32_t flags;{	DB_ENV *dbenv;	int handle_check, ret;	dbenv = dbp->dbenv;	PANIC_CHECK(dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->cursor");	if ((ret = __db_cursor_arg(dbp, flags)) != 0)		return (ret);	/*	 * Check for consistent transaction usage.  For now, assume that	 * this cursor might be used for read operations only (in which	 * case it may not require a txn).  We'll check more stringently	 * in c_del and c_put.  (Note that this all means that the	 * read-op txn tests have to be a subset of the write-op ones.)	 */	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0)		return (ret);	/* Check for replication block. */	handle_check = IS_REPLICATED(dbenv, dbp);	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)		return (ret);	ret = __db_cursor(dbp, txn, dbcp, flags);	/* Release replication block. */	if (handle_check)		__env_db_rep_exit(dbenv);	return (ret);}/* * __db_cursor -- *	DB->cursor. * * PUBLIC: int __db_cursor __P((DB *, DB_TXN *, DBC **, u_int32_t)); */int__db_cursor(dbp, txn, dbcp, flags)	DB *dbp;	DB_TXN *txn;	DBC **dbcp;	u_int32_t flags;{	DB_ENV *dbenv;	DBC *dbc;	db_lockmode_t mode;	u_int32_t op;	int ret;	dbenv = dbp->dbenv;	if ((ret = __db_cursor_int(dbp,	    txn, dbp->type, PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0)		return (ret);	/*	 * If this is CDB, do all the locking in the interface, which is	 * right here.	 */	if (CDB_LOCKING(dbenv)) {		op = LF_ISSET(DB_OPFLAGS_MASK);		mode = (op == DB_WRITELOCK) ? DB_LOCK_WRITE :		    ((op == DB_WRITECURSOR) ? DB_LOCK_IWRITE : DB_LOCK_READ);		if ((ret = __lock_get(dbenv, dbc->locker, 0,		    &dbc->lock_dbt, mode, &dbc->mylock)) != 0)			goto err;		if (op == DB_WRITECURSOR)			F_SET(dbc, DBC_WRITECURSOR);		if (op == DB_WRITELOCK)			F_SET(dbc, DBC_WRITER);	}	if (LF_ISSET(DB_DIRTY_READ) ||	    (txn != NULL && F_ISSET(txn, TXN_DIRTY_READ)))		F_SET(dbc, DBC_DIRTY_READ);	if (LF_ISSET(DB_DEGREE_2) ||	    (txn != NULL && F_ISSET(txn, TXN_DEGREE_2)))		F_SET(dbc, DBC_DEGREE_2);	*dbcp = dbc;	return (0);err:	(void)__db_c_close(dbc);	return (ret);}/* * __db_cursor_arg -- *	Check DB->cursor arguments. */static int__db_cursor_arg(dbp, flags)	DB *dbp;	u_int32_t flags;{	DB_ENV *dbenv;	dbenv = dbp->dbenv;	/*	 * DB_DIRTY_READ  and DB_DGREE_2 are the only valid bit-flags	 * and requires locking.	 */	if (LF_ISSET(DB_DIRTY_READ | DB_DEGREE_2)) {		if (!LOCKING_ON(dbenv))			return (__db_fnl(dbenv, "DB->cursor"));		LF_CLR(DB_DIRTY_READ | DB_DEGREE_2);	}	/* Check for invalid function flags. */	switch (flags) {	case 0:		break;	case DB_WRITECURSOR:		if (IS_READONLY(dbp))			return (__db_rdonly(dbenv, "DB->cursor"));		if (!CDB_LOCKING(dbenv))			return (__db_ferr(dbenv, "DB->cursor", 0));		break;	case DB_WRITELOCK:		if (IS_READONLY(dbp))			return (__db_rdonly(dbenv, "DB->cursor"));		break;	default:		return (__db_ferr(dbenv, "DB->cursor", 0));	}	return (0);}/* * __db_del_pp -- *	DB->del pre/post processing. * * PUBLIC: int __db_del_pp __P((DB *, DB_TXN *, DBT *, u_int32_t)); */int__db_del_pp(dbp, txn, key, flags)	DB *dbp;	DB_TXN *txn;	DBT *key;	u_int32_t flags;{	DB_ENV *dbenv;	int handle_check, ret, txn_local;	dbenv = dbp->dbenv;	PANIC_CHECK(dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del");	if ((ret = __db_del_arg(dbp, flags)) != 0)		return (ret);	/* Create local transaction as necessary. */	if (IS_AUTO_COMMIT(dbenv, txn, flags)) {		if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)			return (ret);		txn_local = 1;		LF_CLR(DB_AUTO_COMMIT);	} else		txn_local = 0;	/* Check for consistent transaction usage. */	if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0)		goto err;	/* Check for replication block. */	handle_check = IS_REPLICATED(dbenv, dbp);	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, txn != NULL)) != 0)		goto err;	ret = __db_del(dbp, txn, key, flags);	/* Release replication block. */	if (handle_check)		__env_db_rep_exit(dbenv);err:	return (txn_local ? __db_txn_auto_resolve(dbenv, txn, 0, ret) : ret);}/* * __db_del_arg -- *	Check DB->delete arguments. */static int__db_del_arg(dbp, flags)	DB *dbp;	u_int32_t flags;{	DB_ENV *dbenv;	dbenv = dbp->dbenv;	/* Check for changes to a read-only tree. */	if (IS_READONLY(dbp))		return (__db_rdonly(dbenv, "DB->del"));	/* Check for invalid function flags. */	LF_CLR(DB_AUTO_COMMIT);	switch (flags) {	case 0:		break;	default:		return (__db_ferr(dbenv, "DB->del", 0));	}	return (0);}/* * db_fd_pp -- *	DB->fd pre/post processing. * * PUBLIC: int __db_fd_pp __P((DB *, int *)); */int__db_fd_pp(dbp, fdp)	DB *dbp;	int *fdp;{	DB_ENV *dbenv;	DB_FH *fhp;	int handle_check, ret;	dbenv = dbp->dbenv;	PANIC_CHECK(dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->fd");	/* Check for replication block. */	handle_check = IS_REPLICATED(dbenv, dbp);	if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0)		return (ret);	/*	 * !!!	 * There's no argument checking to be done.	 *	 * !!!	 * The actual method call is simple, do it inline.	 *	 * XXX	 * Truly spectacular layering violation.	 */	if ((ret = __mp_xxx_fh(dbp->mpf, &fhp)) != 0)		goto err;	if (fhp == NULL) {		*fdp = -1;		__db_err(dbenv,		    "Database does not have a valid file handle");		ret = ENOENT;	} else		*fdp = fhp->fd;err:	/* Release replication block. */	if (handle_check)		__env_db_rep_exit(dbenv);	return (ret);}/* * __db_get_pp -- *	DB->get pre/post processing. * * PUBLIC: int __db_get_pp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); */int__db_get_pp(dbp, txn, key, data, flags)	DB *dbp;	DB_TXN *txn;	DBT *key, *data;	u_int32_t flags;{	DB_ENV *dbenv;	u_int32_t mode;	int handle_check, ret, txn_local;	dbenv = dbp->dbenv;	PANIC_CHECK(dbenv);	DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get");	if ((ret = __db_get_arg(dbp, key, data, flags)) != 0)		return (ret);	mode = 0;	txn_local = 0;	if (LF_ISSET(DB_DIRTY_READ))		mode = DB_DIRTY_READ;	else if ((flags & DB_OPFLAGS_MASK) == DB_CONSUME ||	    (flags & DB_OPFLAGS_MASK) == DB_CONSUME_WAIT) {		mode = DB_WRITELOCK;		if (IS_AUTO_COMMIT(dbenv, txn, flags)) {			if ((ret = __db_txn_auto_init(dbenv, &txn)) != 0)				return (ret);			txn_local = 1;			LF_CLR(DB_AUTO_COMMIT);		}	}

⌨️ 快捷键说明

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