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

📄 env_recover.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
			progress = 34 + (int)(33 * (__lsn_diff(&first_lsn,			    &last_lsn, &lsn, log_size, 0) / nfiles));			dbenv->db_feedback(dbenv, DB_RECOVER, progress);		}		if (max_lsn != NULL && (ret = __rep_lockpages(dbenv,		    dtab, dtabsize, &lsn, NULL, NULL, lockid)) != 0)			continue;		ret = __db_dispatch(dbenv, dbenv->recover_dtab,		    dbenv->recover_dtab_size, &data, &lsn,		    DB_TXN_BACKWARD_ROLL, txninfo);		if (ret != 0) {			if (ret != DB_TXN_CKP)				goto msgerr;			else				ret = 0;		}	}	if (ret != 0 && ret != DB_NOTFOUND)		goto err;	/*	 * Pass #3.  If we are recovering to a timestamp or to an LSN,	 * we need to make sure that we don't roll-forward beyond that	 * point because there may be non-transactional operations (e.g.,	 * closes that would fail).  The last_lsn variable is used for	 * feedback calculations, but use it to set an initial stopping	 * point for the forward pass, and then reset appropriately to	 * derive a real stop_lsn that tells how far the forward pass	 * should go.	 */	pass = "forward";	stop_lsn = last_lsn;	if (max_lsn != NULL || dbenv->tx_timestamp != 0)		stop_lsn = ((DB_TXNHEAD *)txninfo)->maxlsn;	for (ret = logc->get(logc, &lsn, &data, DB_NEXT);	    ret == 0; ret = logc->get(logc, &lsn, &data, DB_NEXT)) {		/*		 * If we are recovering to a timestamp or an LSN,		 * we need to make sure that we don't try to roll		 * forward beyond the soon-to-be end of log.		 */		if (log_compare(&lsn, &stop_lsn) > 0)			break;		if (dbenv->db_feedback != NULL) {			progress = 67 + (int)(33 * (__lsn_diff(&first_lsn,			    &last_lsn, &lsn, log_size, 1) / nfiles));			dbenv->db_feedback(dbenv, DB_RECOVER, progress);		}		ret = __db_dispatch(dbenv, dbenv->recover_dtab,		    dbenv->recover_dtab_size, &data, &lsn,		    DB_TXN_FORWARD_ROLL, txninfo);		if (ret != 0) {			if (ret != DB_TXN_CKP)				goto msgerr;			else				ret = 0;		}	}	if (ret != 0 && ret != DB_NOTFOUND)		goto err;	/*	 * Process any pages that were on the limbo list and move them to	 * the free list.  Do this before checkpointing the database.	 */	 if ((ret = __db_do_the_limbo(dbenv, NULL, NULL, txninfo)) != 0)		goto err;	if (max_lsn == NULL)		region->last_txnid = ((DB_TXNHEAD *)txninfo)->maxid;	/* Take a checkpoint here to force any dirty data pages to disk. */	if (dbenv->tx_timestamp != 0) {		region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn;		__log_vtruncate(dbenv, &((DB_TXNHEAD *)txninfo)->maxlsn,		    &((DB_TXNHEAD *)txninfo)->ckplsn);	}	if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, DB_FORCE)) != 0)		goto err;	/* Close all the db files that are open. */	if ((ret = __dbreg_close_files(dbenv)) != 0)		goto err;	if (max_lsn != NULL) {		region->last_ckp = ((DB_TXNHEAD *)txninfo)->ckplsn;		/* We are going to truncate, so we'd best close the cursor. */		if (logc != NULL && (ret = logc->close(logc, 0)) != 0)			goto err;		__log_vtruncate(dbenv,		    max_lsn, &((DB_TXNHEAD *)txninfo)->ckplsn);		/*		 * Now we need to open files that should be open in order for		 * client processing to continue.  However, since we've		 * truncated the log, we need to recompute from where the		 * openfiles pass should begin.		 */		if ((ret = dbenv->log_cursor(dbenv, &logc, 0)) != 0)			goto err;		if ((ret = logc->get(logc, &first_lsn, &data, DB_FIRST)) != 0) {			if (ret == DB_NOTFOUND)				ret = 0;			else				__db_err(dbenv, "First log record not found");			goto err;		}		if ((ret = __txn_getckp(dbenv, &first_lsn)) == 0 &&		    (ret = logc->get(logc, &first_lsn, &data, DB_SET)) == 0) {			/* We have a recent checkpoint.  This is LSN (1). */			if ((ret = __txn_ckp_read(dbenv,			    data.data, &ckp_args)) != 0) {				__db_err(dbenv,			    "Invalid checkpoint record at [%ld][%ld]",				    (u_long)first_lsn.file,				    (u_long)first_lsn.offset);				goto err;			}			first_lsn = ckp_args->ckp_lsn;		}		if ((ret = logc->get(logc, &first_lsn, &data, DB_SET)) != 0)			goto err;		if ((ret = __env_openfiles(dbenv, logc,		    txninfo, &data, &first_lsn, NULL, nfiles, 1)) != 0)			goto err;	} else if (region->stat.st_nrestores == 0)		/*		 * If there are no prepared transactions that need resolution,		 * we need to reset the transaction ID space and log this fact.		 */		if ((ret = __txn_reset(dbenv)) != 0)			goto err;	if (FLD_ISSET(dbenv->verbose, DB_VERB_RECOVERY)) {		(void)time(&now);		__db_err(dbenv, "Recovery complete at %.24s", ctime(&now));		__db_err(dbenv, "%s %lx %s [%lu][%lu]",		    "Maximum transaction ID",		    ((DB_TXNHEAD *)txninfo)->maxid,		    "Recovery checkpoint",		    (u_long)region->last_ckp.file,		    (u_long)region->last_ckp.offset);	}	if (0) {msgerr:		__db_err(dbenv,		    "Recovery function for LSN %lu %lu failed on %s pass",		    (u_long)lsn.file, (u_long)lsn.offset, pass);	}done:err:	if (lockid != DB_LOCK_INVALIDID) {		if ((t_ret = __rep_unlockpages(dbenv, lockid)) != 0 && ret == 0)			ret = t_ret;		if ((t_ret =		    dbenv->lock_id_free(dbenv, lockid)) != 0 && ret == 0)			ret = t_ret;	}	if (logc != NULL && (t_ret = logc->close(logc, 0)) != 0 && ret == 0)		ret = t_ret;	if (txninfo != NULL)		__db_txnlist_end(dbenv, txninfo);	if (dtab != NULL)		__os_free(dbenv, dtab);	if (ckp_args != NULL)		__os_free(dbenv, ckp_args);	dbenv->tx_timestamp = 0;	/* Restore the state of the thread flag, clear in-recovery flags. */	if (is_thread)		F_SET(dbenv, DB_ENV_THREAD);	F_CLR((DB_LOG *)dbenv->lg_handle, DBLOG_RECOVER);	F_CLR(region, TXN_IN_RECOVERY);	return (ret);}/* * Figure out how many logfiles we have processed.  If we are moving * forward (is_forward != 0), then we're computing current - low.  If * we are moving backward, we are computing high - current.  max is * the number of bytes per logfile. */static double__lsn_diff(low, high, current, max, is_forward)	DB_LSN *low, *high, *current;	u_int32_t max;	int is_forward;{	double nf;	/*	 * There are three cases in each direction.  If you are in the	 * same file, then all you need worry about is the difference in	 * offsets.  If you are in different files, then either your offsets	 * put you either more or less than the integral difference in the	 * number of files -- we need to handle both of these.	 */	if (is_forward) {		if (current->file == low->file)			nf = (double)(current->offset - low->offset) / max;		else if (current->offset < low->offset)			nf = (double)(current->file - low->file - 1) +			    (double)(max - low->offset + current->offset) / max;		else			nf = (double)(current->file - low->file) +			    (double)(current->offset - low->offset) / max;	} else {		if (current->file == high->file)			nf = (double)(high->offset - current->offset) / max;		else if (current->offset > high->offset)			nf = (double)(high->file - current->file - 1) +			    (double)			    (max - current->offset + high->offset) / max;		else			nf = (double)(high->file - current->file) +			    (double)(high->offset - current->offset) / max;	}	return (nf);}/* * __log_backup -- * * This is used to find the earliest log record to process when a client * is trying to sync up with a master whose max LSN is less than this * client's max lsn; we want to roll back everything after that * * Find the latest checkpoint whose ckp_lsn is less than the max lsn. */static int__log_backup(dbenv, logc, max_lsn, start_lsn)	DB_ENV *dbenv;	DB_LOGC *logc;	DB_LSN *max_lsn, *start_lsn;{	DB_LSN lsn;	DBT data;	__txn_ckp_args *ckp_args;	int ret;	memset(&data, 0, sizeof(data));	ckp_args = NULL;	/*	 * Follow checkpoints through the log until we find one with	 * a ckp_lsn less than max_lsn.	 */	if ((ret = __txn_getckp(dbenv, &lsn)) != 0)		goto err;	while ((ret = logc->get(logc, &lsn, &data, DB_SET)) == 0) {		if ((ret = __txn_ckp_read(dbenv, data.data, &ckp_args)) != 0)			return (ret);		if (log_compare(&ckp_args->ckp_lsn, max_lsn) <= 0) {			*start_lsn = ckp_args->ckp_lsn;			break;		}		lsn = ckp_args->prev_lsn;		if (IS_ZERO_LSN(lsn))			break;		__os_free(dbenv, ckp_args);	}	if (ckp_args != NULL)		__os_free(dbenv, ckp_args);err:	if (IS_ZERO_LSN(*start_lsn) && (ret == 0 || ret == DB_NOTFOUND))		ret = logc->get(logc, start_lsn, &data, DB_FIRST);	return (ret);}/* * __log_earliest -- * * Return the earliest recovery point for the log files present.  The * earliest recovery time is the time stamp of the first checkpoint record * whose checkpoint LSN is greater than the first LSN we process. */static int__log_earliest(dbenv, logc, lowtime, lowlsn)	DB_ENV *dbenv;	DB_LOGC *logc;	int32_t *lowtime;	DB_LSN *lowlsn;{	DB_LSN first_lsn, lsn;	DBT data;	__txn_ckp_args *ckpargs;	u_int32_t rectype;	int cmp, ret;	memset(&data, 0, sizeof(data));	/*	 * Read forward through the log looking for the first checkpoint	 * record whose ckp_lsn is greater than first_lsn.	 */	for (ret = logc->get(logc, &first_lsn, &data, DB_FIRST);	    ret == 0; ret = logc->get(logc, &lsn, &data, DB_NEXT)) {		memcpy(&rectype, data.data, sizeof(rectype));		if (rectype != DB___txn_ckp)			continue;		if ((ret = __txn_ckp_read(dbenv, data.data, &ckpargs)) == 0) {			cmp = log_compare(&ckpargs->ckp_lsn, &first_lsn);			*lowlsn = ckpargs->ckp_lsn;			*lowtime = ckpargs->timestamp;			__os_free(dbenv, ckpargs);			if (cmp >= 0)				break;		}	}	return (ret);}/* * __env_openfiles -- * Perform the pass of recovery that opens files.  This is used * both during regular recovery and an initial call to txn_recover (since * we need files open in order to abort prepared, but not yet committed * transactions). * * See the comments in db_apprec for a detailed description of the * various recovery passes. * * If we are not doing feedback processing (i.e., we are doing txn_recover * processing and in_recovery is zero), then last_lsn can be NULL. * * PUBLIC: int __env_openfiles __P((DB_ENV *, DB_LOGC *, * PUBLIC:     void *, DBT *, DB_LSN *, DB_LSN *, double, int)); */int__env_openfiles(dbenv, logc, txninfo,    data, open_lsn, last_lsn, nfiles, in_recovery)	DB_ENV *dbenv;	DB_LOGC *logc;	void *txninfo;	DBT *data;	DB_LSN *open_lsn, *last_lsn;	int in_recovery;	double nfiles;{	DB_LSN lsn;	u_int32_t log_size;	int progress, ret;	/*	 * XXX	 * Get the log size.  No locking required because we're single-threaded	 * during recovery.	 */	log_size =	   ((LOG *)(((DB_LOG *)dbenv->lg_handle)->reginfo.primary))->log_size;	lsn = *open_lsn;	for (;;) {		if (in_recovery && dbenv->db_feedback != NULL) {			DB_ASSERT(last_lsn != NULL);			progress = (int)(33 * (__lsn_diff(open_lsn,			   last_lsn, &lsn, log_size, 1) / nfiles));			dbenv->db_feedback(dbenv, DB_RECOVER, progress);		}		ret = __db_dispatch(dbenv,		    dbenv->recover_dtab, dbenv->recover_dtab_size, data, &lsn,		    in_recovery ? DB_TXN_OPENFILES : DB_TXN_POPENFILES,		    txninfo);		if (ret != 0 && ret != DB_TXN_CKP) {			__db_err(dbenv,			    "Recovery function for LSN %lu %lu failed",			    (u_long)lsn.file, (u_long)lsn.offset);			break;		}		if ((ret = logc->get(logc, &lsn, data, DB_NEXT)) != 0) {			if (ret == DB_NOTFOUND)				ret = 0;			break;		}	}	return (ret);}

⌨️ 快捷键说明

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