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

📄 log.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2004 *	Sleepycat Software.  All rights reserved. * * $Id: log.c,v 11.161 2004/10/15 16:59:42 bostic Exp $ */#include "db_config.h"#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#endif#include "db_int.h"#include "dbinc/crypto.h"#include "dbinc/hmac.h"#include "dbinc/log.h"#include "dbinc/txn.h"static int	__log_init __P((DB_ENV *, DB_LOG *));static int	__log_recover __P((DB_LOG *));static size_t	__log_region_size __P((DB_ENV *));static int	__log_zero __P((DB_ENV *, DB_LSN *, DB_LSN *));/* * __log_open -- *	Internal version of log_open: only called from DB_ENV->open. * * PUBLIC: int __log_open __P((DB_ENV *)); */int__log_open(dbenv)	DB_ENV *dbenv;{	DB_LOG *dblp;	LOG *lp;	int ret;	/* Create/initialize the DB_LOG structure. */	if ((ret = __os_calloc(dbenv, 1, sizeof(DB_LOG), &dblp)) != 0)		return (ret);	dblp->dbenv = dbenv;	/* Set the default buffer size, if not otherwise configured. */	if (dbenv->lg_bsize == 0)		dbenv->lg_bsize = F_ISSET(dbenv, DB_ENV_LOG_INMEMORY) ?		    LG_BSIZE_INMEM : LG_BSIZE_DEFAULT;	/* Join/create the log region. */	dblp->reginfo.dbenv = dbenv;	dblp->reginfo.type = REGION_TYPE_LOG;	dblp->reginfo.id = INVALID_REGION_ID;	dblp->reginfo.flags = REGION_JOIN_OK;	if (F_ISSET(dbenv, DB_ENV_CREATE))		F_SET(&dblp->reginfo, REGION_CREATE_OK);	if ((ret = __db_r_attach(	    dbenv, &dblp->reginfo, __log_region_size(dbenv))) != 0)		goto err;	/* If we created the region, initialize it. */	if (F_ISSET(&dblp->reginfo, REGION_CREATE))		if ((ret = __log_init(dbenv, dblp)) != 0)			goto err;	/* Set the local addresses. */	lp = dblp->reginfo.primary =	    R_ADDR(&dblp->reginfo, dblp->reginfo.rp->primary);	/*	 * If the region is threaded, then we have to lock both the handles	 * and the region, and we need to allocate a mutex for that purpose.	 */	if (F_ISSET(dbenv, DB_ENV_THREAD) &&	    (ret = __db_mutex_setup(dbenv, &dblp->reginfo, &dblp->mutexp,	    MUTEX_ALLOC | MUTEX_NO_RLOCK)) != 0)		goto err;	/* Initialize the rest of the structure. */	dblp->bufp = R_ADDR(&dblp->reginfo, lp->buffer_off);	/*	 * Set the handle -- we may be about to run recovery, which allocates	 * log cursors.  Log cursors require logging be already configured,	 * and the handle being set is what demonstrates that.	 *	 * If we created the region, run recovery.  If that fails, make sure	 * we reset the log handle before cleaning up, otherwise we will try	 * and clean up again in the mainline DB_ENV initialization code.	 */	dbenv->lg_handle = dblp;	if (F_ISSET(&dblp->reginfo, REGION_CREATE)) {		/*		 * We first take the log file size from the environment, if		 * specified.  If that wasn't set, default it.  Regardless,		 * recovery may set it from the persistent information in a		 * log file header.		 */		if (lp->log_size == 0)			lp->log_size = F_ISSET(dbenv, DB_ENV_LOG_INMEMORY) ?			    LG_MAX_INMEM : LG_MAX_DEFAULT;		if ((ret = __log_recover(dblp)) != 0)			goto err;		/*		 * If the next log file size hasn't been set yet, default it		 * to the current log file size.		 */		if (lp->log_nsize == 0)			lp->log_nsize = lp->log_size;		/*		 * If we haven't written any log files, write the first one		 * so that checkpoint gets a valid ckp_lsn value.		 */		if (IS_INIT_LSN(lp->lsn) &&		    (ret = __log_newfile(dblp, NULL, 0)) != 0)			goto err;		/* Initialize replication's next-expected LSN value. */		lp->ready_lsn = lp->lsn;	} else {		/*		 * A process joining the region may have reset the log file		 * size, too.  If so, it only affects the next log file we		 * create.  We need to check that the size is reasonable given		 * the buffer size in the region.		 */		 if (dbenv->lg_size != 0) {			if ((ret =			    __log_check_sizes(dbenv, dbenv->lg_size, 0)) != 0)				goto err;			lp->log_nsize = dbenv->lg_size;		 }		/* Migrate persistent flags from the region into the DB_ENV. */		if (lp->db_log_autoremove)			F_SET(dbenv, DB_ENV_LOG_AUTOREMOVE);		if (lp->db_log_inmemory)			F_SET(dbenv, DB_ENV_LOG_INMEMORY);	}	R_UNLOCK(dbenv, &dblp->reginfo);	return (0);err:	dbenv->lg_handle = NULL;	if (dblp->reginfo.addr != NULL) {		if (F_ISSET(&dblp->reginfo, REGION_CREATE))			ret = __db_panic(dbenv, ret);		R_UNLOCK(dbenv, &dblp->reginfo);		(void)__db_r_detach(dbenv, &dblp->reginfo, 0);	}	if (dblp->mutexp != NULL)		__db_mutex_free(dbenv, &dblp->reginfo, dblp->mutexp);	__os_free(dbenv, dblp);	return (ret);}/* * __log_init -- *	Initialize a log region in shared memory. */static int__log_init(dbenv, dblp)	DB_ENV *dbenv;	DB_LOG *dblp;{	DB_MUTEX *flush_mutexp;	LOG *lp;	int ret;	void *p;#ifdef  HAVE_MUTEX_SYSTEM_RESOURCES	u_int8_t *addr;#endif	/*	 * This is the first point where we can validate the buffer size,	 * because we know all three settings have been configured (file size,	 * buffer size and the in-memory flag).	 */	if ((ret =	   __log_check_sizes(dbenv, dbenv->lg_size, dbenv->lg_bsize)) != 0)		return (ret);	if ((ret = __db_shalloc(&dblp->reginfo,	    sizeof(*lp), MUTEX_ALIGN, &dblp->reginfo.primary)) != 0)		goto mem_err;	dblp->reginfo.rp->primary =	    R_OFFSET(&dblp->reginfo, dblp->reginfo.primary);	lp = dblp->reginfo.primary;	memset(lp, 0, sizeof(*lp));	lp->fid_max = 0;	SH_TAILQ_INIT(&lp->fq);	lp->free_fid_stack = INVALID_ROFF;	lp->free_fids = lp->free_fids_alloced = 0;	/* Initialize LOG LSNs. */	INIT_LSN(lp->lsn);	INIT_LSN(lp->t_lsn);	/*	 * It's possible to be waiting for an LSN of [1][0], if a replication	 * client gets the first log record out of order.  An LSN of [0][0]	 * signifies that we're not waiting.	 */	ZERO_LSN(lp->waiting_lsn);	/*	 * Log makes note of the fact that it ran into a checkpoint on	 * startup if it did so, as a recovery optimization.  A zero	 * LSN signifies that it hasn't found one [yet].	 */	ZERO_LSN(lp->cached_ckp_lsn);#ifdef  HAVE_MUTEX_SYSTEM_RESOURCES	/* Allocate room for the log maintenance info and initialize it. */	if ((ret = __db_shalloc(&dblp->reginfo,	    sizeof(REGMAINT) + LG_MAINT_SIZE, 0, &addr)) != 0)		goto mem_err;	__db_maintinit(&dblp->reginfo, addr, LG_MAINT_SIZE);	lp->maint_off = R_OFFSET(&dblp->reginfo, addr);#endif	if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, &lp->fq_mutex,	    MUTEX_NO_RLOCK)) != 0)		return (ret);	/*	 * We must create a place for the flush mutex separately; mutexes have	 * to be aligned to MUTEX_ALIGN, and the only way to guarantee that is	 * to make sure they're at the beginning of a shalloc'ed chunk.	 */	if ((ret = __db_shalloc(&dblp->reginfo,	    sizeof(DB_MUTEX), MUTEX_ALIGN, &flush_mutexp)) != 0)		goto mem_err;	if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, flush_mutexp,	    MUTEX_NO_RLOCK)) != 0)		return (ret);	lp->flush_mutex_off = R_OFFSET(&dblp->reginfo, flush_mutexp);	/* Initialize the buffer. */	if ((ret = __db_shalloc(&dblp->reginfo, dbenv->lg_bsize, 0, &p)) != 0) {mem_err:	__db_err(dbenv, "Unable to allocate memory for the log buffer");		return (ret);	}	lp->regionmax = dbenv->lg_regionmax;	lp->buffer_off = R_OFFSET(&dblp->reginfo, p);	lp->buffer_size = dbenv->lg_bsize;	lp->log_size = lp->log_nsize = dbenv->lg_size;	/* Initialize the commit Queue. */	SH_TAILQ_INIT(&lp->free_commits);	SH_TAILQ_INIT(&lp->commits);	lp->ncommit = 0;	/* Initialize the logfiles list for in-memory logs. */	SH_TAILQ_INIT(&lp->logfiles);	SH_TAILQ_INIT(&lp->free_logfiles);	/*	 * Fill in the log's persistent header.  Don't fill in the log file	 * sizes, as they may change at any time and so have to be filled in	 * as each log file is created.	 */	lp->persist.magic = DB_LOGMAGIC;	lp->persist.version = DB_LOGVERSION;	lp->persist.mode = (u_int32_t)dbenv->db_mode;	/* Migrate persistent flags from the DB_ENV into the region. */	if (F_ISSET(dbenv, DB_ENV_LOG_AUTOREMOVE))		lp->db_log_autoremove = 1;	if (F_ISSET(dbenv, DB_ENV_LOG_INMEMORY))		lp->db_log_inmemory = 1;	return (0);}/* * __log_recover -- *	Recover a log. */static int__log_recover(dblp)	DB_LOG *dblp;{	DBT dbt;	DB_ENV *dbenv;	DB_LOGC *logc;	DB_LSN lsn;	LOG *lp;	u_int32_t cnt, rectype;	int ret;	logfile_validity status;	logc = NULL;	dbenv = dblp->dbenv;	lp = dblp->reginfo.primary;	/*	 * Find a log file.  If none exist, we simply return, leaving	 * everything initialized to a new log.	 */	if ((ret = __log_find(dblp, 0, &cnt, &status)) != 0)		return (ret);	if (cnt == 0)		return (0);	/*	 * If the last file is an old version, readable or no, start a new	 * file.  Don't bother finding the end of the last log file;	 * we assume that it's valid in its entirety, since the user	 * should have shut down cleanly or run recovery before upgrading.	 */	if (status == DB_LV_OLD_READABLE || status == DB_LV_OLD_UNREADABLE) {		lp->lsn.file = lp->s_lsn.file = cnt + 1;		lp->lsn.offset = lp->s_lsn.offset = 0;		goto skipsearch;	}	DB_ASSERT(status == DB_LV_NORMAL);	/*	 * We have the last useful log file and we've loaded any persistent	 * information.  Set the end point of the log past the end of the last	 * file. Read the last file, looking for the last checkpoint and	 * the log's end.	 */	lp->lsn.file = cnt + 1;	lp->lsn.offset = 0;	lsn.file = cnt;	lsn.offset = 0;	/*	 * Allocate a cursor and set it to the first record.  This shouldn't	 * fail, leave error messages on.	 */	if ((ret = __log_cursor(dbenv, &logc)) != 0)		return (ret);	F_SET(logc, DB_LOG_LOCKED);	memset(&dbt, 0, sizeof(dbt));	if ((ret = __log_c_get(logc, &lsn, &dbt, DB_SET)) != 0)		goto err;	/*	 * Read to the end of the file.  This may fail at some point, so	 * turn off error messages.	 */	F_SET(logc, DB_LOG_SILENT_ERR);	while (__log_c_get(logc, &lsn, &dbt, DB_NEXT) == 0) {		if (dbt.size < sizeof(u_int32_t))			continue;		memcpy(&rectype, dbt.data, sizeof(u_int32_t));		if (rectype == DB___txn_ckp)			/*			 * If we happen to run into a checkpoint, cache its			 * LSN so that the transaction system doesn't have			 * to walk this log file again looking for it.			 */			lp->cached_ckp_lsn = lsn;	}	F_CLR(logc, DB_LOG_SILENT_ERR);	/*	 * We now know where the end of the log is.  Set the first LSN that	 * we want to return to an application and the LSN of the last known	 * record on disk.	 */	lp->lsn = lsn;	lp->s_lsn = lsn;	lp->lsn.offset += logc->c_len;	lp->s_lsn.offset += logc->c_len;	/* Set up the current buffer information, too. */	lp->len = logc->c_len;	lp->a_off = 0;	lp->b_off = 0;	lp->w_off = lp->lsn.offset;skipsearch:	if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY))		__db_msg(dbenv,		    "Finding last valid log LSN: file: %lu offset %lu",		    (u_long)lp->lsn.file, (u_long)lp->lsn.offset);err:	if (logc != NULL)		(void)__log_c_close(logc);	return (ret);}/* * __log_find -- *	Try to find a log file.  If find_first is set, valp will contain * the number of the first readable log file, else it will contain the number * of the last log file (which may be too old to read). * * PUBLIC: int __log_find __P((DB_LOG *, int, u_int32_t *, logfile_validity *)); */int__log_find(dblp, find_first, valp, statusp)	DB_LOG *dblp;	int find_first;	u_int32_t *valp;	logfile_validity *statusp;{	DB_ENV *dbenv;	LOG *lp;	logfile_validity logval_status, status;	struct __db_filestart *filestart;	u_int32_t clv, logval;	int cnt, fcnt, ret;	const char *dir;	char *c, **names, *p, *q, savech;	dbenv = dblp->dbenv;	lp = dblp->reginfo.primary;	logval_status = status = DB_LV_NONEXISTENT;	/* Return a value of 0 as the log file number on failure. */	*valp = 0;	if (lp->db_log_inmemory) {		filestart = find_first ?		    SH_TAILQ_FIRST(&lp->logfiles, __db_filestart) :		    SH_TAILQ_LAST(&lp->logfiles, links, __db_filestart);		if (filestart != NULL) {			*valp = filestart->file;			logval_status = DB_LV_NORMAL;		}		*statusp = logval_status;		return (0);	}	/* Find the directory name. */	if ((ret = __log_name(dblp, 1, &p, NULL, 0)) != 0)		return (ret);	if ((q = __db_rpath(p)) == NULL) {		COMPQUIET(savech, 0);		dir = PATH_DOT;	} else {		savech = *q;		*q = '\0';		dir = p;	}	/* Get the list of file names. */	ret = __os_dirlist(dbenv, dir, &names, &fcnt);	/*	 * !!!	 * We overwrote a byte in the string with a nul.  Restore the string	 * so that the diagnostic checks in the memory allocation code work	 * and any error messages display the right file name.	 */	if (q != NULL)

⌨️ 快捷键说明

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