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

📄 txn.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2002 *	Sleepycat Software.  All rights reserved. *//* * Copyright (c) 1995, 1996 *	The President and Fellows of Harvard University.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Margo Seltzer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: txn.c,v 11.179 2002/08/29 17:41:17 margo Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <stdlib.h>#if TIME_WITH_SYS_TIME#include <sys/time.h>#include <time.h>#else#if HAVE_SYS_TIME_H#include <sys/time.h>#else#include <time.h>#endif#endif#include <string.h>#endif#include "db_int.h"#include "dbinc/crypto.h"#include "dbinc/hmac.h"#include "dbinc/db_page.h"#include "dbinc/db_shash.h"#include "dbinc/hash.h"#include "dbinc/lock.h"#include "dbinc/log.h"#include "dbinc/txn.h"#define	SET_LOG_FLAGS(dbenv, txnp, lflags)				\	do {								\		lflags = DB_COMMIT | DB_PERMANENT;			\		if (F_ISSET(txnp, TXN_SYNC))				\			lflags |= DB_FLUSH;				\		else if (!F_ISSET(txnp, TXN_NOSYNC) &&			\		    !F_ISSET(dbenv, DB_ENV_TXN_NOSYNC)) {		\			if (F_ISSET(dbenv, DB_ENV_TXN_WRITE_NOSYNC))	\				lflags |= DB_WRNOSYNC;			\			else						\				lflags |= DB_FLUSH;			\		}							\	} while (0)/* * __txn_isvalid enumerated types.  We cannot simply use the transaction * statuses, because different statuses need to be handled differently * depending on the caller. */typedef enum {	TXN_OP_ABORT,	TXN_OP_COMMIT,	TXN_OP_DISCARD,	TXN_OP_PREPARE} txnop_t;static int  __txn_begin_int __P((DB_TXN *, int));static int  __txn_end __P((DB_TXN *, int));static int  __txn_isvalid __P((const DB_TXN *, TXN_DETAIL **, txnop_t));static int  __txn_set_timeout __P(( DB_TXN *, db_timeout_t, u_int32_t));static int  __txn_undo __P((DB_TXN *));#ifndef db_create/* * txn_abort -- * txn_begin -- * txn_commit -- * * When we switched to methods in 4.0, we guessed txn_{abort,begin,commit} * were the interfaces applications would likely use and not be willing to * change, due to the sheer volume of the calls.  Provide wrappers -- we * could do txn_abort and txn_commit using macros, but not txn_begin, as * the name of the field is txn_begin, we didn't want to modify it. * * The issue with txn_begin hits us in another way.  If configured with the * --with-uniquename option, we use #defines to re-define DB's interfaces * to unique names.  We can't do that for these functions because txn_begin * is also a field name in the DB_ENV structure, and the #defines we use go * at the end of the db.h file -- we get control too late to #define a field * name.  So, modify the script that generates the unique names #defines to * not generate them for these three functions, and don't include the three * functions in libraries built with that configuration option. * * EXTERN: int txn_abort __P((DB_TXN *)); * EXTERN: int txn_begin __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t)); * EXTERN: int txn_commit __P((DB_TXN *, u_int32_t)); */inttxn_abort(txnp)	DB_TXN *txnp;{	return (txnp->abort(txnp));}inttxn_begin(dbenv, parent, txnpp, flags)	DB_ENV *dbenv;	DB_TXN *parent, **txnpp;	u_int32_t flags;{	return (dbenv->txn_begin(dbenv, parent, txnpp, flags));}inttxn_commit(txnp, flags)	DB_TXN *txnp;	u_int32_t flags;{	return (txnp->commit(txnp, flags));}#endif /* !db_create *//* * __txn_begin -- *	This is a wrapper to the actual begin process.  Normal transaction * begin allocates a DB_TXN structure for the caller, while XA transaction * begin does not.  Other than that, both call into common __txn_begin_int * code. * * Internally, we use TXN_DETAIL structures, but the DB_TXN structure * provides access to the transaction ID and the offset in the transaction * region of the TXN_DETAIL structure. * * PUBLIC: int __txn_begin __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t)); */int__txn_begin(dbenv, parent, txnpp, flags)	DB_ENV *dbenv;	DB_TXN *parent, **txnpp;	u_int32_t flags;{	DB_LOCKREGION *region;	DB_TXN *txn;	int ret;	*txnpp = NULL;	PANIC_CHECK(dbenv);	ENV_REQUIRES_CONFIG(dbenv, dbenv->tx_handle, "txn_begin", DB_INIT_TXN);	if ((ret = __db_fchk(dbenv,	    "txn_begin", flags,	    DB_DIRTY_READ | DB_TXN_NOWAIT |	    DB_TXN_NOSYNC | DB_TXN_SYNC)) != 0)		return (ret);	if ((ret = __db_fcchk(dbenv,	    "txn_begin", flags, DB_TXN_NOSYNC, DB_TXN_SYNC)) != 0)		return (ret);	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_TXN), &txn)) != 0)		return (ret);	txn->mgrp = dbenv->tx_handle;	txn->parent = parent;	TAILQ_INIT(&txn->kids);	TAILQ_INIT(&txn->events);	txn->flags = TXN_MALLOC;	if (LF_ISSET(DB_DIRTY_READ))		F_SET(txn, TXN_DIRTY_READ);	if (LF_ISSET(DB_TXN_NOSYNC))		F_SET(txn, TXN_NOSYNC);	if (LF_ISSET(DB_TXN_SYNC))		F_SET(txn, TXN_SYNC);	if (LF_ISSET(DB_TXN_NOWAIT))		F_SET(txn, TXN_NOWAIT);	if ((ret = __txn_begin_int(txn, 0)) != 0)		goto err;	if (parent != NULL)		TAILQ_INSERT_HEAD(&parent->kids, txn, klinks);	if (LOCKING_ON(dbenv)) {		region = ((DB_LOCKTAB *)dbenv->lk_handle)->reginfo.primary;		if (parent != NULL) {			ret = __lock_inherit_timeout(dbenv,			    parent->txnid, txn->txnid);			/* No parent locker set yet. */			if (ret == EINVAL) {				parent = NULL;				ret = 0;			}			if (ret != 0)				goto err;		}		/*		 * Parent is NULL if we have no parent		 * or it has no timeouts set.		 */		if (parent == NULL && region->tx_timeout != 0)			if ((ret = __lock_set_timeout(dbenv, txn->txnid,			    region->tx_timeout, DB_SET_TXN_TIMEOUT)) != 0)				goto err;	}	*txnpp = txn;	return (0);err:	__os_free(dbenv, txn);	return (ret);}/* * __txn_xa_begin -- *	XA version of txn_begin. * * PUBLIC: int __txn_xa_begin __P((DB_ENV *, DB_TXN *)); */int__txn_xa_begin(dbenv, txn)	DB_ENV *dbenv;	DB_TXN *txn;{	PANIC_CHECK(dbenv);	memset(txn, 0, sizeof(DB_TXN));	txn->mgrp = dbenv->tx_handle;	TAILQ_INIT(&txn->kids);	TAILQ_INIT(&txn->events);	return (__txn_begin_int(txn, 0));}/* * __txn_compensate_begin *	Begin an compensation transaction.  This is a special interface * that is used only for transactions that must be started to compensate * for actions during an abort.  Currently only used for allocations. * * PUBLIC: int __txn_compensate_begin __P((DB_ENV *, DB_TXN **txnp)); */int__txn_compensate_begin(dbenv, txnpp)	DB_ENV *dbenv;	DB_TXN **txnpp;{	DB_TXN *txn;	int ret;	PANIC_CHECK(dbenv);	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_TXN), &txn)) != 0)		return (ret);	txn->mgrp = dbenv->tx_handle;	TAILQ_INIT(&txn->kids);	TAILQ_INIT(&txn->events);	txn->flags = TXN_MALLOC;	F_SET(txn, TXN_COMPENSATE);	*txnpp = txn;	return (__txn_begin_int(txn, 1));}/* * __txn_begin_int -- *	Normal DB version of txn_begin. */static int__txn_begin_int(txn, internal)	DB_TXN *txn;	int internal;{	DB_ENV *dbenv;	DB_LSN begin_lsn, null_lsn;	DB_TXNMGR *mgr;	DB_TXNREGION *region;	TXN_DETAIL *td;	size_t off;	u_int32_t id, *ids;	int nids, ret;	mgr = txn->mgrp;	dbenv = mgr->dbenv;	region = mgr->reginfo.primary;	/*	 * We do not have to write begin records (and if we do not, then we	 * need never write records for read-only transactions).  However,	 * we do need to find the current LSN so that we can store it in the	 * transaction structure, so we can know where to take checkpoints.	 *	 * XXX	 * We should set this value when we write the first log record, not	 * here.	 */	if (DBENV_LOGGING(dbenv))		__log_txn_lsn(dbenv, &begin_lsn, NULL, NULL);	R_LOCK(dbenv, &mgr->reginfo);	if (!F_ISSET(txn, TXN_COMPENSATE) && F_ISSET(region, TXN_IN_RECOVERY)) {		__db_err(dbenv, "operation not permitted during recovery");		ret = EINVAL;		goto err;	}	/* Make sure that we aren't still recovering prepared transactions. */	if (!internal && region->stat.st_nrestores != 0) {		__db_err(dbenv,    "recovery of prepared but not yet committed transactions is incomplete");		ret = EINVAL;		goto err;	}	/*	 * Allocate a new transaction id. Our current valid range can span	 * the maximum valid value, so check for it and wrap manually.	 */	if (region->last_txnid == TXN_MAXIMUM &&	    region->cur_maxid != TXN_MAXIMUM)		region->last_txnid = TXN_MINIMUM - 1;	if (region->last_txnid == region->cur_maxid) {		if ((ret = __os_malloc(dbenv,		    sizeof(u_int32_t) * region->maxtxns, &ids)) != 0)			goto err;		nids = 0;		for (td = SH_TAILQ_FIRST(&region->active_txn, __txn_detail);		    td != NULL;		    td = SH_TAILQ_NEXT(td, links, __txn_detail))			ids[nids++] = td->txnid;		region->last_txnid = TXN_MINIMUM - 1;		region->cur_maxid = TXN_MAXIMUM;		if (nids != 0)			__db_idspace(ids, nids,			    &region->last_txnid, &region->cur_maxid);		__os_free(dbenv, ids);		if (DBENV_LOGGING(dbenv) &&		    (ret = __txn_recycle_log(dbenv, NULL,		    &null_lsn, 0, region->last_txnid, region->cur_maxid)) != 0)			goto err;	}	/* Allocate a new transaction detail structure. */	if ((ret =	    __db_shalloc(mgr->reginfo.addr, sizeof(TXN_DETAIL), 0, &td)) != 0) {		__db_err(dbenv,		    "Unable to allocate memory for transaction detail");		goto err;	}	/* Place transaction on active transaction list. */	SH_TAILQ_INSERT_HEAD(&region->active_txn, td, links, __txn_detail);	id = ++region->last_txnid;	++region->stat.st_nbegins;	if (++region->stat.st_nactive > region->stat.st_maxnactive)		region->stat.st_maxnactive = region->stat.st_nactive;	td->txnid = id;	td->begin_lsn = begin_lsn;	ZERO_LSN(td->last_lsn);	td->status = TXN_RUNNING;	if (txn->parent != NULL)		td->parent = txn->parent->off;	else		td->parent = INVALID_ROFF;	td->flags = 0;	off = R_OFFSET(&mgr->reginfo, td);	R_UNLOCK(dbenv, &mgr->reginfo);	ZERO_LSN(txn->last_lsn);	txn->txnid = id;	txn->off = (u_int32_t)off;	txn->abort = __txn_abort;	txn->commit = __txn_commit;	txn->discard = __txn_discard;	txn->id = __txn_id;	txn->prepare = __txn_prepare;	txn->set_timeout = __txn_set_timeout;	/*	 * If this is a transaction family, we must link the child to the	 * maximal grandparent in the lock table for deadlock detection.	 */	if (txn->parent != NULL && LOCKING_ON(dbenv))		if ((ret = __lock_addfamilylocker(dbenv,		    txn->parent->txnid, txn->txnid)) != 0)			return (ret);	if (F_ISSET(txn, TXN_MALLOC)) {		MUTEX_THREAD_LOCK(dbenv, mgr->mutexp);		TAILQ_INSERT_TAIL(&mgr->txn_chain, txn, links);		MUTEX_THREAD_UNLOCK(dbenv, mgr->mutexp);	}	return (0);err:	R_UNLOCK(dbenv, &mgr->reginfo);	return (ret);}/* * __txn_commit -- *	Commit a transaction. * * PUBLIC: int __txn_commit __P((DB_TXN *, u_int32_t)); */int__txn_commit(txnp, flags)	DB_TXN *txnp;	u_int32_t flags;{	DB_ENV *dbenv;	DB_LOCKREQ request;	DB_TXN *kid;	TXN_DETAIL *td;	u_int32_t lflags;	int ret, t_ret;	dbenv = txnp->mgrp->dbenv;	PANIC_CHECK(dbenv);	if ((ret = __txn_isvalid(txnp, &td, TXN_OP_COMMIT)) != 0)		return (ret);	/*	 * We clear flags that are incorrect, ignoring any flag errors, and	 * default to synchronous operations.  By definition, transaction	 * handles are dead when we return, and this error should never	 * happen, but we don't want to fail in the field 'cause the app is	 * specifying the wrong flag for some reason.	 */	if (__db_fchk(dbenv,	    "DB_TXN->commit", flags, DB_TXN_NOSYNC | DB_TXN_SYNC) != 0)		flags = DB_TXN_SYNC;	if (__db_fcchk(dbenv,	    "DB_TXN->commit", flags, DB_TXN_NOSYNC, DB_TXN_SYNC) != 0)		flags = DB_TXN_SYNC;	if (LF_ISSET(DB_TXN_NOSYNC)) {

⌨️ 快捷键说明

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