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

📄 rep_backup.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 4 页
字号:
	 */	if (rep->file_mpf != NULL) {		ret = __memp_fclose(rep->file_mpf, 0);		rep->file_mpf = NULL;		if (ret != 0)			goto err;	}	/*	 * 2.  Close/reset the page database.	 */	ret = __db_close(rep->file_dbp, NULL, DB_NOSYNC);	rep->file_dbp = NULL;	if (ret != 0)		goto err;	/*	 * 3.  Check if we have all file data.  If so, request logs.	 */	__os_free(dbenv, rep->curinfo);	if (++rep->curfile == rep->nfiles) {		RPRINT(dbenv, rep, (dbenv, &mb,		    "FILEDONE: have %d files.  RECOVER_LOG now", rep->nfiles));		/*		 * Move to REP_RECOVER_LOG state.		 * Request logs.		 */		__os_free(dbenv, rep->originfo);		/*		 * We need to do a sync here so that any later opens		 * can find the file and file id.  We need to do it		 * before we clear REP_F_RECOVER_PAGE so that we do not		 * try to flush the log.		 */		if ((ret = __memp_sync(dbenv, NULL)) != 0)			goto err;		F_CLR(rep, REP_F_RECOVER_PAGE);		F_SET(rep, REP_F_RECOVER_LOG);		memset(&dbt, 0, sizeof(dbt));		dbt.data = &rep->last_lsn;		dbt.size = sizeof(rep->last_lsn);		RPRINT(dbenv, rep, (dbenv, &mb,		    "FILEDONE: LOG_REQ from LSN [%lu][%lu] to [%lu][%lu]",		    (u_long)rep->first_lsn.file, (u_long)rep->first_lsn.offset,		    (u_long)rep->last_lsn.file, (u_long)rep->last_lsn.offset));		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);		if ((ret = __rep_log_setup(dbenv, rep)) != 0)			goto err;		(void)__rep_send_message(dbenv, eid,		    REP_LOG_REQ, &rep->first_lsn, &dbt, 0);		MUTEX_LOCK(dbenv, db_rep->rep_mutexp);		return (0);	}	/*	 * 4.  If not, set curinfo to next file and request its pages.	 */	rep->finfo = rep->nextinfo;	if ((ret = __rep_fileinfo_read(dbenv, rep->finfo, &rep->nextinfo,	    &rep->curinfo)) != 0)		goto err;	DB_ASSERT(rep->curinfo->pgno == 0);	rep->ready_pg = 0;	rep->npages = 0;	rep->waiting_pg = PGNO_INVALID;	rep->max_wait_pg = PGNO_INVALID;	memset(&dbt, 0, sizeof(dbt));	RPRINT(dbenv, rep, (dbenv, &mb,	    "FILEDONE: Next file %d.  Request pages 0 to %lu",	    rep->curinfo->filenum, (u_long)rep->curinfo->max_pgno));	dbt.data = rep->finfo;	dbt.size = (u_int32_t)((u_int8_t *)rep->nextinfo -	    (u_int8_t *)rep->finfo);	(void)__rep_send_message(dbenv, eid, REP_PAGE_REQ,	    NULL, &dbt, 0);err:	return (ret);}/* * __rep_mpf_open - *	Create and open the mpool file for a database. *	Used by both master and client to bring files into mpool. */static int__rep_mpf_open(dbenv, mpfp, rfp)	DB_ENV *dbenv;	DB_MPOOLFILE **mpfp;	__rep_fileinfo_args *rfp;{	DB db;	int ret;	if ((ret = __memp_fcreate(dbenv, mpfp)) != 0)		return (ret);	/*	 * We need a dbp to pass into to __db_dbenv_mpool.  Set up	 * only the parts that it needs.	 */	db.type = rfp->type;	db.pgsize = (u_int32_t)rfp->pgsize;	memcpy(db.fileid, rfp->uid.data, DB_FILE_ID_LEN);	db.flags = rfp->flags;	db.mpf = *mpfp;	db.dbenv = dbenv;	if ((ret = __db_dbenv_mpool(&db, rfp->info.data, 0)) != 0) {		(void)__memp_fclose(*mpfp, 0);		*mpfp = NULL;	}	return (ret);}/* * __rep_pggap_req - *	Request a page gap.  Assumes the caller holds the rep_mutexp. * * PUBLIC: int __rep_pggap_req __P((DB_ENV *, REP *, __rep_fileinfo_args *, * PUBLIC:    int)); */int__rep_pggap_req(dbenv, rep, reqfp, moregap)	DB_ENV *dbenv;	REP *rep;	__rep_fileinfo_args *reqfp;	int moregap;{	DBT max_pg_dbt;	__rep_fileinfo_args *tmpfp;	size_t len;	int alloc, ret;	ret = 0;	alloc = 0;	/*	 * There is a window where we have to set REP_RECOVER_PAGE when	 * we receive the update information to transition from getting	 * file information to getting page information.  However, that	 * thread does release and then reacquire mutexes.  So, we might	 * try re-requesting before the original thread can get curinfo	 * setup.  If curinfo isn't set up there is nothing to do.	 */	if (rep->curinfo == NULL)		return (0);	if (reqfp == NULL) {		if ((ret = __rep_finfo_alloc(dbenv, rep->curinfo, &tmpfp)) != 0)			return (ret);		alloc = 1;	} else		tmpfp = reqfp;	/*	 * If we've never requested this page, then	 * request everything between it and the first	 * page we have.  If we have requested this page	 * then only request this record, not the entire gap.	 */	memset(&max_pg_dbt, 0, sizeof(max_pg_dbt));	tmpfp->pgno = rep->ready_pg;	max_pg_dbt.data = rep->finfo;	max_pg_dbt.size = (u_int32_t)((u_int8_t *)rep->nextinfo -	    (u_int8_t *)rep->finfo);	if (rep->max_wait_pg == PGNO_INVALID || moregap) {		/*		 * Request the gap - set max to waiting_pg - 1 or if		 * there is no waiting_pg, just ask for one.		 */		if (rep->waiting_pg == PGNO_INVALID) {			if (moregap)				rep->max_wait_pg = rep->curinfo->max_pgno;			else				rep->max_wait_pg = rep->ready_pg;		} else			rep->max_wait_pg = rep->waiting_pg - 1;		tmpfp->max_pgno = rep->max_wait_pg;	} else {		/*		 * Request 1 page - set max to ready_pg.		 */		rep->max_wait_pg = rep->ready_pg;		tmpfp->max_pgno = rep->ready_pg;	}	if (rep->master_id != DB_EID_INVALID) {		rep->stat.st_pg_requested++;		/*		 * We need to request the pages, but we need to get the		 * new info into rep->finfo.  Assert that the sizes never		 * change.  The only thing this should do is change		 * the pgno field.  Everything else remains the same.		 */		ret = __rep_fileinfo_buf(rep->finfo, max_pg_dbt.size, &len,		    tmpfp->pgsize, tmpfp->pgno, tmpfp->max_pgno,		    tmpfp->filenum, tmpfp->id, tmpfp->type,		    tmpfp->flags, &tmpfp->uid, &tmpfp->info);		DB_ASSERT(len == max_pg_dbt.size);		(void)__rep_send_message(dbenv, rep->master_id,		    REP_PAGE_REQ, NULL, &max_pg_dbt, 0);	} else		(void)__rep_send_message(dbenv, DB_EID_BROADCAST,		    REP_MASTER_REQ, NULL, NULL, 0);	if (alloc)		__os_free(dbenv, tmpfp);	return (ret);}/* * __rep_loggap_req - *	Request a log gap.  Assumes the caller holds the db_mutexp. * * PUBLIC: void __rep_loggap_req __P((DB_ENV *, REP *, DB_LSN *, int)); */void__rep_loggap_req(dbenv, rep, lsnp, moregap)	DB_ENV *dbenv;	REP *rep;	DB_LSN *lsnp;	int moregap;{	DB_LOG *dblp;	DBT max_lsn_dbt, *max_lsn_dbtp;	DB_LSN next_lsn;	LOG *lp;	dblp = dbenv->lg_handle;	lp = dblp->reginfo.primary;	R_LOCK(dbenv, &dblp->reginfo);	next_lsn = lp->lsn;	R_UNLOCK(dbenv, &dblp->reginfo);	if (moregap ||	    (lsnp != NULL &&	    (log_compare(lsnp, &lp->max_wait_lsn) == 0 ||	    IS_ZERO_LSN(lp->max_wait_lsn)))) {		/*		 * We need to ask for the gap.  Either we never asked		 * for records before, or we asked for a single record		 * and received it.		 */		lp->max_wait_lsn = lp->waiting_lsn;		memset(&max_lsn_dbt, 0, sizeof(max_lsn_dbt));		max_lsn_dbt.data = &lp->waiting_lsn;		max_lsn_dbt.size = sizeof(lp->waiting_lsn);		max_lsn_dbtp = &max_lsn_dbt;	} else {		max_lsn_dbtp = NULL;		lp->max_wait_lsn = next_lsn;	}	if (rep->master_id != DB_EID_INVALID) {		rep->stat.st_log_requested++;		(void)__rep_send_message(dbenv, rep->master_id,		    REP_LOG_REQ, &next_lsn, max_lsn_dbtp, 0);	} else		(void)__rep_send_message(dbenv, DB_EID_BROADCAST,		    REP_MASTER_REQ, NULL, NULL, 0);	return;}/* * __rep_finfo_alloc - *	Allocate and initialize a fileinfo structure. * * PUBLIC: int __rep_finfo_alloc __P((DB_ENV *, __rep_fileinfo_args *, * PUBLIC:    __rep_fileinfo_args **)); */int__rep_finfo_alloc(dbenv, rfpsrc, rfpp)	DB_ENV *dbenv;	__rep_fileinfo_args *rfpsrc, **rfpp;{	size_t size;	int ret;	size = sizeof(__rep_fileinfo_args) + rfpsrc->uid.size +	    rfpsrc->info.size;	if ((ret = __os_malloc(dbenv, size, rfpp)) != 0)		return (ret);	memcpy(*rfpp, rfpsrc, size);	return (ret);}/* * __rep_log_setup - *	We know our first LSN and need to reset the log subsystem *	to get our logs set up for the proper file. */static int__rep_log_setup(dbenv, rep)	DB_ENV *dbenv;	REP *rep;{	DB_LOG *dblp;	DB_LSN lsn;	u_int32_t fnum;	int ret;	char *name;	dblp = dbenv->lg_handle;	/*	 * Set up the log starting at the file number of the first LSN we	 * need to get from the master.	 */	if ((ret = __log_newfile(dblp, &lsn, rep->first_lsn.file)) == 0) {		/*		 * We do know we want to start this client's log at		 * log file 'first_lsn.file'.  So we want to forcibly		 * remove any log files earlier than that number.		 * We don't know what might be in any earlier log files		 * so we cannot just use __log_autoremove.		 */		for (fnum = 1; fnum < rep->first_lsn.file; fnum++) {			if ((ret = __log_name(dblp, fnum, &name, NULL, 0)) != 0)				goto err;			(void)__os_unlink(dbenv, name);			__os_free(dbenv, name);		}	}err:	return (ret);}/* * __rep_queue_filedone - *	Determine if we're really done getting the pages for a queue file. *	Queue is handled in several steps. *	1.  First we get the meta page only. *	2.  We use the meta-page information to figure out first and last *	    page numbers (and if queue wraps, first can be > last. *	3.  If first < last, we do a REP_PAGE_REQ for all pages. *	4.  If first > last, we REP_PAGE_REQ from first -> max page number. *	    Then we'll ask for page 1 -> last. * * This function can return several things: *	DB_REP_PAGEDONE - if we're done with this file. *	0 - if we're not doen with this file. *	error - if we get an error doing some operations. * * This function will open a dbp handle to the queue file.  This is needed * by most of the QAM macros.  We'll open it on the first pass through * here and we'll close it whenever we decide we're done. */static int__rep_queue_filedone(dbenv, rep, rfp)	DB_ENV *dbenv;	REP *rep;	__rep_fileinfo_args *rfp;{#ifndef HAVE_QUEUE	COMPQUIET(rep, NULL);	COMPQUIET(rfp, NULL);	return (__db_no_queue_am(dbenv));#else	db_pgno_t first, last;	u_int32_t flags;	int empty, ret, t_ret;#ifdef DIAGNOSTIC	DB_MSGBUF mb;#endif	ret = 0;	if (rep->queue_dbp == NULL) {		/*		 * We need to do a sync here so that the open		 * can find the file and file id.		 */		if ((ret = __memp_sync(dbenv, NULL)) != 0)			goto out;		if ((ret = db_create(&rep->queue_dbp, dbenv,		    DB_REP_CREATE)) != 0)			goto out;		flags = DB_NO_AUTO_COMMIT |		    (F_ISSET(dbenv, DB_ENV_THREAD) ? DB_THREAD : 0);		if ((ret = __db_open(rep->queue_dbp, NULL, rfp->info.data,		    NULL, DB_QUEUE, flags, 0, PGNO_BASE_MD)) != 0)			goto out;	}	if ((ret = __queue_pageinfo(rep->queue_dbp,	    &first, &last, &empty, 0, 0)) != 0)		goto out;	RPRINT(dbenv, rep, (dbenv, &mb,	    "Queue fileinfo: first %lu, last %lu, empty %d",	    (u_long)first, (u_long)last, empty));	/*	 * We can be at the end of 3 possible states.	 * 1.  We have received the meta-page and now need to get the	 *     rest of the pages in the database.	 * 2.  We have received from first -> max_pgno.  We might be done,	 *     or we might need to ask for wrapped pages.	 * 3.  We have received all pages in the file.  We're done.	 */	if (rfp->max_pgno == 0) {		/*		 * We have just received the meta page.  Set up the next		 * pages to ask for and check if the file is empty.		 */		if (empty)			goto out;		if (first > last) {			rfp->max_pgno =			    QAM_RECNO_PAGE(rep->queue_dbp, UINT32_MAX);		} else			rfp->max_pgno = last;		RPRINT(dbenv, rep, (dbenv, &mb,		    "Queue fileinfo: First req: first %lu, last %lu",		    (u_long)first, (u_long)rfp->max_pgno));		goto req;	} else if (rfp->max_pgno != last) {		/*		 * If max_pgno != last that means we're dealing with a		 * wrapped situation.  Request next batch of pages.		 * Set npages to 1 because we already have page 0, the		 * meta-page, now we need pages 1-max_pgno.		 */		first = 1;		rfp->max_pgno = last;		RPRINT(dbenv, rep, (dbenv, &mb,		    "Queue fileinfo: Wrap req: first %lu, last %lu",		    (u_long)first, (u_long)last));req:		/*		 * Since we're simulating a "gap" to resend new PAGE_REQ		 * for this file, we need to set waiting page to last + 1		 * so that we'll ask for all from ready_pg -> last.		 */		rep->npages = first;		rep->ready_pg = first;		rep->waiting_pg = rfp->max_pgno + 1;		rep->max_wait_pg = PGNO_INVALID;		ret = __rep_pggap_req(dbenv, rep, rfp, 0);		return (ret);	}	/*	 * max_pgno == last	 * If we get here, we have all the pages we need.	 * Close the dbp and return.	 */out:	if (rep->queue_dbp != NULL &&	    (t_ret = __db_close(rep->queue_dbp, NULL, DB_NOSYNC)) != 0 &&	    ret == 0)		ret = t_ret;	rep->queue_dbp = NULL;	if (ret == 0)		ret = DB_REP_PAGEDONE;	return (ret);#endif}

⌨️ 快捷键说明

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