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

📄 log.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
 */int__log_vtruncate(dbenv, lsn, ckplsn, trunclsn)	DB_ENV *dbenv;	DB_LSN *lsn, *ckplsn, *trunclsn;{	DBT log_dbt;	DB_LOG *dblp;	DB_LOGC *logc;	DB_LSN end_lsn;	DB_MUTEX *flush_mutexp;	LOG *lp;	u_int32_t bytes, c_len;	int ret, t_ret;	/* Need to find out the length of this soon-to-be-last record. */	if ((ret = __log_cursor(dbenv, &logc)) != 0)		return (ret);	memset(&log_dbt, 0, sizeof(log_dbt));	ret = __log_c_get(logc, lsn, &log_dbt, DB_SET);	c_len = logc->c_len;	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)		ret = t_ret;	if (ret != 0)		return (ret);	/* Now do the truncate. */	dblp = (DB_LOG *)dbenv->lg_handle;	lp = (LOG *)dblp->reginfo.primary;	R_LOCK(dbenv, &dblp->reginfo);	/*	 * Flush the log so we can simply initialize the in-memory buffer	 * after the truncate.	 */	if ((ret = __log_flush_int(dblp, NULL, 0)) != 0)		goto err;	end_lsn = lp->lsn;	lp->lsn = *lsn;	lp->len = c_len;	lp->lsn.offset += lp->len;	if (lp->db_log_inmemory &&	    (ret = __log_inmem_lsnoff(dblp, &lp->lsn, &lp->b_off)) != 0)		goto err;	/*	 * I am going to assume that the number of bytes written since	 * the last checkpoint doesn't exceed a 32-bit number.	 */	DB_ASSERT(lp->lsn.file >= ckplsn->file);	bytes = 0;	if (ckplsn->file != lp->lsn.file) {		bytes = lp->log_size - ckplsn->offset;		if (lp->lsn.file > ckplsn->file + 1)			bytes += lp->log_size *			    ((lp->lsn.file - ckplsn->file) - 1);		bytes += lp->lsn.offset;	} else		bytes = lp->lsn.offset - ckplsn->offset;	lp->stat.st_wc_mbytes += bytes / MEGABYTE;	lp->stat.st_wc_bytes += bytes % MEGABYTE;	/*	 * If the saved lsn is greater than our new end of log, reset it	 * to our current end of log.	 */	flush_mutexp = R_ADDR(&dblp->reginfo, lp->flush_mutex_off);	MUTEX_LOCK(dbenv, flush_mutexp);	if (log_compare(&lp->s_lsn, lsn) > 0)		lp->s_lsn = lp->lsn;	MUTEX_UNLOCK(dbenv, flush_mutexp);	/* Initialize the in-region buffer to a pristine state. */	ZERO_LSN(lp->f_lsn);	lp->w_off = lp->lsn.offset;	if (trunclsn != NULL)		*trunclsn = lp->lsn;	/* Truncate the log to the new point. */	if ((ret = __log_zero(dbenv, &lp->lsn, &end_lsn)) != 0)		goto err;err:	R_UNLOCK(dbenv, &dblp->reginfo);	return (ret);}/* * __log_is_outdated -- *	Used by the replication system to identify if a client's logs * are too old.  The log represented by dbenv is compared to the file * number passed in fnum.  If the log file fnum does not exist and is * lower-numbered than the current logs, the we return *outdatedp non * zero, else we return it 0. * * PUBLIC: int __log_is_outdated __P((DB_ENV *, u_int32_t, int *)); */int__log_is_outdated(dbenv, fnum, outdatedp)	DB_ENV *dbenv;	u_int32_t fnum;	int *outdatedp;{	DB_LOG *dblp;	LOG *lp;	char *name;	int ret;	u_int32_t cfile;	struct __db_filestart *filestart;	dblp = dbenv->lg_handle;	if (F_ISSET(dbenv, DB_ENV_LOG_INMEMORY)) {		R_LOCK(dbenv, &dblp->reginfo);		lp = (LOG *)dblp->reginfo.primary;		filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);		*outdatedp = (fnum < filestart->file);		R_UNLOCK(dbenv, &dblp->reginfo);		return (0);	}	*outdatedp = 0;	if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0)		return (ret);	/* If the file exists, we're just fine. */	if (__os_exists(name, NULL) == 0)		goto out;	/*	 * It didn't exist, decide if the file number is too big or	 * too little.  If it's too little, then we need to indicate	 * that the LSN is outdated.	 */	R_LOCK(dbenv, &dblp->reginfo);	lp = (LOG *)dblp->reginfo.primary;	cfile = lp->lsn.file;	R_UNLOCK(dbenv, &dblp->reginfo);	if (cfile > fnum)		*outdatedp = 1;out:	__os_free(dbenv, name);	return (ret);}/* * __log_zero -- *	Zero out the tail of a log after a truncate. */static int__log_zero(dbenv, from_lsn, to_lsn)	DB_ENV *dbenv;	DB_LSN *from_lsn, *to_lsn;{	DB_FH *fhp;	DB_LOG *dblp;	LOG *lp;	struct __db_filestart *filestart, *nextstart;	size_t nbytes, len, nw;	u_int32_t fn, mbytes, bytes;	u_int8_t buf[4096];	int ret;	char *fname;	dblp = dbenv->lg_handle;	DB_ASSERT(log_compare(from_lsn, to_lsn) <= 0);	if (log_compare(from_lsn, to_lsn) > 0) {		__db_err(dbenv,		    "Warning: truncating to point beyond end of log");		return (0);	}	lp = (LOG *)dblp->reginfo.primary;	if (lp->db_log_inmemory) {		/*		 * Remove the first file if it is invalidated by this write.		 * Log records can't be bigger than a file, so we only need to		 * check the first file.		 */		for (filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);		    filestart != NULL && from_lsn->file < filestart->file;		    filestart = nextstart) {			nextstart = SH_TAILQ_NEXT(filestart,			    links, __db_filestart);			SH_TAILQ_REMOVE(&lp->logfiles, filestart,			    links, __db_filestart);			SH_TAILQ_INSERT_HEAD(&lp->free_logfiles, filestart,			    links, __db_filestart);		}		return (0);	}	/* Close any open file handles so unlinks don't fail. */	if (dblp->lfhp != NULL) {		(void)__os_closehandle(dbenv, dblp->lfhp);		dblp->lfhp = NULL;	}	/* Throw away any extra log files that we have around. */	for (fn = from_lsn->file + 1;; fn++) {		if (__log_name(dblp, fn, &fname, &fhp, DB_OSO_RDONLY) != 0) {			__os_free(dbenv, fname);			break;		}		(void)__os_closehandle(dbenv, fhp);		ret = __os_unlink(dbenv, fname);		__os_free(dbenv, fname);		if (ret != 0)			return (ret);	}	/* We removed some log files; have to 0 to end of file. */	if ((ret =	    __log_name(dblp, from_lsn->file, &fname, &dblp->lfhp, 0)) != 0)		return (ret);	__os_free(dbenv, fname);	if ((ret = __os_ioinfo(dbenv,	    NULL, dblp->lfhp, &mbytes, &bytes, NULL)) != 0)		goto err;	DB_ASSERT((mbytes * MEGABYTE + bytes) >= from_lsn->offset);	len = (mbytes * MEGABYTE + bytes) - from_lsn->offset;	memset(buf, 0, sizeof(buf));	/* Initialize the write position. */	if ((ret = __os_seek(dbenv,	    dblp->lfhp, 0, 0, from_lsn->offset, 0, DB_OS_SEEK_SET)) != 0)		goto err;	while (len > 0) {		nbytes = len > sizeof(buf) ? sizeof(buf) : len;		if ((ret =		    __os_write(dbenv, dblp->lfhp, buf, nbytes, &nw)) != 0)			goto err;		len -= nbytes;	}err:	(void)__os_closehandle(dbenv, dblp->lfhp);	dblp->lfhp = NULL;	return (ret);}/* * __log_inmem_lsnoff -- *	Find the offset in the buffer of a given LSN. * * PUBLIC: int __log_inmem_lsnoff __P((DB_LOG *, DB_LSN *, size_t *)); */int__log_inmem_lsnoff(dblp, lsn, offsetp)	DB_LOG *dblp;	DB_LSN *lsn;	size_t *offsetp;{	LOG *lp;	struct __db_filestart *filestart;	lp = (LOG *)dblp->reginfo.primary;	SH_TAILQ_FOREACH(filestart, &lp->logfiles, links, __db_filestart)		if (filestart->file == lsn->file) {			*offsetp =			    (filestart->b_off + lsn->offset) % lp->buffer_size;			return (0);		}	return (DB_NOTFOUND);}/* * __log_inmem_newfile -- *	Records the offset of the beginning of a new file in the in-memory *	buffer. * * PUBLIC: int __log_inmem_newfile __P((DB_LOG *, u_int32_t)); */int__log_inmem_newfile(dblp, file)	DB_LOG *dblp;	u_int32_t file;{	HDR hdr;	LOG *lp;	struct __db_filestart *filestart;	int ret;#ifdef DIAGNOSTIC	struct __db_filestart *first, *last;#endif	lp = (LOG *)dblp->reginfo.primary;	/*	 * We write an empty header at the end of every in-memory log file.	 * This is used during cursor traversal to indicate when to switch the	 * LSN to the next file.	 */	if (file > 1) {		memset(&hdr, 0, sizeof(HDR));		__log_inmem_copyin(dblp, lp->b_off, &hdr, sizeof(HDR));		lp->b_off = (lp->b_off + sizeof(HDR)) % lp->buffer_size;	}	filestart = SH_TAILQ_FIRST(&lp->free_logfiles, __db_filestart);	if (filestart == NULL) {		if ((ret = __db_shalloc(&dblp->reginfo,		    sizeof(struct __db_filestart), 0, &filestart)) != 0)			return (ret);		memset(filestart, 0, sizeof(*filestart));	} else		SH_TAILQ_REMOVE(&lp->free_logfiles, filestart,		    links, __db_filestart);	filestart->file = file;	filestart->b_off = lp->b_off;#ifdef DIAGNOSTIC	first = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);	last = SH_TAILQ_LAST(&(lp)->logfiles, links, __db_filestart);	/* Check that we don't wrap. */	DB_ASSERT(!first || first == last ||	    RINGBUF_LEN(lp, first->b_off, lp->b_off) ==	    RINGBUF_LEN(lp, first->b_off, last->b_off) +	    RINGBUF_LEN(lp, last->b_off, lp->b_off));#endif	SH_TAILQ_INSERT_TAIL(&lp->logfiles, filestart, links);	return (0);}/* * __log_inmem_chkspace -- *	Ensure that the requested amount of space is available in the buffer, *	and invalidate the region. *      Note: assumes that the region lock is held on entry. * * PUBLIC: int __log_inmem_chkspace __P((DB_LOG *, size_t)); */int__log_inmem_chkspace(dblp, len)	DB_LOG *dblp;	size_t len;{	LOG *lp;	DB_LSN active_lsn, old_active_lsn;	struct __db_filestart *filestart;	lp = dblp->reginfo.primary;	DB_ASSERT(lp->db_log_inmemory);	/*	 * Allow room for an extra header so that we don't need to check for	 * space when switching files.	 */	len += sizeof(HDR);	/*	 * If transactions are enabled and we're about to fill available space,	 * update the active LSN and recheck.  If transactions aren't enabled,	 * don't even bother checking: in that case we can always overwrite old	 * log records, because we're never going to abort.	 */	while (TXN_ON(dblp->dbenv) &&	    RINGBUF_LEN(lp, lp->b_off, lp->a_off) <= len) {		old_active_lsn = lp->active_lsn;		active_lsn = lp->lsn;		/*		 * Drop the log region lock so we don't hold it while		 * taking the transaction region lock.		 */		R_UNLOCK(dblp->dbenv, &dblp->reginfo);		__txn_getactive(dblp->dbenv, &active_lsn);		R_LOCK(dblp->dbenv, &dblp->reginfo);		active_lsn.offset = 0;		/* If we didn't make any progress, give up. */		if (log_compare(&active_lsn, &old_active_lsn) == 0) {			__db_err(dblp->dbenv,      "In-memory log buffer is full (an active transaction spans the buffer)");			return (DB_LOG_BUFFER_FULL);		}		/* Make sure we're moving the region LSN forwards. */		if (log_compare(&active_lsn, &lp->active_lsn) > 0) {			lp->active_lsn = active_lsn;			(void)__log_inmem_lsnoff(dblp, &active_lsn,			    &lp->a_off);		}	}	/*	 * Remove the first file if it is invalidated by this write.	 * Log records can't be bigger than a file, so we only need to	 * check the first file.	 */	filestart = SH_TAILQ_FIRST(&lp->logfiles, __db_filestart);	if (filestart != NULL &&	    RINGBUF_LEN(lp, lp->b_off, filestart->b_off) <= len) {		SH_TAILQ_REMOVE(&lp->logfiles, filestart,		    links, __db_filestart);		SH_TAILQ_INSERT_HEAD(&lp->free_logfiles, filestart,		    links, __db_filestart);		lp->f_lsn.file = filestart->file + 1;	}	return (0);}/* * __log_inmem_copyout -- *	Copies the given number of bytes from the buffer -- no checking. *      Note: assumes that the region lock is held on entry. * * PUBLIC: void __log_inmem_copyout __P((DB_LOG *, size_t, void *, size_t)); */void__log_inmem_copyout(dblp, offset, buf, size)	DB_LOG *dblp;	size_t offset;	void *buf;	size_t size;{	LOG *lp;	size_t nbytes;	lp = (LOG *)dblp->reginfo.primary;	nbytes = (offset + size < lp->buffer_size) ?	    size : lp->buffer_size - offset;	memcpy(buf, dblp->bufp + offset, nbytes);	if (nbytes < size)		memcpy((u_int8_t *)buf + nbytes, dblp->bufp, size - nbytes);}/* * __log_inmem_copyin -- *	Copies the given number of bytes into the buffer -- no checking. *      Note: assumes that the region lock is held on entry. * * PUBLIC: void __log_inmem_copyin __P((DB_LOG *, size_t, void *, size_t)); */void__log_inmem_copyin(dblp, offset, buf, size)	DB_LOG *dblp;	size_t offset;	void *buf;	size_t size;{	LOG *lp;	size_t nbytes;	lp = (LOG *)dblp->reginfo.primary;	nbytes = (offset + size < lp->buffer_size) ?	    size : lp->buffer_size - offset;	memcpy(dblp->bufp + offset, buf, nbytes);	if (nbytes < size)		memcpy(dblp->bufp, (u_int8_t *)buf + nbytes, size - nbytes);}

⌨️ 快捷键说明

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