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

📄 log.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996-2002 *	Sleepycat Software.  All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: log.c,v 11.111 2002/08/16 00:27:44 ubell Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#include <ctype.h>#include <stdlib.h>#include <string.h>#include <unistd.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;	/* Join/create the log region. */	dblp->reginfo.type = REGION_TYPE_LOG;	dblp->reginfo.id = INVALID_REGION_ID;	dblp->reginfo.mode = dbenv->db_mode;	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)) {		if ((ret = __log_recover(dblp)) != 0) {			dbenv->lg_handle = NULL;			goto err;		}		/*		 * We first take the log file size from the environment, if		 * specified.  If that wasn't set, recovery may have set it		 * from the persistent information in a log file header.  If		 * that didn't set it either, we default.		 */		if (lp->log_size == 0)			lp->log_size = lp->log_nsize = LG_MAX_DEFAULT;	} 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.		 */		 if (dbenv->lg_size != 0)			lp->log_nsize = dbenv->lg_size;	}	R_UNLOCK(dbenv, &dblp->reginfo);	return (0);err:	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 *region;	int ret;	void *p;#ifdef  HAVE_MUTEX_SYSTEM_RESOURCES	u_int8_t *addr;#endif	if ((ret = __db_shalloc(dblp->reginfo.addr,	    sizeof(*region), 0, &dblp->reginfo.primary)) != 0)		goto mem_err;	dblp->reginfo.rp->primary =	    R_OFFSET(&dblp->reginfo, dblp->reginfo.primary);	region = dblp->reginfo.primary;	memset(region, 0, sizeof(*region));	region->fid_max = 0;	SH_TAILQ_INIT(&region->fq);	region->free_fid_stack = INVALID_ROFF;	region->free_fids = region->free_fids_alloced = 0;	/* Initialize LOG LSNs. */	INIT_LSN(region->lsn);	INIT_LSN(region->ready_lsn);	INIT_LSN(region->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(region->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(region->cached_ckp_lsn);#ifdef  HAVE_MUTEX_SYSTEM_RESOURCES	/* Allocate room for the log maintenance info and initialize it. */	if ((ret = __db_shalloc(dblp->reginfo.addr,	    sizeof(REGMAINT) + LG_MAINT_SIZE, 0, &addr)) != 0)		goto mem_err;	__db_maintinit(&dblp->reginfo, addr, LG_MAINT_SIZE);	region->maint_off = R_OFFSET(&dblp->reginfo, addr);#endif	if ((ret = __db_mutex_setup(dbenv, &dblp->reginfo, &region->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.addr,	    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);	region->flush_mutex_off = R_OFFSET(&dblp->reginfo, flush_mutexp);	/* Initialize the buffer. */	if ((ret =	    __db_shalloc(dblp->reginfo.addr, dbenv->lg_bsize, 0, &p)) != 0) {mem_err:	__db_err(dbenv, "Unable to allocate memory for the log buffer");		return (ret);	}	region->buffer_size = dbenv->lg_bsize;	region->buffer_off = R_OFFSET(&dblp->reginfo, p);	region->log_size = region->log_nsize = dbenv->lg_size;	/* Initialize the commit Queue. */	SH_TAILQ_INIT(&region->free_commits);	SH_TAILQ_INIT(&region->commits);	region->ncommit = 0;	/*	 * 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.	 */	region->persist.magic = DB_LOGMAGIC;	region->persist.version = DB_LOGVERSION;	region->persist.mode = (u_int32_t)dbenv->db_mode;	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 = dbenv->log_cursor(dbenv, &logc, 0)) != 0)		return (ret);	F_SET(logc, DB_LOG_LOCKED);	memset(&dbt, 0, sizeof(dbt));	if ((ret = logc->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 (logc->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->b_off = 0;	lp->w_off = lp->lsn.offset;skipsearch:	if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY))		__db_err(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)logc->close(logc, 0);	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;	logfile_validity logval_status, status;	u_int32_t clv, logval;	int cnt, fcnt, ret;	const char *dir;	char *c, **names, *p, *q, savech;	dbenv = dblp->dbenv;	logval_status = status = DB_LV_NONEXISTENT;	/* Return a value of 0 as the log file number on failure. */	*valp = 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)		*q = savech;	if (ret != 0) {		__db_err(dbenv, "%s: %s", dir, db_strerror(ret));		__os_free(dbenv, p);		return (ret);	}	/* Search for a valid log file name. */	for (cnt = fcnt, clv = logval = 0; --cnt >= 0;) {		if (strncmp(names[cnt], LFPREFIX, sizeof(LFPREFIX) - 1) != 0)			continue;		/*		 * Names of the form log\.[0-9]* are reserved for DB.  Other		 * names sharing LFPREFIX, such as "log.db", are legal.		 */		for (c = names[cnt] + sizeof(LFPREFIX) - 1; *c != '\0'; c++)			if (!isdigit((int)*c))				break;		if (*c != '\0')			continue;		/*		 * Use atol, not atoi; if an "int" is 16-bits, the largest		 * log file name won't fit.		 */		clv = atol(names[cnt] + (sizeof(LFPREFIX) - 1));		/*		 * If searching for the first log file, we want to return the		 * oldest log file we can read, or, if no readable log files		 * exist, the newest log file we can't read (the crossover		 * point between the old and new versions of the log file).		 *		 * If we're searching for the last log file, we want to return		 * the newest log file, period.		 *		 * Readable log files should never preceede unreadable log		 * files, that would mean the admin seriously screwed up.		 */		if (find_first) {			if (logval != 0 &&			    status != DB_LV_OLD_UNREADABLE && clv > logval)				continue;		} else			if (logval != 0 && clv < logval)				continue;		if ((ret = __log_valid(dblp, clv, 1, &status)) != 0) {			__db_err(dbenv, "Invalid log file: %s: %s",			    names[cnt], db_strerror(ret));			goto err;		}		switch (status) {		case DB_LV_NONEXISTENT:			/* __log_valid never returns DB_LV_NONEXISTENT. */			DB_ASSERT(0);			break;		case DB_LV_INCOMPLETE:			/*			 * The last log file may not have been initialized --			 * it's possible to create a log file but not write			 * anything to it.  If performing recovery (that is,			 * if find_first isn't set), ignore the file, it's			 * not interesting.  If we're searching for the first			 * log record, return the file (assuming we don't find			 * something better), as the "real" first log record			 * is likely to be in the log buffer, and we want to			 * set the file LSN for our return.			 */			if (find_first)				goto found;			break;		case DB_LV_OLD_UNREADABLE:			/*			 * If we're searching for the first log file, then we			 * only want this file if we don't yet have a file or			 * already have an unreadable file and this one is			 * newer than that one.  If we're searching for the			 * last log file, we always want this file because we			 * wouldn't be here if it wasn't newer than our current			 * choice.			 */			if (!find_first || logval == 0 ||			    (status == DB_LV_OLD_UNREADABLE && clv > logval))				goto found;			break;		case DB_LV_NORMAL:		case DB_LV_OLD_READABLE:found:			logval = clv;			logval_status = status;			break;		}	}	*valp = logval;err:	__os_dirfree(dbenv, names, fcnt);	__os_free(dbenv, p);	*statusp = logval_status;	return (ret);}/* * log_valid -- *	Validate a log file.  Returns an error code in the event of *	a fatal flaw in a the specified log file;  returns success with *	a code indicating the currentness and completeness of the specified *	log file if it is not unexpectedly flawed (that is, if it's perfectly *	normal, if it's zero-length, or if it's an old version). * * PUBLIC: int __log_valid __P((DB_LOG *, u_int32_t, int, logfile_validity *)); */int__log_valid(dblp, number, set_persist, statusp)	DB_LOG *dblp;	u_int32_t number;	int set_persist;	logfile_validity *statusp;{	DB_CIPHER *db_cipher;	DB_ENV *dbenv;	DB_FH fh;	HDR *hdr;	LOG *region;	LOGP *persist;	logfile_validity status;	size_t hdrsize, nw, recsize;	int is_hmac, need_free, ret;	u_int8_t *tmp;	char *fname;	dbenv = dblp->dbenv;	db_cipher = dbenv->crypto_handle;	persist = NULL;	status = DB_LV_NORMAL;	/* Try to open the log file. */	if ((ret = __log_name(dblp,	    number, &fname, &fh, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {		__os_free(dbenv, fname);		return (ret);

⌨️ 快捷键说明

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