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

📄 log_get.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
		for (p = dblp->bufp + (lp->b_off - lp->len);;) {			memcpy(hdr, p, hdr->size);			if (hdr->prev == lsn->offset) {				b_region = (u_int32_t)(p - dblp->bufp);				break;			}			p = dblp->bufp + (hdr->prev - lp->w_off);		}	/*	 * If we don't have enough room for the record, we have to allocate	 * space.  We have to do it while holding the region lock, which is	 * truly annoying, but there's no way around it.  This call is why	 * we allocate cursor buffer space when allocating the cursor instead	 * of waiting.	 */	if (logc->bp_size <= b_region + b_disk) {		len = (size_t)DB_ALIGN((b_region + b_disk) * 2, 128);		if ((ret = __os_realloc(logc->dbenv, len, &logc->bp)) != 0)			return (ret);		logc->bp_size = (u_int32_t)len;	}	/* Copy the region's bytes to the end of the cursor's buffer. */	p = (logc->bp + logc->bp_size) - b_region;	memcpy(p, dblp->bufp, b_region);	/* Release the region lock. */	if (*rlockp == L_ACQUIRED) {		*rlockp = L_NONE;		R_UNLOCK(dbenv, &dblp->reginfo);	}	/*	 * Read the rest of the information from disk.  Neither short reads	 * or EOF are acceptable, the bytes we want had better be there.	 */	if (b_disk != 0) {		p -= b_disk;		nr = b_disk;		if ((ret = __log_c_io(		    logc, lsn->file, lsn->offset, p, &nr, NULL)) != 0)			return (ret);		if (nr < b_disk)			return (__log_c_shortread(logc, lsn, 0));	}	/* Copy the header information into the caller's structure. */	memcpy(hdr, p, hdr->size);	*pp = p;	return (0);}/* * __log_c_ondisk -- *	Read a record off disk. */static int__log_c_ondisk(logc, lsn, last_lsn, flags, hdr, pp, eofp)	DB_LOGC *logc;	DB_LSN *lsn, *last_lsn;	u_int32_t flags;	int *eofp;	HDR *hdr;	u_int8_t **pp;{	DB_ENV *dbenv;	size_t len, nr;	u_int32_t offset;	int ret;	dbenv = logc->dbenv;	*eofp = 0;	nr = hdr->size;	if ((ret =	    __log_c_io(logc, lsn->file, lsn->offset, hdr, &nr, eofp)) != 0)		return (ret);	if (*eofp)		return (0);	/*	 * If the read was successful, but we can't read a full header, assume	 * we've hit EOF.  We can't check that the header has been partially	 * zeroed out, but it's unlikely that this is caused by a write failure	 * since the header is written as a single write call and it's less	 * than sector.	 */	if (nr < hdr->size) {		*eofp = 1;		return (0);	}	/* Check the HDR. */	if ((ret = __log_c_hdrchk(logc, lsn, hdr, eofp)) != 0)		return (ret);	if (*eofp)		return (0);	/*	 * Regardless of how we return, the previous contents of the cursor's	 * buffer are useless -- trash it.	 */	logc->bp_rlen = 0;	/*	 * Otherwise, we now (finally!) know how big the record is.  (Maybe	 * we should have just stuck the length of the record into the LSN!?)	 * Make sure we have enough space.	 */	if (logc->bp_size <= hdr->len) {		len = (size_t)DB_ALIGN(hdr->len * 2, 128);		if ((ret = __os_realloc(dbenv, len, &logc->bp)) != 0)			return (ret);		logc->bp_size = (u_int32_t)len;	}	/*	 * If we're moving forward in the log file, read this record in at the	 * beginning of the buffer.  Otherwise, read this record in at the end	 * of the buffer, making sure we don't try and read before the start	 * of the file.  (We prefer positioning at the end because transaction	 * aborts use DB_SET to move backward through the log and we might get	 * lucky.)	 *	 * Read a buffer's worth, without reading past the logical EOF.  The	 * last_lsn may be a zero LSN, but that's OK, the test works anyway.	 */	if (flags == DB_FIRST || flags == DB_NEXT)		offset = lsn->offset;	else if (lsn->offset + hdr->len < logc->bp_size)		offset = 0;	else		offset = (lsn->offset + hdr->len) - logc->bp_size;	nr = logc->bp_size;	if (lsn->file == last_lsn->file && offset + nr >= last_lsn->offset)		nr = last_lsn->offset - offset;	if ((ret =	    __log_c_io(logc, lsn->file, offset, logc->bp, &nr, eofp)) != 0)		return (ret);	/*	 * We should have at least gotten the bytes up-to-and-including the	 * record we're reading.	 */	if (nr < (lsn->offset + hdr->len) - offset)		return (__log_c_shortread(logc, lsn, 1));	/*	 * Set up the return information.	 *	 * !!!	 * No need to set the bp_lsn.file field, __log_c_io set it for us.	 */	logc->bp_rlen = (u_int32_t)nr;	logc->bp_lsn.offset = offset;	*pp = logc->bp + (lsn->offset - offset);	return (0);}/* * __log_c_hdrchk -- * * Check for corrupted HDRs before we use them to allocate memory or find * records. * * If the log files were pre-allocated, a zero-filled HDR structure is the * logical file end.  However, we can see buffers filled with 0's during * recovery, too (because multiple log buffers were written asynchronously, * and one made it to disk before a different one that logically precedes * it in the log file. * * Check for impossibly large records.  The malloc should fail later, but we * have customers that run mallocs that treat all allocation failures as fatal * errors. * * Note that none of this is necessarily something awful happening.  We let * the application hand us any LSN they want, and it could be a pointer into * the middle of a log record, there's no way to tell. */static int__log_c_hdrchk(logc, lsn, hdr, eofp)	DB_LOGC *logc;	DB_LSN *lsn;	HDR *hdr;	int *eofp;{	DB_ENV *dbenv;	int ret;	dbenv = logc->dbenv;	/*	 * Check EOF before we do any other processing.	 */	if (eofp != NULL) {		if (hdr->prev == 0 && hdr->chksum[0] == 0 && hdr->len == 0) {			*eofp = 1;			return (0);		}		*eofp = 0;	}	/*	 * Sanity check the log record's size.	 * We must check it after "virtual" EOF above.	 */	if (hdr->len <= hdr->size)		goto err;	/*	 * If the cursor's max-record value isn't yet set, it means we aren't	 * reading these records from a log file and no check is necessary.	 */	if (logc->bp_maxrec != 0 && hdr->len > logc->bp_maxrec) {		/*		 * If we fail the check, there's the pathological case that		 * we're reading the last file, it's growing, and our initial		 * check information was wrong.  Get it again, to be sure.		 */		if ((ret = __log_c_set_maxrec(logc, NULL)) != 0) {			__db_err(dbenv, "DB_LOGC->get: %s", db_strerror(ret));			return (ret);		}		if (logc->bp_maxrec != 0 && hdr->len > logc->bp_maxrec)			goto err;	}	return (0);err:	if (!F_ISSET(logc, DB_LOG_SILENT_ERR))		__db_err(dbenv,		    "DB_LOGC->get: LSN %lu/%lu: invalid log record header",		    (u_long)lsn->file, (u_long)lsn->offset);	return (EIO);}/* * __log_c_io -- *	Read records from a log file. */static int__log_c_io(logc, fnum, offset, p, nrp, eofp)	DB_LOGC *logc;	u_int32_t fnum, offset;	void *p;	size_t *nrp;	int *eofp;{	DB_ENV *dbenv;	DB_LOG *dblp;	int ret;	char *np;	dbenv = logc->dbenv;	dblp = dbenv->lg_handle;	/*	 * If we've switched files, discard the current file handle and acquire	 * a new one.	 */	if (logc->c_fhp != NULL && logc->bp_lsn.file != fnum) {		ret = __os_closehandle(dbenv, logc->c_fhp);		logc->c_fhp = NULL;		logc->bp_lsn.file = 0;		if (ret != 0)			return (ret);	}	if (logc->c_fhp == NULL) {		if ((ret = __log_name(dblp, fnum,		    &np, &logc->c_fhp, DB_OSO_RDONLY | DB_OSO_SEQ)) != 0) {			/*			 * If we're allowed to return EOF, assume that's the			 * problem, set the EOF status flag and return 0.			 */			if (eofp != NULL) {				*eofp = 1;				ret = 0;			} else if (!F_ISSET(logc, DB_LOG_SILENT_ERR))				__db_err(dbenv, "DB_LOGC->get: %s: %s",				    np, db_strerror(ret));			__os_free(dbenv, np);			return (ret);		}		if ((ret = __log_c_set_maxrec(logc, np)) != 0) {			__db_err(dbenv,			    "DB_LOGC->get: %s: %s", np, db_strerror(ret));			__os_free(dbenv, np);			return (ret);		}		__os_free(dbenv, np);		logc->bp_lsn.file = fnum;	}	/* Seek to the record's offset. */	if ((ret = __os_seek(dbenv,	    logc->c_fhp, 0, 0, offset, 0, DB_OS_SEEK_SET)) != 0) {		if (!F_ISSET(logc, DB_LOG_SILENT_ERR))			__db_err(dbenv,			    "DB_LOGC->get: LSN: %lu/%lu: seek: %s",			    (u_long)fnum, (u_long)offset, db_strerror(ret));		return (ret);	}	/* Read the data. */	if ((ret = __os_read(dbenv, logc->c_fhp, p, *nrp, nrp)) != 0) {		if (!F_ISSET(logc, DB_LOG_SILENT_ERR))			__db_err(dbenv,			    "DB_LOGC->get: LSN: %lu/%lu: read: %s",			    (u_long)fnum, (u_long)offset, db_strerror(ret));		return (ret);	}	return (0);}/* * __log_c_shortread -- *	Read was short -- return a consistent error message and error. */static int__log_c_shortread(logc, lsn, check_silent)	DB_LOGC *logc;	DB_LSN *lsn;	int check_silent;{	if (!check_silent || !F_ISSET(logc, DB_LOG_SILENT_ERR))		__db_err(logc->dbenv, "DB_LOGC->get: LSN: %lu/%lu: short read",		    (u_long)lsn->file, (u_long)lsn->offset);	return (EIO);}/* * __log_c_set_maxrec -- *	Bound the maximum log record size in a log file. */static int__log_c_set_maxrec(logc, np)	DB_LOGC *logc;	char *np;{	DB_ENV *dbenv;	DB_LOG *dblp;	LOG *lp;	u_int32_t mbytes, bytes;	int ret;	dbenv = logc->dbenv;	dblp = dbenv->lg_handle;	/*	 * We don't want to try and allocate huge chunks of memory because	 * applications with error-checking malloc's often consider that a	 * hard failure.  If we're about to look at a corrupted record with	 * a bizarre size, we need to know before trying to allocate space	 * to hold it.  We could read the persistent data at the beginning	 * of the file but that's hard -- we may have to decrypt it, checksum	 * it and so on.  Stat the file instead.	 */	if (logc->c_fhp != NULL) {		if ((ret = __os_ioinfo(dbenv, np, logc->c_fhp,		    &mbytes, &bytes, NULL)) != 0)			return (ret);		if (logc->bp_maxrec < (mbytes * MEGABYTE + bytes))			logc->bp_maxrec = mbytes * MEGABYTE + bytes;	}	/*	 * If reading from the log file currently being written, we could get	 * an incorrect size, that is, if the cursor was opened on the file	 * when it had only a few hundred bytes, and then the cursor used to	 * move forward in the file, after more log records were written, the	 * original stat value would be wrong.  Use the maximum of the current	 * log file size and the size of the buffer -- that should represent	 * the max of any log record currently in the file.	 *	 * The log buffer size is set when the environment is opened and never	 * changed, we don't need a lock on it.	 */	lp = dblp->reginfo.primary;	if (logc->bp_maxrec < lp->buffer_size)		logc->bp_maxrec = lp->buffer_size;	return (0);}

⌨️ 快捷键说明

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