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

📄 db_rec.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 *	Sleepycat Software.  All rights reserved. * * $Id: db_rec.c,v 11.61 2004/10/21 14:39:58 bostic 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/log.h"#include "dbinc/mp.h"#include "dbinc/hash.h"static int __db_pg_free_recover_int __P((DB_ENV *,    __db_pg_freedata_args *, DB *, DB_LSN *, DB_MPOOLFILE *, db_recops, int));/* * PUBLIC: int __db_addrem_recover * PUBLIC:    __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); * * This log message is generated whenever we add or remove a duplicate * to/from a duplicate page.  On recover, we just do the opposite. */int__db_addrem_recover(dbenv, dbtp, lsnp, op, info)	DB_ENV *dbenv;	DBT *dbtp;	DB_LSN *lsnp;	db_recops op;	void *info;{	__db_addrem_args *argp;	DB *file_dbp;	DBC *dbc;	DB_MPOOLFILE *mpf;	PAGE *pagep;	u_int32_t change;	int cmp_n, cmp_p, ret;	pagep = NULL;	COMPQUIET(info, NULL);	REC_PRINT(__db_addrem_print);	REC_INTRO(__db_addrem_read, 1);	REC_FGET(mpf, argp->pgno, &pagep, done);	cmp_n = log_compare(lsnp, &LSN(pagep));	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);	change = 0;	if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_DUP) ||	    (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_DUP)) {		/* Need to redo an add, or undo a delete. */		if ((ret = __db_pitem(dbc, pagep, argp->indx, argp->nbytes,		    argp->hdr.size == 0 ? NULL : &argp->hdr,		    argp->dbt.size == 0 ? NULL : &argp->dbt)) != 0)			goto out;		change = DB_MPOOL_DIRTY;	} else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_DUP) ||	    (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_DUP)) {		/* Need to undo an add, or redo a delete. */		if ((ret = __db_ditem(dbc,		    pagep, argp->indx, argp->nbytes)) != 0)			goto out;		change = DB_MPOOL_DIRTY;	}	if (change) {		if (DB_REDO(op))			LSN(pagep) = *lsnp;		else			LSN(pagep) = argp->pagelsn;	}	if ((ret = __memp_fput(mpf, pagep, change)) != 0)		goto out;	pagep = NULL;done:	*lsnp = argp->prev_lsn;	ret = 0;out:	if (pagep != NULL)		(void)__memp_fput(mpf, pagep, 0);	REC_CLOSE;}/* * PUBLIC: int __db_big_recover * PUBLIC:     __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); */int__db_big_recover(dbenv, dbtp, lsnp, op, info)	DB_ENV *dbenv;	DBT *dbtp;	DB_LSN *lsnp;	db_recops op;	void *info;{	__db_big_args *argp;	DB *file_dbp;	DBC *dbc;	DB_MPOOLFILE *mpf;	PAGE *pagep;	u_int32_t change;	int cmp_n, cmp_p, ret;	pagep = NULL;	COMPQUIET(info, NULL);	REC_PRINT(__db_big_print);	REC_INTRO(__db_big_read, 1);	REC_FGET(mpf, argp->pgno, &pagep, ppage);	/*	 * There are three pages we need to check.  The one on which we are	 * adding data, the previous one whose next_pointer may have	 * been updated, and the next one whose prev_pointer may have	 * been updated.	 */	cmp_n = log_compare(lsnp, &LSN(pagep));	cmp_p = log_compare(&LSN(pagep), &argp->pagelsn);	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->pagelsn);	change = 0;	if ((cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) ||	    (cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_REM_BIG)) {		/* We are either redo-ing an add, or undoing a delete. */		P_INIT(pagep, file_dbp->pgsize, argp->pgno, argp->prev_pgno,			argp->next_pgno, 0, P_OVERFLOW);		OV_LEN(pagep) = argp->dbt.size;		OV_REF(pagep) = 1;		memcpy((u_int8_t *)pagep + P_OVERHEAD(file_dbp), argp->dbt.data,		    argp->dbt.size);		PREV_PGNO(pagep) = argp->prev_pgno;		change = DB_MPOOL_DIRTY;	} else if ((cmp_n == 0 && DB_UNDO(op) && argp->opcode == DB_ADD_BIG) ||	    (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_REM_BIG)) {		/*		 * We are either undo-ing an add or redo-ing a delete.		 * The page is about to be reclaimed in either case, so		 * there really isn't anything to do here.		 */		change = DB_MPOOL_DIRTY;	}	if (change)		LSN(pagep) = DB_REDO(op) ? *lsnp : argp->pagelsn;	if ((ret = __memp_fput(mpf, pagep, change)) != 0)		goto out;	pagep = NULL;	/*	 * We only delete a whole chain of overflow.	 * Each page is handled individually	 */	if (argp->opcode == DB_REM_BIG)		goto done;	/* Now check the previous page. */ppage:	if (argp->prev_pgno != PGNO_INVALID) {		change = 0;		REC_FGET(mpf, argp->prev_pgno, &pagep, npage);		cmp_n = log_compare(lsnp, &LSN(pagep));		cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);		CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);		if (cmp_p == 0 && DB_REDO(op) && argp->opcode == DB_ADD_BIG) {			/* Redo add, undo delete. */			NEXT_PGNO(pagep) = argp->pgno;			change = DB_MPOOL_DIRTY;		} else if (cmp_n == 0 &&		    DB_UNDO(op) && argp->opcode == DB_ADD_BIG) {			/* Redo delete, undo add. */			NEXT_PGNO(pagep) = argp->next_pgno;			change = DB_MPOOL_DIRTY;		}		if (change)			LSN(pagep) = DB_REDO(op) ? *lsnp : argp->prevlsn;		if ((ret = __memp_fput(mpf, pagep, change)) != 0)			goto out;	}	pagep = NULL;	/* Now check the next page.  Can only be set on a delete. */npage:	if (argp->next_pgno != PGNO_INVALID) {		change = 0;		REC_FGET(mpf, argp->next_pgno, &pagep, done);		cmp_n = log_compare(lsnp, &LSN(pagep));		cmp_p = log_compare(&LSN(pagep), &argp->nextlsn);		CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->nextlsn);		if (cmp_p == 0 && DB_REDO(op)) {			PREV_PGNO(pagep) = PGNO_INVALID;			change = DB_MPOOL_DIRTY;		} else if (cmp_n == 0 && DB_UNDO(op)) {			PREV_PGNO(pagep) = argp->pgno;			change = DB_MPOOL_DIRTY;		}		if (change)			LSN(pagep) = DB_REDO(op) ? *lsnp : argp->nextlsn;		if ((ret = __memp_fput(mpf, pagep, change)) != 0)			goto out;	}	pagep = NULL;done:	*lsnp = argp->prev_lsn;	ret = 0;out:	if (pagep != NULL)		(void)__memp_fput(mpf, pagep, 0);	REC_CLOSE;}/* * __db_ovref_recover -- *	Recovery function for __db_ovref(). * * PUBLIC: int __db_ovref_recover * PUBLIC:     __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); */int__db_ovref_recover(dbenv, dbtp, lsnp, op, info)	DB_ENV *dbenv;	DBT *dbtp;	DB_LSN *lsnp;	db_recops op;	void *info;{	__db_ovref_args *argp;	DB *file_dbp;	DBC *dbc;	DB_MPOOLFILE *mpf;	PAGE *pagep;	int cmp, modified, ret;	pagep = NULL;	COMPQUIET(info, NULL);	REC_PRINT(__db_ovref_print);	REC_INTRO(__db_ovref_read, 1);	REC_FGET(mpf, argp->pgno, &pagep, done);	modified = 0;	cmp = log_compare(&LSN(pagep), &argp->lsn);	CHECK_LSN(op, cmp, &LSN(pagep), &argp->lsn);	if (cmp == 0 && DB_REDO(op)) {		/* Need to redo update described. */		OV_REF(pagep) += argp->adjust;		pagep->lsn = *lsnp;		modified = 1;	} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {		/* Need to undo update described. */		OV_REF(pagep) -= argp->adjust;		pagep->lsn = argp->lsn;		modified = 1;	}	if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)		goto out;	pagep = NULL;done:	*lsnp = argp->prev_lsn;	ret = 0;out:	if (pagep != NULL)		(void)__memp_fput(mpf, pagep, 0);	REC_CLOSE;}/* * __db_debug_recover -- *	Recovery function for debug. * * PUBLIC: int __db_debug_recover __P((DB_ENV *, * PUBLIC:     DBT *, DB_LSN *, db_recops, void *)); */int__db_debug_recover(dbenv, dbtp, lsnp, op, info)	DB_ENV *dbenv;	DBT *dbtp;	DB_LSN *lsnp;	db_recops op;	void *info;{	__db_debug_args *argp;	int ret;	COMPQUIET(dbenv, NULL);	COMPQUIET(op, DB_TXN_ABORT);	COMPQUIET(info, NULL);	REC_PRINT(__db_debug_print);	REC_NOOP_INTRO(__db_debug_read);	*lsnp = argp->prev_lsn;	ret = 0;	REC_NOOP_CLOSE;}/* * __db_noop_recover -- *	Recovery function for noop. * * PUBLIC: int __db_noop_recover __P((DB_ENV *, * PUBLIC:      DBT *, DB_LSN *, db_recops, void *)); */int__db_noop_recover(dbenv, dbtp, lsnp, op, info)	DB_ENV *dbenv;	DBT *dbtp;	DB_LSN *lsnp;	db_recops op;	void *info;{	__db_noop_args *argp;	DB *file_dbp;	DBC *dbc;	DB_MPOOLFILE *mpf;	PAGE *pagep;	u_int32_t change;	int cmp_n, cmp_p, ret;	pagep = NULL;	COMPQUIET(info, NULL);	REC_PRINT(__db_noop_print);	REC_INTRO(__db_noop_read, 0);	REC_FGET(mpf, argp->pgno, &pagep, done);	cmp_n = log_compare(lsnp, &LSN(pagep));	cmp_p = log_compare(&LSN(pagep), &argp->prevlsn);	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->prevlsn);	change = 0;	if (cmp_p == 0 && DB_REDO(op)) {		LSN(pagep) = *lsnp;		change = DB_MPOOL_DIRTY;	} else if (cmp_n == 0 && DB_UNDO(op)) {		LSN(pagep) = argp->prevlsn;		change = DB_MPOOL_DIRTY;	}	ret = __memp_fput(mpf, pagep, change);	pagep = NULL;done:	*lsnp = argp->prev_lsn;out:	if (pagep != NULL)		(void)__memp_fput(mpf, pagep, 0);	REC_CLOSE;}/* * __db_pg_alloc_recover -- *	Recovery function for pg_alloc. * * PUBLIC: int __db_pg_alloc_recover * PUBLIC:   __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *)); */int__db_pg_alloc_recover(dbenv, dbtp, lsnp, op, info)	DB_ENV *dbenv;	DBT *dbtp;	DB_LSN *lsnp;	db_recops op;	void *info;{	__db_pg_alloc_args *argp;	DB *file_dbp;	DBC *dbc;	DBMETA *meta;	DB_MPOOLFILE *mpf;	PAGE *pagep;	db_pgno_t pgno;	int cmp_n, cmp_p, created, level, meta_modified, modified, ret;	meta = NULL;	pagep = NULL;	created = meta_modified = modified = 0;	REC_PRINT(__db_pg_alloc_print);	REC_INTRO(__db_pg_alloc_read, 0);	/*	 * Fix up the metadata page.  If we're redoing the operation, we have	 * to get the metadata page and update its LSN and its free pointer.	 * If we're undoing the operation and the page was ever created, we put	 * it on the freelist.	 */	pgno = PGNO_BASE_MD;	if ((ret = __memp_fget(mpf, &pgno, 0, &meta)) != 0) {		/* The metadata page must always exist on redo. */		if (DB_REDO(op)) {			ret = __db_pgerr(file_dbp, pgno, ret);			goto out;		} else			goto done;	}	cmp_n = log_compare(lsnp, &LSN(meta));	cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);	CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn);	if (cmp_p == 0 && DB_REDO(op)) {		/* Need to redo update described. */		LSN(meta) = *lsnp;		meta->free = argp->next;		meta_modified = 1;		if (argp->pgno > meta->last_pgno)			meta->last_pgno = argp->pgno;	} else if (cmp_n == 0 && DB_UNDO(op)) {		/* Need to undo update described. */		LSN(meta) = argp->meta_lsn;		/*		 * If the page has a zero LSN then its newly created		 * and will be truncated or go into limbo rather than		 * directly on the free list.		 */		if (!IS_ZERO_LSN(argp->page_lsn))			meta->free = argp->pgno;#ifdef HAVE_FTRUNCATE		/*		 * With truncate we will restore the file to		 * its original length.  Without truncate		 * the last_pgno never goes backward.		 */		meta->last_pgno = argp->last_pgno;#endif		meta_modified = 1;	}	/*	 * Fix up the allocated page. If the page does not exist	 * and we can truncate it then don't create it.	 * Otherwise if we're redoing the operation, we have	 * to get the page (creating it if it doesn't exist), and update its	 * LSN.  If we're undoing the operation, we have to reset the page's	 * LSN and put it on the free list, or into limbo..	 */	if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {		/*		 * We have to be able to identify if a page was newly		 * created so we can recover it properly.  We cannot simply		 * look for an empty header, because hash uses a pgin		 * function that will set the header.  Instead, we explicitly		 * try for the page without CREATE and if that fails, then		 * create it.		 */#ifdef HAVE_FTRUNCATE		if (DB_UNDO(op))			goto do_truncate;#endif		if ((ret = __memp_fget(		    mpf, &argp->pgno, DB_MPOOL_CREATE, &pagep)) != 0) {			if (DB_UNDO(op) && ret == ENOSPC)				goto do_truncate;			ret = __db_pgerr(file_dbp, argp->pgno, ret);			goto out;		}		created = modified = 1;	}	/* Fix up the allocated page. */	cmp_n = log_compare(lsnp, &LSN(pagep));	cmp_p = log_compare(&LSN(pagep), &argp->page_lsn);	/*	 * If an initial allocation is aborted and then reallocated during	 * an archival restore the log record will have an LSN for the page	 * but the page will be empty.	 * If we we rolled back this allocation previously during an	 * archive restore, the page may have INIT_LSN from the limbo list.	 */	if (IS_ZERO_LSN(LSN(pagep)) ||	    (IS_ZERO_LSN(argp->page_lsn) && IS_INIT_LSN(LSN(pagep))))		cmp_p = 0;	CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->page_lsn);	/*	 * Another special case we have to handle is if we ended up with a	 * page of all 0's which can happen if we abort between allocating a	 * page in mpool and initializing it.  In that case, even if we're	 * undoing, we need to re-initialize the page.	 */	if (DB_REDO(op) && cmp_p == 0) {		/* Need to redo update described. */		switch (argp->ptype) {		case P_LBTREE:		case P_LRECNO:		case P_LDUP:			level = LEAFLEVEL;			break;		default:			level = 0;			break;		}		P_INIT(pagep, file_dbp->pgsize,		    argp->pgno, PGNO_INVALID, PGNO_INVALID, level, argp->ptype);		pagep->lsn = *lsnp;		modified = 1;	} else if (DB_UNDO(op) && (cmp_n == 0 || created)) {		/*		 * This is where we handle the case of a 0'd page (pagep->pgno		 * is equal to PGNO_INVALID).		 * Undo the allocation, reinitialize the page and

⌨️ 快捷键说明

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