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

📄 db_cam.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2000-2002 *	Sleepycat Software.  All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: db_cam.c,v 11.114 2002/09/03 15:44:46 krinsky Exp $";#endif /* not lint */#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/log.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 = (dbp)->dbenv->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);/* * Copy the lock info from one cursor to another, so that locking * in CDB can be done in the context of an internally-duplicated * or off-page-duplicate cursor. */#define	CDB_LOCKING_COPY(dbp, dbc_o, dbc_n)				\	if (CDB_LOCKING((dbp)->dbenv) &&				\	    F_ISSET((dbc_o), DBC_WRITECURSOR | DBC_WRITEDUP)) { \		memcpy(&(dbc_n)->mylock, &(dbc_o)->mylock,		\		    sizeof((dbc_o)->mylock));				\		/* This lock isn't ours to put--just discard it on close. */ \		F_SET((dbc_n), DBC_WRITEDUP);				\	}/* * __db_c_close -- *	Close the cursor. * * 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;	ret = 0;	PANIC_CHECK(dbenv);	/*	 * If the cursor is already closed we have a serious problem, and we	 * assume that the cursor isn't on the active queue.  Don't do any of	 * the remaining cursor close processing.	 */	if (!F_ISSET(dbc, DBC_ACTIVE)) {		if (dbp != NULL)			__db_err(dbenv, "Closing already-closed cursor");		DB_ASSERT(0);		return (EINVAL);	}	cp = dbc->internal;	opd = cp->opd;	/*	 * 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 acess-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)) {		/*		 * If DBC_WRITEDUP is set, the cursor is an internally		 * duplicated write cursor and the lock isn't ours to put.		 *		 * 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 (!F_ISSET(dbc, DBC_WRITEDUP) && LOCK_ISSET(dbc->mylock)) {			if ((t_ret = dbenv->lock_put(			    dbenv, &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));		F_CLR(dbc, DBC_WRITEDUP);	}	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 = dbenv->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 *, u_int32_t)); */int__db_c_count(dbc, recnop, flags)	DBC *dbc;	db_recno_t *recnop;	u_int32_t flags;{	DB *dbp;	int ret;	/*	 * 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.	 */	dbp = dbc->dbp;	PANIC_CHECK(dbp->dbenv);	/* Check for invalid flags. */	if ((ret = __db_ccountchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)		return (ret);	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;	default:		return (__db_unknown_type(dbp->dbenv,		    "__db_c_count", dbp->type));	}	return (0);}/* * __db_c_del -- *	Delete using a cursor. * * 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;	/*	 * 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.	 */	dbp = dbc->dbp;	PANIC_CHECK(dbp->dbenv);	/* Check for invalid flags. */	if ((ret = __db_cdelchk(dbp, flags, IS_INITIALIZED(dbc))) != 0)		return (ret);	/* Check for consistent transaction usage. */	if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0)		return (ret);	DEBUG_LWRITE(dbc, dbc->txn, "db_c_del", NULL, NULL, flags);	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);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;{	DB_ENV *dbenv;	DB *dbp;	DBC *dbc_n, *dbc_nopd;	int ret;	dbp = dbc_orig->dbp;	dbenv = dbp->dbenv;	dbc_n = dbc_nopd = NULL;	PANIC_CHECK(dbp->dbenv);	/*	 * We can never have two write cursors open in CDB, so do not	 * allow duplication of a write cursor.	 */	if (flags != DB_POSITIONI &&	    F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR)) {		__db_err(dbenv, "Cannot duplicate writeable cursor");		return (EINVAL);	}	/* Allocate a new cursor and initialize it. */	if ((ret = __db_c_idup(dbc_orig, &dbc_n, flags)) != 0)		goto err;	*dbcp = dbc_n;	/*	 * If we're in CDB, and this isn't an internal duplication (in which	 * case we're explicitly overriding CDB locking), the duplicated	 * cursor needs its own read lock.  (We know it's not a write cursor	 * because we wouldn't have made it this far;  you can't dup them.)	 */	if (CDB_LOCKING(dbenv) && flags != DB_POSITIONI) {		DB_ASSERT(!F_ISSET(dbc_orig, DBC_WRITER | DBC_WRITECURSOR));		if ((ret = dbenv->lock_get(dbenv, dbc_n->locker, 0,		    &dbc_n->lock_dbt, DB_LOCK_READ, &dbc_n->mylock)) != 0) {			(void)__db_c_close(dbc_n);			return (ret);		}	}	/*	 * 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;	}	/* Copy the dirty read flag to the new cursor. */	F_SET(dbc_n, F_ISSET(dbc_orig, DBC_DIRTY_READ));	return (0);err:	if (dbc_n != NULL)		(void)dbc_n->c_close(dbc_n);	if (dbc_nopd != NULL)		(void)dbc_nopd->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_icursor(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);	/* If the user wants the cursor positioned, do it here.  */	if (flags == DB_POSITION || flags == DB_POSITIONI) {		int_n = dbc_n->internal;		int_orig = dbc_orig->internal;

⌨️ 快捷键说明

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