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

📄 log.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
		*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 = (u_int32_t)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 precede 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, NULL, 0, &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, * PUBLIC:     DB_FH **, u_int32_t, logfile_validity *)); */int__log_valid(dblp, number, set_persist, fhpp, flags, statusp)	DB_LOG *dblp;	u_int32_t number;	int set_persist;	DB_FH **fhpp;	u_int32_t flags;	logfile_validity *statusp;{	DB_CIPHER *db_cipher;	DB_ENV *dbenv;	DB_FH *fhp;	HDR *hdr;	LOG *lp;	LOGP *persist;	logfile_validity status;	size_t hdrsize, nr, recsize;	int is_hmac, ret;	u_int8_t *tmp;	char *fname;	dbenv = dblp->dbenv;	db_cipher = dbenv->crypto_handle;	fhp = NULL;	persist = NULL;	status = DB_LV_NORMAL;	tmp = NULL;	/* Return the file handle to our caller, on request */	if (fhpp != NULL)		*fhpp = NULL;	if (flags == 0)		flags = DB_OSO_RDONLY | DB_OSO_SEQ;	/* Try to open the log file. */	if ((ret = __log_name(dblp, number, &fname, &fhp, flags)) != 0) {		__os_free(dbenv, fname);		return (ret);	}	hdrsize = HDR_NORMAL_SZ;	is_hmac = 0;	recsize = sizeof(LOGP);	if (CRYPTO_ON(dbenv)) {		hdrsize = HDR_CRYPTO_SZ;		recsize = sizeof(LOGP);		recsize += db_cipher->adj_size(recsize);		is_hmac = 1;	}	if ((ret = __os_calloc(dbenv, 1, recsize + hdrsize, &tmp)) != 0)		goto err;	hdr = (HDR *)tmp;	persist = (LOGP *)(tmp + hdrsize);	/*	 * Try to read the header.  This can fail if the log is truncated, or	 * if we find a preallocated log file where the header has not yet been	 * written, so we need to check whether the header is zero-filled.	 */	if ((ret = __os_read(dbenv, fhp, tmp, recsize + hdrsize, &nr)) != 0 ||	    nr != recsize + hdrsize ||	    (hdr->len == 0 && persist->magic == 0 && persist->log_size == 0)) {		if (ret == 0)			status = DB_LV_INCOMPLETE;		else			/*			 * The error was a fatal read error, not just an			 * incompletely initialized log file.			 */			__db_err(dbenv, "Ignoring log file: %s: %s",			    fname, db_strerror(ret));		goto err;	}	/*	 * Now we have to validate the persistent record.  We have	 * several scenarios we have to deal with:	 *	 * 1.  User has crypto turned on:	 *	- They're reading an old, unencrypted log file	 *	  .  We will fail the record size match check below.	 *	- They're reading a current, unencrypted log file	 *	  .  We will fail the record size match check below.	 *	- They're reading an old, encrypted log file [NOT YET]	 *	  .  After decryption we'll fail the version check.  [NOT YET]	 *	- They're reading a current, encrypted log file	 *	  .  We should proceed as usual.	 * 2.  User has crypto turned off:	 *	- They're reading an old, unencrypted log file	 *	  .  We will fail the version check.	 *	- They're reading a current, unencrypted log file	 *	  .  We should proceed as usual.	 *	- They're reading an old, encrypted log file [NOT YET]	 *	  .  We'll fail the magic number check (it is encrypted).	 *	- They're reading a current, encrypted log file	 *	  .  We'll fail the magic number check (it is encrypted).	 */	if (CRYPTO_ON(dbenv)) {		/*		 * If we are trying to decrypt an unencrypted log		 * we can only detect that by having an unreasonable		 * data length for our persistent data.		 */		if ((hdr->len - hdrsize) != sizeof(LOGP)) {			__db_err(dbenv, "log record size mismatch");			goto err;		}		/* Check the checksum and decrypt. */		if ((ret = __db_check_chksum(dbenv, db_cipher, &hdr->chksum[0],		    (u_int8_t *)persist, hdr->len - hdrsize, is_hmac)) != 0) {			__db_err(dbenv, "log record checksum mismatch");			goto err;		}		if ((ret = db_cipher->decrypt(dbenv, db_cipher->data,		    &hdr->iv[0], (u_int8_t *)persist, hdr->len - hdrsize)) != 0)			goto err;	}	/* Validate the header. */	if (persist->magic != DB_LOGMAGIC) {		__db_err(dbenv,		    "Ignoring log file: %s: magic number %lx, not %lx",		    fname, (u_long)persist->magic, (u_long)DB_LOGMAGIC);		ret = EINVAL;		goto err;	}	/*	 * Set our status code to indicate whether the log file belongs to an	 * unreadable or readable old version; leave it alone if and only if	 * the log file version is the current one.	 */	if (persist->version > DB_LOGVERSION) {		/* This is a fatal error--the log file is newer than DB. */		__db_err(dbenv,		    "Unacceptable log file %s: unsupported log version %lu",		    fname, (u_long)persist->version);		ret = EINVAL;		goto err;	} else if (persist->version < DB_LOGOLDVER) {		status = DB_LV_OLD_UNREADABLE;		/* This is a non-fatal error, but give some feedback. */		__db_err(dbenv,		    "Skipping log file %s: historic log version %lu",		    fname, (u_long)persist->version);		/*		 * We don't want to set persistent info based on an unreadable		 * region, so jump to "err".		 */		goto err;	} else if (persist->version < DB_LOGVERSION)		status = DB_LV_OLD_READABLE;	/*	 * Only if we have a current log do we verify the checksum.  We could	 * not check the checksum before checking the magic and version because	 * old log headers put the length and checksum in a different location.	 */	if (!CRYPTO_ON(dbenv) && ((ret = __db_check_chksum(dbenv,	    db_cipher, &hdr->chksum[0], (u_int8_t *)persist,	    hdr->len - hdrsize, is_hmac)) != 0)) {		__db_err(dbenv, "log record checksum mismatch");		goto err;	}	/*	 * If the log is readable so far and we're doing system initialization,	 * set the region's persistent information based on the headers.	 *	 * Override the current log file size.	 *	 * XXX	 * Always use the persistent header's mode, regardless of what was set	 * in the current environment.  We've always done it this way, but it's	 * probably a bug -- I can't think of a way not-changing the mode would	 * be a problem, though.	 */	if (set_persist) {		lp = dblp->reginfo.primary;		lp->log_size = persist->log_size;		lp->persist.mode = persist->mode;	}err:	if (fname != NULL)		__os_free(dbenv, fname);	if (ret == 0 && fhpp != NULL)		*fhpp = fhp;	else		/* Must close on error or if we only used it locally. */		(void)__os_closehandle(dbenv, fhp);	if (tmp != NULL)		__os_free(dbenv, tmp);	*statusp = status;	return (ret);}/* * __log_dbenv_refresh -- *	Clean up after the log system on a close or failed open. * * PUBLIC: int __log_dbenv_refresh __P((DB_ENV *)); */int__log_dbenv_refresh(dbenv)	DB_ENV *dbenv;{	DB_LOG *dblp;	LOG *lp;	REGINFO *reginfo;	int ret, t_ret;	dblp = dbenv->lg_handle;	reginfo = &dblp->reginfo;	lp = reginfo->primary;	/* We may have opened files as part of XA; if so, close them. */	F_SET(dblp, DBLOG_RECOVER);	ret = __dbreg_close_files(dbenv);	/*	 * If a private region, return the memory to the heap.  Not needed for	 * filesystem-backed or system shared memory regions, that memory isn't	 * owned by any particular process.	 */	if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {		/* Discard the flush mutex. */		__db_shalloc_free(reginfo,		    R_ADDR(reginfo, lp->flush_mutex_off));		/* Discard the buffer. */		__db_shalloc_free(reginfo, R_ADDR(reginfo, lp->buffer_off));		/* Discard stack of free file IDs. */		if (lp->free_fid_stack != INVALID_ROFF)			__db_shalloc_free(reginfo,			    R_ADDR(reginfo, lp->free_fid_stack));	}	/* Discard the per-thread lock. */	if (dblp->mutexp != NULL)		__db_mutex_free(dbenv, reginfo, dblp->mutexp);	/* Detach from the region. */	if ((t_ret = __db_r_detach(dbenv, reginfo, 0)) != 0 && ret == 0)		ret = t_ret;	/* Close open files, release allocated memory. */	if (dblp->lfhp != NULL) {		if ((t_ret =		    __os_closehandle(dbenv, dblp->lfhp)) != 0 && ret == 0)			ret = t_ret;		dblp->lfhp = NULL;	}	if (dblp->dbentry != NULL)		__os_free(dbenv, dblp->dbentry);	__os_free(dbenv, dblp);	dbenv->lg_handle = NULL;	return (ret);}/* * __log_get_cached_ckp_lsn -- *	Retrieve any last checkpoint LSN that we may have found on startup. * * PUBLIC: void __log_get_cached_ckp_lsn __P((DB_ENV *, DB_LSN *)); */void__log_get_cached_ckp_lsn(dbenv, ckp_lsnp)	DB_ENV *dbenv;	DB_LSN *ckp_lsnp;{	DB_LOG *dblp;	LOG *lp;	dblp = (DB_LOG *)dbenv->lg_handle;	lp = (LOG *)dblp->reginfo.primary;	R_LOCK(dbenv, &dblp->reginfo);	*ckp_lsnp = lp->cached_ckp_lsn;	R_UNLOCK(dbenv, &dblp->reginfo);}/* * __log_region_size -- *	Return the amount of space needed for the log region. *	Make the region large enough to hold txn_max transaction *	detail structures  plus some space to hold thread handles *	and the beginning of the shalloc region and anything we *	need for mutex system resource recording. */static size_t__log_region_size(dbenv)	DB_ENV *dbenv;{	size_t s;	s = dbenv->lg_regionmax + dbenv->lg_bsize;#ifdef HAVE_MUTEX_SYSTEM_RESOURCES	if (F_ISSET(dbenv, DB_ENV_THREAD))		s += sizeof(REGMAINT) + LG_MAINT_SIZE;#endif	return (s);}/* * __log_region_destroy *	Destroy any region maintenance info. * * PUBLIC: void __log_region_destroy __P((DB_ENV *, REGINFO *)); */void__log_region_destroy(dbenv, infop)	DB_ENV *dbenv;	REGINFO *infop;{	/*	 * This routine is called in two cases: when discarding the mutexes	 * from a previous Berkeley DB run, during recovery, and two, when	 * discarding the mutexes as we shut down the database environment.	 * In the latter case, we also need to discard shared memory segments,	 * this is the last time we use them, and the last region-specific	 * call we make.	 */#ifdef HAVE_MUTEX_SYSTEM_RESOURCES	LOG *lp;	lp = R_ADDR(infop, infop->rp->primary);	/* Destroy mutexes. */	__db_shlocks_destroy(infop, R_ADDR(infop, lp->maint_off));	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))		__db_shalloc_free(infop, R_ADDR(infop, lp->maint_off));#endif	if (infop->primary != NULL && F_ISSET(dbenv, DB_ENV_PRIVATE))		__db_shalloc_free(infop, infop->primary);}/* * __log_vtruncate *	This is a virtual truncate.  We set up the log indicators to * make everyone believe that the given record is the last one in the * log.  Returns with the next valid LSN (i.e., the LSN of the next * record to be written). This is used in replication to discard records * in the log file that do not agree with the master. * * PUBLIC: int __log_vtruncate __P((DB_ENV *, DB_LSN *, DB_LSN *, DB_LSN *));

⌨️ 快捷键说明

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