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

📄 rep_backup.c

📁 这是国外的resip协议栈
💻 C
📖 第 1 页 / 共 4 页
字号:
		rep->stat.st_pg_duplicated++;		ret = 0;		goto err_nolock;	}	if (ret != 0)		goto err_nolock;	RPRINT(dbenv, rep, (dbenv, &mb,	    "PAGE: Write page %lu into mpool", (u_long)msgfp->pgno));	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);	/*	 * We put the page in the database file itself.	 */	ret = __rep_write_page(dbenv, rep, msgfp);	if (ret != 0) {		/*		 * We got an error storing the page, therefore, we need		 * remove this page marker from the page database too.		 * !!!		 * I'm ignoring errors from the delete because we want to		 * return the original error.  If we cannot write the page		 * and we cannot delete the item we just put, what should		 * we do?  Panic the env and return DB_RUNRECOVERY?		 */		(void)__db_del(rep->file_dbp, NULL, &key, 0);		goto err;	}	rep->stat.st_pg_records++;	rep->npages++;	/*	 * Now check the LSN on the page and save it if it is later	 * than the one we have.	 */	if (log_compare(&rp->lsn, &rep->last_lsn) > 0)		rep->last_lsn = rp->lsn;	/*	 * We've successfully written the page.  Now we need to see if	 * we're done with this file.  __rep_filedone will check if we	 * have all the pages expected and if so, set up for the next	 * file and send out a page request for the next file's pages.	 */	ret = __rep_filedone(dbenv, eid, rep, msgfp, rp->rectype);err:	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);err_nolock:	__os_free(dbenv, msgfp);	return (ret);}/* * __rep_page_fail *	Process a page fail message. * * PUBLIC: int __rep_page_fail __P((DB_ENV *, int, DBT *)); */int__rep_page_fail(dbenv, eid, rec)	DB_ENV *dbenv;	int eid;	DBT *rec;{	DB_REP *db_rep;	REP *rep;	__rep_fileinfo_args *msgfp, *rfp;	int ret;	void *next;#ifdef DIAGNOSTIC	DB_MSGBUF mb;#endif	ret = 0;	db_rep = dbenv->rep_handle;	rep = db_rep->region;	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);	if (!F_ISSET(rep, REP_F_RECOVER_PAGE)) {		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);		return (0);	}	if ((ret = __rep_fileinfo_read(dbenv, rec->data, &next, &msgfp)) != 0) {		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);		return (ret);	}	/*	 * Check if this page is from the file we're expecting.	 * This may be an old or delayed page message.	 */	/*	 * !!!	 * If we allow dbrename/dbremove on the master while a client	 * is updating, then we'd have to verify the file's uid here too.	 */	if (msgfp->filenum != rep->curfile) {		RPRINT(dbenv, rep, (dbenv, &mb, "Msg file %d != curfile %d",		    msgfp->filenum, rep->curfile));		MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);		return (0);	}	rfp = rep->curinfo;	if (rfp->type != DB_QUEUE)		--rfp->max_pgno;	else {		/*		 * Queue is special.  Pages at the beginning of the queue		 * may disappear, as well as at the end.  Use msgfp->pgno		 * to adjust accordingly.		 */		RPRINT(dbenv, rep, (dbenv, &mb,	    "page_fail: BEFORE page %lu failed. ready %lu, max %lu, npages %d",		    (u_long)msgfp->pgno, (u_long)rep->ready_pg,		    (u_long)rfp->max_pgno, rep->npages));		if (msgfp->pgno == rfp->max_pgno)			--rfp->max_pgno;		if (msgfp->pgno >= rep->ready_pg) {			rep->ready_pg = msgfp->pgno + 1;			rep->npages = rep->ready_pg;		}		RPRINT(dbenv, rep, (dbenv, &mb,	    "page_fail: AFTER page %lu failed. ready %lu, max %lu, npages %d",		    (u_long)msgfp->pgno, (u_long)rep->ready_pg,		    (u_long)rfp->max_pgno, rep->npages));	}	/*	 * We've lowered the number of pages expected.  It is possible that	 * this was the last page we were expecting.  Now we need to see if	 * we're done with this file.  __rep_filedone will check if we have	 * all the pages expected and if so, set up for the next file and	 * send out a page request for the next file's pages.	 */	ret = __rep_filedone(dbenv, eid, rep, msgfp, REP_PAGE_FAIL);	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);	return (ret);}/* * __rep_write_page - *	Write this page into a database. */static int__rep_write_page(dbenv, rep, msgfp)	DB_ENV *dbenv;	REP *rep;	__rep_fileinfo_args *msgfp;{	__rep_fileinfo_args *rfp;	DB_FH *rfh;	int ret;	void *dst;	char *real_name;	real_name = NULL;	/*	 * If this is the first page we're putting in this database, we need	 * to create the mpool file.  Otherwise call memp_fget to create the	 * page in mpool.  Then copy the data to the page, and memp_fput the	 * page to give it back to mpool.	 *	 * We need to create the file, removing any existing file and associate	 * the correct file ID with the new one.	 */	if (rep->file_mpf == NULL) {		rfp = rep->curinfo;		if (!F_ISSET(rfp, DB_AM_INMEM)) {			if ((ret = __db_appname(dbenv, DB_APP_DATA,			    rfp->info.data, 0, NULL, &real_name)) != 0)				goto err;			/*			 * Calling memp_nameop will both purge any matching			 * fileid from mpool and unlink it on disk.			 */			if ((ret = __memp_nameop(dbenv,			    rfp->uid.data, NULL, real_name, NULL)) != 0)				goto err;			/*			 * Create the file on disk.  We'll be putting the data			 * into the file via mpool.			 */			if ((ret = __os_open(dbenv, real_name,			    DB_OSO_CREATE, dbenv->db_mode, &rfh)) == 0)				ret = __os_closehandle(dbenv, rfh);			if (ret != 0)				goto err;		}		if ((ret =		    __rep_mpf_open(dbenv, &rep->file_mpf, rep->curinfo)) != 0)			goto err;	}	/*	 * Handle queue specially.  If we're a QUEUE database, we need to	 * use the __qam_fget/put calls.  We need to use rep->queue_dbp for	 * that.  That dbp is opened after getting the metapage for the	 * queue database.  Since the meta-page is always in the queue file,	 * we'll use the normal path for that first page.  After that we	 * can assume the dbp is opened.	 */	if (msgfp->type == DB_QUEUE && msgfp->pgno != 0) {#ifdef HAVE_QUEUE		if ((ret = __qam_fget(		    rep->queue_dbp, &msgfp->pgno, DB_MPOOL_CREATE, &dst)) != 0)#else		if ((ret = __db_no_queue_am(dbenv)) != 0)#endif			goto err;	} else if ((ret = __memp_fget(		    rep->file_mpf, &msgfp->pgno, DB_MPOOL_CREATE, &dst)) != 0)			goto err;	memcpy(dst, msgfp->info.data, msgfp->pgsize);	if (msgfp->type != DB_QUEUE || msgfp->pgno == 0)		ret = __memp_fput(rep->file_mpf, dst, DB_MPOOL_DIRTY);#ifdef HAVE_QUEUE	else		ret = __qam_fput(rep->queue_dbp, msgfp->pgno, dst,		    DB_MPOOL_DIRTY);#endiferr:	if (real_name != NULL)		 __os_free(dbenv, real_name);	return (ret);}/* * __rep_page_gap - *	After we've put the page into the database, we need to check if *	we have a page gap and whether we need to request pages. */static int__rep_page_gap(dbenv, rep, msgfp, type)	DB_ENV *dbenv;	REP *rep;	__rep_fileinfo_args *msgfp;	u_int32_t type;{	DB_LOG *dblp;	DB_REP *db_rep;	DBT data, key;	LOG *lp;	__rep_fileinfo_args *rfp;	db_recno_t recno;	int ret;#ifdef DIAGNOSTIC	DB_MSGBUF mb;#endif	db_rep = dbenv->rep_handle;	ret = 0;	dblp = dbenv->lg_handle;	lp = dblp->reginfo.primary;	/*	 * We've successfully put this page into our file.	 * Now we need to account for it and re-request new pages	 * if necessary.	 */	/*	 * We already hold the rep mutex, but we also need the db mutex.	 * So we need to drop it, acquire both in the right order and	 * then recheck the state of the world.	 */	MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);	MUTEX_LOCK(dbenv, db_rep->db_mutexp);	MUTEX_LOCK(dbenv, db_rep->rep_mutexp);	rfp = rep->curinfo;	/*	 * Make sure we're still talking about the same file.	 * If not, we're done here.	 */	if (rfp->filenum != msgfp->filenum) {		ret = DB_REP_PAGEDONE;		goto err;	}	/*	 * We have 3 possible states:	 * 1.  We receive a page we already have.	 *	msg pgno < ready pgno	 * 2.  We receive a page that is beyond a gap.	 *	msg pgno > ready pgno	 * 3.  We receive the page we're expecting.	 *	msg pgno == ready pgno	 */	/*	 * State 1.  This should not happen because this function	 * should only be called once per page received because we	 * check for DB_KEY_EXIST when we save the page information.	 */	DB_ASSERT(msgfp->pgno >= rep->ready_pg);	/*	 * State 2.  This page is beyond the page we're expecting.	 * We need to update waiting_pg if this page is less than	 * (earlier) the current waiting_pg.  There is nothing	 * to do but see if we need to request.	 */	RPRINT(dbenv, rep, (dbenv, &mb,    "PAGE_GAP: pgno %lu, max_pg %lu ready %lu, waiting %lu max_wait %lu",	    (u_long)msgfp->pgno, (u_long)rfp->max_pgno, (u_long)rep->ready_pg,	    (u_long)rep->waiting_pg, (u_long)rep->max_wait_pg));	if (msgfp->pgno > rep->ready_pg) {		if (rep->waiting_pg == PGNO_INVALID ||		    msgfp->pgno < rep->waiting_pg)			rep->waiting_pg = msgfp->pgno;	} else {		/*		 * We received the page we're expecting.		 */		rep->ready_pg++;		lp->rcvd_recs = 0;		while (ret == 0 && rep->ready_pg == rep->waiting_pg) {			/*			 * If we get here we know we just filled a gap.			 */			lp->wait_recs = 0;			lp->rcvd_recs = 0;			rep->max_wait_pg = PGNO_INVALID;			/*			 * We need to walk the recno database looking for the			 * next page we need or expect.			 */			memset(&key, 0, sizeof(key));			memset(&data, 0, sizeof(data));			recno = (db_recno_t)rep->ready_pg;			key.data = &recno;			key.ulen = key.size = sizeof(db_recno_t);			key.flags = DB_DBT_USERMEM;			ret = __db_get(rep->file_dbp, NULL, &key, &data, 0);			if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY)				break;			else if (ret != 0)				goto err;			rep->ready_pg++;		}	}	/*	 * If we filled a gap and now have the entire file, there's	 * nothing to do.  We're done when ready_pg is > max_pgno	 * because ready_pg is larger than the last page we received.	 */	if (rep->ready_pg > rfp->max_pgno)		goto err;	/*	 * Check if we need to ask for more pages.	 */	if ((rep->waiting_pg != PGNO_INVALID &&	    rep->ready_pg != rep->waiting_pg) || type == REP_PAGE_MORE) {		/*		 * We got a page but we may still be waiting for more.		 */		if (lp->wait_recs == 0) {			/*			 * This is a new gap. Initialize the number of			 * records that we should wait before requesting			 * that it be resent.  We grab the limits out of			 * the rep without the mutex.			 */			lp->wait_recs = rep->request_gap;			lp->rcvd_recs = 0;			rep->max_wait_pg = PGNO_INVALID;		}		/*		 * If we got REP_PAGE_MORE we always want to ask for more.		 */		if ((__rep_check_doreq(dbenv, rep) || type == REP_PAGE_MORE) &&		    ((ret = __rep_pggap_req(dbenv, rep, rfp,		    type == REP_PAGE_MORE)) != 0))			goto err;	} else {		lp->wait_recs = 0;		rep->max_wait_pg = PGNO_INVALID;	}err:	MUTEX_UNLOCK(dbenv, db_rep->db_mutexp);	return (ret);}/* * __rep_filedone - *	We need to check if we're done with the current file after *	processing the current page.  Stat the database to see if *	we have all the pages.  If so, we need to clean up/close *	this one, set up for the next one, and ask for its pages, *	or if this is the last file, request the log records and *	move to the REP_RECOVER_LOG state. */static int__rep_filedone(dbenv, eid, rep, msgfp, type)	DB_ENV *dbenv;	int eid;	REP *rep;	__rep_fileinfo_args *msgfp;	u_int32_t type;{	DBT dbt;	DB_REP *db_rep;	__rep_fileinfo_args *rfp;	int ret;#ifdef DIAGNOSTIC	DB_MSGBUF mb;#endif	db_rep = dbenv->rep_handle;	/*	 * We've put our page, now we need to do any gap processing	 * that might be needed to re-request pages.	 */	ret = __rep_page_gap(dbenv, rep, msgfp, type);	/*	 * The world changed while we were doing gap processing.	 * We're done here.	 */	if (ret == DB_REP_PAGEDONE)		return (0);	rfp = rep->curinfo;	/*	 * max_pgno is 0-based and npages is 1-based, so we don't have	 * all the pages until npages is > max_pgno.	 */	RPRINT(dbenv, rep, (dbenv, &mb, "FILEDONE: have %lu pages. Need %lu.",	    (u_long)rep->npages, (u_long)rfp->max_pgno + 1));	if (rep->npages <= rfp->max_pgno)		return (0);	/*	 * If we're queue and we think we have all the pages for this file,	 * we need to do special queue processing.  Queue is handled in	 * several stages.	 */	if (rfp->type == DB_QUEUE &&	    ((ret = __rep_queue_filedone(dbenv, rep, rfp)) !=	    DB_REP_PAGEDONE))		return (ret);	/*	 * We have all the pages for this file.  We need to:	 * 1.  Close up the file data pointer we used.	 * 2.  Close/reset the page database.	 * 3.  Check if we have all file data.  If so, request logs.	 * 4.  If not, set curfile to next file and request its pages.	 */	/*	 * 1.  Close up the file data pointer we used.

⌨️ 快捷键说明

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