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

📄 log_put.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (release)		R_LOCK(dbenv, &dblp->reginfo);	lp->in_flush--;	++lp->stat.st_scount;	/*	 * How many flush calls (usually commits) did this call actually sync?	 * At least one, if it got here.	 */	ncommit = 1;done:	if (lp->ncommit != 0) {		first = 1;		for (commit = SH_TAILQ_FIRST(&lp->commits, __db_commit);		    commit != NULL;		    commit = SH_TAILQ_NEXT(commit, links, __db_commit))			if (log_compare(&lp->s_lsn, &commit->lsn) > 0) {				MUTEX_UNLOCK(dbenv, &commit->mutex);				SH_TAILQ_REMOVE(				    &lp->commits, commit, links, __db_commit);				ncommit++;			} else if (first == 1) {				F_SET(commit, DB_COMMIT_FLUSH);				MUTEX_UNLOCK(dbenv, &commit->mutex);				SH_TAILQ_REMOVE(				    &lp->commits, commit, links, __db_commit);				/*				 * This thread will wake and flush.				 * If another thread commits and flushes				 * first we will waste a trip trough the				 * mutex.				 */				lp->in_flush++;				first = 0;			}	}	if (lp->stat.st_maxcommitperflush < ncommit)		lp->stat.st_maxcommitperflush = ncommit;	if (lp->stat.st_mincommitperflush > ncommit ||	    lp->stat.st_mincommitperflush == 0)		lp->stat.st_mincommitperflush = ncommit;	return (ret);}/* * __log_fill -- *	Write information into the log. */static int__log_fill(dblp, lsn, addr, len)	DB_LOG *dblp;	DB_LSN *lsn;	void *addr;	u_int32_t len;{	LOG *lp;	u_int32_t bsize, nrec;	size_t nw, remain;	int ret;	lp = dblp->reginfo.primary;	bsize = lp->buffer_size;	if (lp->db_log_inmemory) {		__log_inmem_copyin(dblp, lp->b_off, addr, len);		lp->b_off = (lp->b_off + len) % lp->buffer_size;		return (0);	}	while (len > 0) {			/* Copy out the data. */		/*		 * If we're beginning a new buffer, note the user LSN to which		 * the first byte of the buffer belongs.  We have to know this		 * when flushing the buffer so that we know if the in-memory		 * buffer needs to be flushed.		 */		if (lp->b_off == 0)			lp->f_lsn = *lsn;		/*		 * If we're on a buffer boundary and the data is big enough,		 * copy as many records as we can directly from the data.		 */		if (lp->b_off == 0 && len >= bsize) {			nrec = len / bsize;			if ((ret = __log_write(dblp, addr, nrec * bsize)) != 0)				return (ret);			addr = (u_int8_t *)addr + nrec * bsize;			len -= nrec * bsize;			++lp->stat.st_wcount_fill;			continue;		}		/* Figure out how many bytes we can copy this time. */		remain = bsize - lp->b_off;		nw = remain > len ? len : remain;		memcpy(dblp->bufp + lp->b_off, addr, nw);		addr = (u_int8_t *)addr + nw;		len -= (u_int32_t)nw;		lp->b_off += nw;		/* If we fill the buffer, flush it. */		if (lp->b_off == bsize) {			if ((ret = __log_write(dblp, dblp->bufp, bsize)) != 0)				return (ret);			lp->b_off = 0;			++lp->stat.st_wcount_fill;		}	}	return (0);}/* * __log_write -- *	Write the log buffer to disk. */static int__log_write(dblp, addr, len)	DB_LOG *dblp;	void *addr;	u_int32_t len;{	DB_ENV *dbenv;	LOG *lp;	size_t nw;	int ret;	dbenv = dblp->dbenv;	lp = dblp->reginfo.primary;	DB_ASSERT(!lp->db_log_inmemory);	/*	 * If we haven't opened the log file yet or the current one has	 * changed, acquire a new log file.  We are creating the file if we're	 * about to write to the start of it, in other words, if the write	 * offset is zero.	 */	if (dblp->lfhp == NULL || dblp->lfname != lp->lsn.file)		if ((ret = __log_newfh(dblp, lp->w_off == 0)) != 0)			return (ret);	/*	 * If we're writing the first block in a log file on a filesystem that	 * guarantees unwritten blocks are zero-filled, we set the size of the	 * file in advance.  This increases sync performance on some systems,	 * because they don't need to update metadata on every sync.	 */#ifdef HAVE_FILESYSTEM_NOTZERO	if (lp->w_off == 0 && !__os_fs_notzero())#else	if (lp->w_off == 0)#endif		ret = __db_fileinit(dbenv, dblp->lfhp, lp->log_size, 0);	/*	 * Seek to the offset in the file (someone may have written it	 * since we last did).	 */	if ((ret = __os_seek(dbenv,	    dblp->lfhp, 0, 0, lp->w_off, 0, DB_OS_SEEK_SET)) != 0 ||	    (ret = __os_write(dbenv, dblp->lfhp, addr, len, &nw)) != 0)		return (ret);	/* Reset the buffer offset and update the seek offset. */	lp->w_off += len;	/* Update written statistics. */	if ((lp->stat.st_w_bytes += len) >= MEGABYTE) {		lp->stat.st_w_bytes -= MEGABYTE;		++lp->stat.st_w_mbytes;	}	if ((lp->stat.st_wc_bytes += len) >= MEGABYTE) {		lp->stat.st_wc_bytes -= MEGABYTE;		++lp->stat.st_wc_mbytes;	}	++lp->stat.st_wcount;	return (0);}/* * __log_file_pp -- *	DB_ENV->log_file pre/post processing. * * PUBLIC: int __log_file_pp __P((DB_ENV *, const DB_LSN *, char *, size_t)); */int__log_file_pp(dbenv, lsn, namep, len)	DB_ENV *dbenv;	const DB_LSN *lsn;	char *namep;	size_t len;{	int rep_check, ret;	PANIC_CHECK(dbenv);	ENV_REQUIRES_CONFIG(dbenv,	    dbenv->lg_handle, "DB_ENV->log_file", DB_INIT_LOG);	if (F_ISSET(dbenv, DB_ENV_LOG_INMEMORY)) {		__db_err(dbenv,		    "DB_ENV->log_file is illegal with in-memory logs.");		return (EINVAL);	}	rep_check = IS_ENV_REPLICATED(dbenv) ? 1 : 0;	if (rep_check)		__env_rep_enter(dbenv);	ret = __log_file(dbenv, lsn, namep, len);	if (rep_check)		__env_db_rep_exit(dbenv);	return (ret);}/* * __log_file -- *	DB_ENV->log_file. */static int__log_file(dbenv, lsn, namep, len)	DB_ENV *dbenv;	const DB_LSN *lsn;	char *namep;	size_t len;{	DB_LOG *dblp;	int ret;	char *name;	dblp = dbenv->lg_handle;	R_LOCK(dbenv, &dblp->reginfo);	ret = __log_name(dblp, lsn->file, &name, NULL, 0);	R_UNLOCK(dbenv, &dblp->reginfo);	if (ret != 0)		return (ret);	/* Check to make sure there's enough room and copy the name. */	if (len < strlen(name) + 1) {		*namep = '\0';		__db_err(dbenv, "DB_ENV->log_file: name buffer is too short");		return (EINVAL);	}	(void)strcpy(namep, name);	__os_free(dbenv, name);	return (0);}/* * __log_newfh -- *	Acquire a file handle for the current log file. */static int__log_newfh(dblp, create)	DB_LOG *dblp;	int create;{	DB_ENV *dbenv;	LOG *lp;	u_int32_t flags;	int ret;	logfile_validity status;	dbenv = dblp->dbenv;	lp = dblp->reginfo.primary;	/* Close any previous file descriptor. */	if (dblp->lfhp != NULL) {		(void)__os_closehandle(dbenv, dblp->lfhp);		dblp->lfhp = NULL;	}	flags = DB_OSO_LOG | DB_OSO_SEQ |	    (create ? DB_OSO_CREATE : 0) |	    (F_ISSET(dbenv, DB_ENV_DIRECT_LOG) ? DB_OSO_DIRECT : 0) |	    (F_ISSET(dbenv, DB_ENV_DSYNC_LOG) ? DB_OSO_DSYNC : 0);	/* Get the path of the new file and open it. */	dblp->lfname = lp->lsn.file;	if ((ret = __log_valid(dblp, dblp->lfname, 0, &dblp->lfhp,	    flags, &status)) != 0)		__db_err(dbenv,		    "DB_ENV->log_put: %d: %s", lp->lsn.file, db_strerror(ret));	else if (status != DB_LV_NORMAL && status != DB_LV_INCOMPLETE)		ret = DB_NOTFOUND;	return (ret);}/* * __log_name -- *	Return the log name for a particular file, and optionally open it. * * PUBLIC: int __log_name __P((DB_LOG *, * PUBLIC:     u_int32_t, char **, DB_FH **, u_int32_t)); */int__log_name(dblp, filenumber, namep, fhpp, flags)	DB_LOG *dblp;	u_int32_t filenumber, flags;	char **namep;	DB_FH **fhpp;{	DB_ENV *dbenv;	LOG *lp;	int ret;	char *oname;	char old[sizeof(LFPREFIX) + 5 + 20], new[sizeof(LFPREFIX) + 10 + 20];	dbenv = dblp->dbenv;	lp = dblp->reginfo.primary;	DB_ASSERT(!lp->db_log_inmemory);	/*	 * !!!	 * The semantics of this routine are bizarre.	 *	 * The reason for all of this is that we need a place where we can	 * intercept requests for log files, and, if appropriate, check for	 * both the old-style and new-style log file names.  The trick is	 * that all callers of this routine that are opening the log file	 * read-only want to use an old-style file name if they can't find	 * a match using a new-style name.  The only down-side is that some	 * callers may check for the old-style when they really don't need	 * to, but that shouldn't mess up anything, and we only check for	 * the old-style name when we've already failed to find a new-style	 * one.	 *	 * Create a new-style file name, and if we're not going to open the	 * file, return regardless.	 */	(void)snprintf(new, sizeof(new), LFNAME, filenumber);	if ((ret = __db_appname(dbenv,	    DB_APP_LOG, new, 0, NULL, namep)) != 0 || fhpp == NULL)		return (ret);	/* Open the new-style file -- if we succeed, we're done. */	if ((ret = __os_open_extend(dbenv, *namep, 0, flags,	    (int)lp->persist.mode, fhpp)) == 0)		return (0);	/*	 * The open failed... if the DB_RDONLY flag isn't set, we're done,	 * the caller isn't interested in old-style files.	 */	if (!LF_ISSET(DB_OSO_RDONLY)) {		__db_err(dbenv,		    "%s: log file open failed: %s", *namep, db_strerror(ret));		return (__db_panic(dbenv, ret));	}	/* Create an old-style file name. */	(void)snprintf(old, sizeof(old), LFNAME_V1, filenumber);	if ((ret = __db_appname(dbenv, DB_APP_LOG, old, 0, NULL, &oname)) != 0)		goto err;	/*	 * Open the old-style file -- if we succeed, we're done.  Free the	 * space allocated for the new-style name and return the old-style	 * name to the caller.	 */	if ((ret =	    __os_open(dbenv, oname, flags, (int)lp->persist.mode, fhpp)) == 0) {		__os_free(dbenv, *namep);		*namep = oname;		return (0);	}	/*	 * Couldn't find either style of name -- return the new-style name	 * for the caller's error message.  If it's an old-style name that's	 * actually missing we're going to confuse the user with the error	 * message, but that implies that not only were we looking for an	 * old-style name, but we expected it to exist and we weren't just	 * looking for any log file.  That's not a likely error.	 */err:	__os_free(dbenv, oname);	return (ret);}/* * __log_rep_put -- *	Short-circuit way for replication clients to put records into the * log.  Replication clients' logs need to be laid out exactly their masters' * are, so we let replication take responsibility for when the log gets * flushed, when log switches files, etc.  This is just a thin PUBLIC wrapper * for __log_putr with a slightly prettier interface. * * Note that the db_rep->db_mutexp should be held when this is called. * Note that we acquire the log region lock while holding db_mutexp. * * PUBLIC: int __log_rep_put __P((DB_ENV *, DB_LSN *, const DBT *)); */int__log_rep_put(dbenv, lsnp, rec)	DB_ENV *dbenv;	DB_LSN *lsnp;	const DBT *rec;{	DB_CIPHER *db_cipher;	DB_LOG *dblp;	HDR hdr;	DBT *dbt, t;	LOG *lp;	int need_free, ret;	dblp = dbenv->lg_handle;	lp = dblp->reginfo.primary;	R_LOCK(dbenv, &dblp->reginfo);	memset(&hdr, 0, sizeof(HDR));	t = *rec;	dbt = &t;	need_free = 0;	db_cipher = (DB_CIPHER *)dbenv->crypto_handle;	if (CRYPTO_ON(dbenv))		t.size += db_cipher->adj_size(rec->size);	if ((ret = __os_calloc(dbenv, 1, t.size, &t.data)) != 0)		goto err;	need_free = 1;	memcpy(t.data, rec->data, rec->size);	if ((ret = __log_encrypt_record(dbenv, dbt, &hdr, rec->size)) != 0)		goto err;	__db_chksum(t.data, t.size,	    (CRYPTO_ON(dbenv)) ? db_cipher->mac_key : NULL, hdr.chksum);	DB_ASSERT(log_compare(lsnp, &lp->lsn) == 0);	ret = __log_putr(dblp, lsnp, dbt, lp->lsn.offset - lp->len, &hdr);err:	/*	 * !!! Assume caller holds db_rep->db_mutex to modify ready_lsn.	 */	lp->ready_lsn = lp->lsn;	R_UNLOCK(dbenv, &dblp->reginfo);	if (need_free)		__os_free(dbenv, t.data);	return (ret);}static int__log_encrypt_record(dbenv, dbt, hdr, orig)	DB_ENV *dbenv;	DBT *dbt;	HDR *hdr;	u_int32_t orig;{	DB_CIPHER *db_cipher;	int ret;	if (CRYPTO_ON(dbenv)) {		db_cipher = (DB_CIPHER *)dbenv->crypto_handle;		hdr->size = HDR_CRYPTO_SZ;		hdr->orig_size = orig;		if ((ret = db_cipher->encrypt(dbenv, db_cipher->data,		    hdr->iv, dbt->data, dbt->size)) != 0)			return (ret);	} else {		hdr->size = HDR_NORMAL_SZ;	}	return (0);}

⌨️ 快捷键说明

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