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

📄 txn_util.c

📁 这是国外的resip协议栈
💻 C
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2001-2004 *	Sleepycat Software.  All rights reserved. * * $Id: txn_util.c,v 11.28 2004/09/16 17:55:19 margo 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/lock.h"#include "dbinc/mp.h"#include "dbinc/txn.h"#include "dbinc/db_am.h"typedef struct __txn_event TXN_EVENT;struct __txn_event {	TXN_EVENT_T op;	TAILQ_ENTRY(__txn_event) links;	union {		struct {			/* Delayed close. */			DB *dbp;		} c;		struct {			/* Delayed remove. */			char *name;			u_int8_t *fileid;		} r;		struct {			/* Lock event. */			DB_LOCK lock;			u_int32_t locker;			DB *dbp;		} t;	} u;};/* * __txn_closeevent -- * * Creates a close event that can be added to the [so-called] commit list, so * that we can redo a failed DB handle close once we've aborted the transaction. * * PUBLIC: int __txn_closeevent __P((DB_ENV *, DB_TXN *, DB *)); */int__txn_closeevent(dbenv, txn, dbp)	DB_ENV *dbenv;	DB_TXN *txn;	DB *dbp;{	int ret;	TXN_EVENT *e;	e = NULL;	if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)		return (ret);	e->u.c.dbp = dbp;	e->op = TXN_CLOSE;	TAILQ_INSERT_TAIL(&txn->events, e, links);	return (0);}/* * __txn_remevent -- * * Creates a remove event that can be added to the commit list. * * PUBLIC: int __txn_remevent __P((DB_ENV *, * PUBLIC:       DB_TXN *, const char *, u_int8_t*)); */int__txn_remevent(dbenv, txn, name, fileid)	DB_ENV *dbenv;	DB_TXN *txn;	const char *name;	u_int8_t *fileid;{	int ret;	TXN_EVENT *e;	e = NULL;	if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)		return (ret);	if ((ret = __os_strdup(dbenv, name, &e->u.r.name)) != 0)		goto err;	if (fileid != NULL) {		if ((ret = __os_calloc(dbenv,		    1, DB_FILE_ID_LEN, &e->u.r.fileid)) != 0)			return (ret);		memcpy(e->u.r.fileid, fileid, DB_FILE_ID_LEN);	}	e->op = TXN_REMOVE;	TAILQ_INSERT_TAIL(&txn->events, e, links);	return (0);err:	if (e != NULL)		__os_free(dbenv, e);	return (ret);}/* * __txn_remrem -- *	Remove a remove event because the remove has be superceeded, * by a create of the same name, for example. * * PUBLIC: void __txn_remrem __P((DB_ENV *, DB_TXN *, const char *)); */void__txn_remrem(dbenv, txn, name)	DB_ENV *dbenv;	DB_TXN *txn;	const char *name;{	TXN_EVENT *e, *next_e;	for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {		next_e = TAILQ_NEXT(e, links);		if (e->op != TXN_REMOVE || strcmp(name, e->u.r.name) != 0)			continue;		TAILQ_REMOVE(&txn->events, e, links);		__os_free(dbenv, e->u.r.name);		if (e->u.r.fileid != NULL)			__os_free(dbenv, e->u.r.fileid);		__os_free(dbenv, e);	}	return;}/* * __txn_lockevent -- * * Add a lockevent to the commit-queue.  The lock event indicates a locker * trade. * * PUBLIC: int __txn_lockevent __P((DB_ENV *, * PUBLIC:     DB_TXN *, DB *, DB_LOCK *, u_int32_t)); */int__txn_lockevent(dbenv, txn, dbp, lock, locker)	DB_ENV *dbenv;	DB_TXN *txn;	DB *dbp;	DB_LOCK *lock;	u_int32_t locker;{	int ret;	TXN_EVENT *e;	if (!LOCKING_ON(dbenv))		return (0);	e = NULL;	if ((ret = __os_calloc(dbenv, 1, sizeof(TXN_EVENT), &e)) != 0)		return (ret);	e->u.t.locker = locker;	e->u.t.lock = *lock;	e->u.t.dbp = dbp;	e->op = TXN_TRADE;	TAILQ_INSERT_TAIL(&txn->events, e, links);	return (0);}/* * __txn_remlock -- *	Remove a lock event because the locker is going away.  We can remove * by lock (using offset) or by locker_id (or by both). * * PUBLIC: void __txn_remlock __P((DB_ENV *, DB_TXN *, DB_LOCK *, u_int32_t)); */void__txn_remlock(dbenv, txn, lock, locker)	DB_ENV *dbenv;	DB_TXN *txn;	DB_LOCK *lock;	u_int32_t locker;{	TXN_EVENT *e, *next_e;	for (e = TAILQ_FIRST(&txn->events); e != NULL; e = next_e) {		next_e = TAILQ_NEXT(e, links);		if ((e->op != TXN_TRADE && e->op != TXN_TRADED) ||		    (e->u.t.lock.off != lock->off && e->u.t.locker != locker))			continue;		TAILQ_REMOVE(&txn->events, e, links);		__os_free(dbenv, e);	}	return;}/* * __txn_doevents -- * Process the list of events associated with a transaction.  On commit, * apply the events; on abort, just toss the entries. * * PUBLIC: int __txn_doevents __P((DB_ENV *, DB_TXN *, int, int)); */#define	DO_TRADE do {							\	memset(&req, 0, sizeof(req));					\	req.lock = e->u.t.lock;						\	req.op = DB_LOCK_TRADE;						\	t_ret = __lock_vec(dbenv, e->u.t.locker, 0, &req, 1, NULL);	\	if (t_ret == 0)							\		e->u.t.dbp->cur_lid = e->u.t.locker;			\	else if (t_ret == DB_NOTFOUND)					\		t_ret = 0;						\	if (t_ret != 0 && ret == 0)					\		ret = t_ret;						\	e->op = TXN_TRADED;						\} while (0)int__txn_doevents(dbenv, txn, opcode, preprocess)	DB_ENV *dbenv;	DB_TXN *txn;	int opcode, preprocess;{	DB_LOCKREQ req;	TXN_EVENT *e;	int ret, t_ret;	ret = 0;	/*	 * This phase only gets called if we have a phase where we	 * release read locks.  Since not all paths will call this	 * phase, we have to check for it below as well.  So, when	 * we do the trade, we update the opcode of the entry so that	 * we don't try the trade again.	 */	if (preprocess) {		for (e = TAILQ_FIRST(&txn->events);		    e != NULL; e = TAILQ_NEXT(e, links)) {			if (e->op != TXN_TRADE)				continue;			DO_TRADE;		}		return (ret);	}	/*	 * Prepare should only cause a preprocess, since the transaction	 * isn't over.	 */	DB_ASSERT(opcode != TXN_PREPARE);	while ((e = TAILQ_FIRST(&txn->events)) != NULL) {		TAILQ_REMOVE(&txn->events, e, links);		/*		 * Most deferred events should only happen on		 * commits, not aborts or prepares.  The one exception		 * is a close which gets done on commit and abort, but		 * not prepare. If we're not doing operations, then we		 * can just go free resources.		 */		if (opcode == TXN_ABORT && e->op != TXN_CLOSE)			goto dofree;		switch (e->op) {		case TXN_CLOSE:			/* If we didn't abort this txn, we screwed up badly. */			DB_ASSERT(opcode == TXN_ABORT);			if ((t_ret = __db_close(e->u.c.dbp,			    NULL, DB_NOSYNC)) != 0 && ret == 0)				ret = t_ret;			break;		case TXN_REMOVE:			if (e->u.r.fileid != NULL) {				if ((t_ret = __memp_nameop(dbenv,				    e->u.r.fileid,				    NULL, e->u.r.name, NULL)) != 0 && ret == 0)					ret = t_ret;			} else if ((t_ret =			    __os_unlink(dbenv, e->u.r.name)) != 0 && ret == 0)				ret = t_ret;			break;		case TXN_TRADE:			DO_TRADE;			/* Fall through */		case TXN_TRADED:			/* Downgrade the lock. */			if ((t_ret = __lock_downgrade(dbenv,			    &e->u.t.lock, DB_LOCK_READ, 0)) != 0 && ret == 0)				ret = t_ret;			break;		default:			/* This had better never happen. */			DB_ASSERT(0);		}dofree:		/* Free resources here. */		switch (e->op) {		case TXN_REMOVE:			if (e->u.r.fileid != NULL)				__os_free(dbenv, e->u.r.fileid);			__os_free(dbenv, e->u.r.name);			break;		case TXN_CLOSE:		case TXN_TRADE:		case TXN_TRADED:		default:			break;		}		__os_free(dbenv, e);	}	return (ret);}

⌨️ 快捷键说明

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