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

📄 rep_backup.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 4 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2004 *	Sleepycat Software.  All rights reserved. * * $Id: rep_backup.c,v 1.33 2004/10/29 18:08:09 bostic Exp $ */#include "db_config.h"#ifndef NO_SYSTEM_INCLUDES#if TIME_WITH_SYS_TIME#include <sys/time.h>#include <time.h>#else#if HAVE_SYS_TIME_H#include <sys/time.h>#else#include <time.h>#endif#endif#include <string.h>#endif#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/db_shash.h"#include "dbinc/db_am.h"#include "dbinc/lock.h"#include "dbinc/log.h"#include "dbinc/mp.h"#include "dbinc/qam.h"#include "dbinc/txn.h"static int __rep_filedone __P((DB_ENV *, int, REP *, __rep_fileinfo_args *,    u_int32_t));static int __rep_files_data __P((DB_ENV *, u_int8_t *, size_t *,    size_t *, int *));static int __rep_files_inmem __P((DB_ENV *, u_int8_t *, size_t *,    size_t *, int *));static int __rep_get_fileinfo __P((DB_ENV *, const char *,    __rep_fileinfo_args *, u_int8_t *, int *));static int __rep_log_setup __P((DB_ENV *, REP *));static int __rep_mpf_open __P((DB_ENV *, DB_MPOOLFILE **,    __rep_fileinfo_args *));static int __rep_page_gap __P((DB_ENV *, REP *, __rep_fileinfo_args *,    u_int32_t));static int __rep_page_sendpages __P((DB_ENV *, int,    __rep_fileinfo_args *, DB_MPOOLFILE *, DB *));static int __rep_queue_filedone __P((DB_ENV *, REP *, __rep_fileinfo_args *));static int __rep_walk_dir __P((DB_ENV *, const char *, u_int8_t *,    size_t *, size_t *, int *));static int __rep_write_page __P((DB_ENV *, REP *, __rep_fileinfo_args *));/* * __rep_update_req - *	Process an update_req and send the file information to the client. * * PUBLIC: int __rep_update_req __P((DB_ENV *, int)); */int__rep_update_req(dbenv, eid)	DB_ENV *dbenv;	int eid;{	DBT updbt;	DB_LOG *dblp;	DB_LOGC *logc;	DB_LSN lsn;	DBT data_dbt;	size_t filelen, filesz, updlen;	u_int8_t *buf, *fp;	int filecnt, ret, t_ret;	/*	 * Allocate enough for all currently open files and then some.	 * Optimize for the common use of having most databases open.	 * Allocate dbentry_cnt * 2 plus an estimated 60 bytes per	 * file for the filename/path (or multiplied by 120).	 *	 * The data we send looks like this:	 *	__rep_update_args	 *	__rep_fileinfo_args	 *	__rep_fileinfo_args	 *	...	 */	dblp = dbenv->lg_handle;	filecnt = 0;	filelen = 0;	updlen = 0;	filesz = MEGABYTE;	if ((ret = __os_calloc(dbenv, 1, filesz, &buf)) != 0)		return (ret);	/*	 * First get our file information.  Get in-memory files first	 * then get on-disk files.	 */	fp = buf + sizeof(__rep_update_args);	if ((ret = __rep_files_inmem(dbenv, fp, &filesz, &filelen,	    &filecnt)) != 0)		goto err;	if ((ret = __rep_files_data(dbenv, fp, &filesz, &filelen,	    &filecnt)) != 0)		goto err;	/*	 * Now get our first LSN.	 */	if ((ret = __log_cursor(dbenv, &logc)) != 0)		goto err;	memset(&data_dbt, 0, sizeof(data_dbt));	ret = __log_c_get(logc, &lsn, &data_dbt, DB_FIRST);	if ((t_ret = __log_c_close(logc)) != 0 && ret == 0)		ret = t_ret;	if (ret != 0)		goto err;	/*	 * Package up the update information.	 */	if ((ret = __rep_update_buf(buf, filesz, &updlen, &lsn, filecnt)) != 0)		goto err;	/*	 * We have all the file information now.  Send it to the client.	 */	memset(&updbt, 0, sizeof(updbt));	updbt.data = buf;	updbt.size = (u_int32_t)(filelen + updlen);	R_LOCK(dbenv, &dblp->reginfo);	lsn = ((LOG *)dblp->reginfo.primary)->lsn;	R_UNLOCK(dbenv, &dblp->reginfo);	(void)__rep_send_message(dbenv, eid, REP_UPDATE, &lsn, &updbt, 0);err:	__os_free(dbenv, buf);	return (ret);}/* * __rep_files_data - *	Walk through all the files in the env's data_dirs.  We need to *	open them, gather the necessary information and then close them. *	Then we need to figure out if they're already in the dbentry array. */static int__rep_files_data(dbenv, fp, fileszp, filelenp, filecntp)	DB_ENV *dbenv;	u_int8_t *fp;	size_t *fileszp, *filelenp;	int *filecntp;{	int ret;	char **ddir;	ret = 0;	if (dbenv->db_data_dir == NULL) {		/*		 * If we don't have a data dir, we have just the		 * env home dir.		 */		ret = __rep_walk_dir(dbenv, dbenv->db_home, fp,		    fileszp, filelenp, filecntp);	} else {		for (ddir = dbenv->db_data_dir; *ddir != NULL; ++ddir)			if ((ret = __rep_walk_dir(dbenv, *ddir, fp,			    fileszp, filelenp, filecntp)) != 0)				break;	}	return (ret);}static int__rep_walk_dir(dbenv, dir, fp, fileszp, filelenp, filecntp)	DB_ENV *dbenv;	const char *dir;	u_int8_t *fp;	size_t *fileszp, *filelenp;	int *filecntp;{	DBT namedbt, uiddbt;	__rep_fileinfo_args tmpfp;	size_t len, offset;	int cnt, i, ret;	u_int8_t *rfp, uid[DB_FILE_ID_LEN];	char **names;#ifdef DIAGNOSTIC	REP *rep;	DB_MSGBUF mb;	DB_REP *db_rep;	db_rep = dbenv->rep_handle;	rep = db_rep->region;#endif	memset(&namedbt, 0, sizeof(namedbt));	memset(&uiddbt, 0, sizeof(uiddbt));	RPRINT(dbenv, rep, (dbenv, &mb,	    "Walk_dir: Getting info for dir: %s", dir));	if ((ret = __os_dirlist(dbenv, dir, &names, &cnt)) != 0)		return (ret);	rfp = fp;	RPRINT(dbenv, rep, (dbenv, &mb,	    "Walk_dir: Dir %s has %d files", dir, cnt));	for (i = 0; i < cnt; i++) {		RPRINT(dbenv, rep, (dbenv, &mb,		    "Walk_dir: File %d name: %s", i, names[i]));		/*		 * Skip DB-owned files: ., ..,  __db*, DB_CONFIG, log*		 */		if (strcmp(names[i], ".") == 0)			continue;		if (strcmp(names[i], "..") == 0)			continue;		if (strncmp(names[i], "__db", 4) == 0)			continue;		if (strncmp(names[i], "DB_CONFIG", 9) == 0)			continue;		if (strncmp(names[i], "log", 3) == 0)			continue;		/*		 * We found a file to process.  Check if we need		 * to allocate more space.		 */		if ((ret = __rep_get_fileinfo(dbenv, names[i], &tmpfp, uid,		    filecntp)) != 0) {			/*			 * If we find a file that isn't a database, skip it.			 */			RPRINT(dbenv, rep, (dbenv, &mb,			    "Walk_dir: File %d %s: returned error %s",			    i, names[i], db_strerror(ret)));			ret = 0;			continue;		}		RPRINT(dbenv, rep, (dbenv, &mb,		    "Walk_dir: File %d (of %d) %s: pgsize %lu, max_pgno %lu",		    tmpfp.filenum, i, names[i],		    (u_long)tmpfp.pgsize, (u_long)tmpfp.max_pgno));		namedbt.data = names[i];		namedbt.size = (u_int32_t)strlen(names[i]) + 1;		uiddbt.data = uid;		uiddbt.size = DB_FILE_ID_LEN;retry:		ret = __rep_fileinfo_buf(rfp, *fileszp, &len,		    tmpfp.pgsize, tmpfp.pgno, tmpfp.max_pgno,		    tmpfp.filenum, tmpfp.id, tmpfp.type,		    tmpfp.flags, &uiddbt, &namedbt);		if (ret == ENOMEM) {			offset = (size_t)(rfp - fp);			*fileszp *= 2;			/*			 * Need to account for update info on both sides			 * of the allocation.			 */			fp -= sizeof(__rep_update_args);			if ((ret = __os_realloc(dbenv, *fileszp, fp)) != 0)				break;			fp += sizeof(__rep_update_args);			rfp = fp + offset;			/*			 * Now that we've reallocated the space, try to			 * store it again.			 */			goto retry;		}		rfp += len;		*filelenp += len;	}	__os_dirfree(dbenv, names, cnt);	return (ret);}static int__rep_get_fileinfo(dbenv, file, rfp, uid, filecntp)	DB_ENV *dbenv;	const char *file;	__rep_fileinfo_args *rfp;	u_int8_t *uid;	int *filecntp;{	DB *dbp, *entdbp;	DB_LOCK lk;	DB_LOG *dblp;	DB_MPOOLFILE *mpf;	DBC *dbc;	DBMETA *dbmeta;	PAGE *pagep;	int i, ret, t_ret;	dbp = NULL;	dbc = NULL;	pagep = NULL;	mpf = NULL;	LOCK_INIT(lk);	dblp = dbenv->lg_handle;	if ((ret = db_create(&dbp, dbenv, 0)) != 0)		goto err;	if ((ret = __db_open(dbp, NULL, file, NULL, DB_UNKNOWN,	    DB_RDONLY | (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0),	    0, PGNO_BASE_MD)) != 0)		goto err;	if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)		goto err;	if ((ret = __db_lget(	    dbc, 0, dbp->meta_pgno, DB_LOCK_READ, 0, &lk)) != 0)		goto err;	if ((ret = __memp_fget(dbp->mpf, &dbp->meta_pgno, 0, &pagep)) != 0)		goto err;	/*	 * We have the meta page.  Set up our information.	 */	dbmeta = (DBMETA *)pagep;	rfp->pgno = 0;	/*	 * Queue is a special-case.  We need to set max_pgno to 0 so that	 * the client can compute the pages from the meta-data.	 */	if (dbp->type == DB_QUEUE)		rfp->max_pgno = 0;	else		rfp->max_pgno = dbmeta->last_pgno;	rfp->pgsize = dbp->pgsize;	memcpy(uid, dbp->fileid, DB_FILE_ID_LEN);	rfp->filenum = (*filecntp)++;	rfp->type = dbp->type;	rfp->flags = dbp->flags;	rfp->id = DB_LOGFILEID_INVALID;	ret = __memp_fput(dbp->mpf, pagep, 0);	pagep = NULL;	if ((t_ret = __LPUT(dbc, lk)) != 0 && ret == 0)		ret = t_ret;	if (ret != 0)		goto err;err:	if ((t_ret = __LPUT(dbc, lk)) != 0 && ret == 0)		ret = t_ret;	if (dbc != NULL && (t_ret = __db_c_close(dbc)) != 0 && ret == 0)		ret = t_ret;	if (pagep != NULL &&	    (t_ret = __memp_fput(mpf, pagep, 0)) != 0 && ret == 0)		ret = t_ret;	if (dbp != NULL && (t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0)		ret = t_ret;	/*	 * We walk the entry table now, after closing the dbp because	 * otherwise we find the open from this function and the id	 * is useless in that case.	 */	if (ret == 0) {		MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);		/*		 * Walk entry table looking for this uid.		 * If we find it, save the id.		 */		for (i = 0; i < dblp->dbentry_cnt; i++) {			entdbp = dblp->dbentry[i].dbp;			if (entdbp == NULL)				break;			DB_ASSERT(entdbp->log_filename != NULL);			if (memcmp(uid,			    entdbp->log_filename->ufid,			    DB_FILE_ID_LEN) == 0)				rfp->id = i;		}		MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);	}	return (ret);}/* * __rep_files_inmem - *	Gather all the information about in-memory files. */static int__rep_files_inmem(dbenv, fp, fileszp, filelenp, filecntp)	DB_ENV *dbenv;	u_int8_t *fp;	size_t *fileszp, *filelenp;	int *filecntp;{	int ret;	COMPQUIET(dbenv, NULL);	COMPQUIET(fp, NULL);	COMPQUIET(fileszp, NULL);	COMPQUIET(filelenp, NULL);	COMPQUIET(filecntp, NULL);	ret = 0;	return (ret);}/* * __rep_page_req *	Process a page_req and send the page information to the client. * * PUBLIC: int __rep_page_req __P((DB_ENV *, int, DBT *)); */int__rep_page_req(dbenv, eid, rec)	DB_ENV *dbenv;	int eid;	DBT *rec;{	DB *dbp;	DBT msgdbt;	DB_LOG *dblp;	DB_MPOOLFILE *mpf;	__rep_fileinfo_args *msgfp;	int ret, t_ret;	void *next;#ifdef DIAGNOSTIC	DB_MSGBUF mb;	DB_REP *db_rep;	REP *rep;	db_rep = dbenv->rep_handle;	rep = db_rep->region;#endif	dblp = dbenv->lg_handle;	if ((ret = __rep_fileinfo_read(dbenv, rec->data, &next, &msgfp)) != 0)		return (ret);	/*	 * See if we can find it already.  If so we can quickly	 * access its mpool and process.  Otherwise we have to	 * open the file ourselves.	 */	RPRINT(dbenv, rep, (dbenv, &mb, "page_req: file %d page %lu to %lu",	    msgfp->filenum, (u_long)msgfp->pgno, (u_long)msgfp->max_pgno));	MUTEX_THREAD_LOCK(dbenv, dblp->mutexp);	if (msgfp->id >= 0 && dblp->dbentry_cnt > msgfp->id) {		dbp = dblp->dbentry[msgfp->id].dbp;		if (dbp != NULL) {			DB_ASSERT(dbp->log_filename != NULL);			if (memcmp(msgfp->uid.data, dbp->log_filename->ufid,			    DB_FILE_ID_LEN) == 0) {				MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);				RPRINT(dbenv, rep, (dbenv, &mb,				    "page_req: found %d in dbreg",				    msgfp->filenum));				ret = __rep_page_sendpages(dbenv, eid,				    msgfp, dbp->mpf, dbp);				goto err;			}		}	}	MUTEX_THREAD_UNLOCK(dbenv, dblp->mutexp);

⌨️ 快捷键说明

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