📄 rep_util.c
字号:
* __rep_elect_done * Clear all election information for this site. Assumes the * caller hold rep_mutex. * * PUBLIC: void __rep_elect_done __P((DB_ENV *, REP *)); */void__rep_elect_done(dbenv, rep) DB_ENV *dbenv; REP *rep;{ int inelect;#ifdef DIAGNOSTIC DB_MSGBUF mb;#else COMPQUIET(dbenv, NULL);#endif inelect = IN_ELECTION_TALLY(rep); F_CLR(rep, REP_F_EPHASE1 | REP_F_EPHASE2 | REP_F_TALLY); rep->sites = 0; rep->votes = 0; if (inelect) rep->egen++; RPRINT(dbenv, rep, (dbenv, &mb, "Election done; egen %lu", (u_long)rep->egen));}/* * __rep_grow_sites -- * Called to allocate more space in the election tally information. * Called with the rep mutex held. We need to call the region mutex, so * we need to make sure that we *never* acquire those mutexes in the * opposite order. * * PUBLIC: int __rep_grow_sites __P((DB_ENV *dbenv, int nsites)); */int__rep_grow_sites(dbenv, nsites) DB_ENV *dbenv; int nsites;{ REGENV *renv; REGINFO *infop; REP *rep; int nalloc, ret, *tally; rep = ((DB_REP *)dbenv->rep_handle)->region; /* * Allocate either twice the current allocation or nsites, * whichever is more. */ nalloc = 2 * rep->asites; if (nalloc < nsites) nalloc = nsites; infop = dbenv->reginfo; renv = infop->primary; MUTEX_LOCK(dbenv, &renv->mutex); /* * We allocate 2 tally regions, one for tallying VOTE1's and * one for VOTE2's. Always grow them in tandem, because if we * get more VOTE1's we'll always expect more VOTE2's then too. */ if ((ret = __db_shalloc(infop, (size_t)nalloc * sizeof(REP_VTALLY), sizeof(REP_VTALLY), &tally)) == 0) { if (rep->tally_off != INVALID_ROFF) __db_shalloc_free( infop, R_ADDR(infop, rep->tally_off)); rep->tally_off = R_OFFSET(infop, tally); if ((ret = __db_shalloc(infop, (size_t)nalloc * sizeof(REP_VTALLY), sizeof(REP_VTALLY), &tally)) == 0) { /* Success */ if (rep->v2tally_off != INVALID_ROFF) __db_shalloc_free(infop, R_ADDR(infop, rep->v2tally_off)); rep->v2tally_off = R_OFFSET(infop, tally); rep->asites = nalloc; rep->nsites = nsites; } else { /* * We were unable to allocate both. So, we must * free the first one and reinitialize. If * v2tally_off is valid, it is from an old * allocation and we are clearing it all out due * to the error. */ if (rep->v2tally_off != INVALID_ROFF) __db_shalloc_free(infop, R_ADDR(infop, rep->v2tally_off)); __db_shalloc_free(infop, R_ADDR(infop, rep->tally_off)); rep->v2tally_off = rep->tally_off = INVALID_ROFF; rep->asites = 0; rep->nsites = 0; } } MUTEX_UNLOCK(dbenv, &renv->mutex); return (ret);}/* * __env_rep_enter -- * * Check if we are in the middle of replication initialization and/or * recovery, and if so, disallow operations. If operations are allowed, * increment handle-counts, so that we do not start recovery while we * are operating in the library. * * PUBLIC: void __env_rep_enter __P((DB_ENV *)); */void__env_rep_enter(dbenv) DB_ENV *dbenv;{ DB_REP *db_rep; REP *rep; int cnt; /* Check if locks have been globally turned off. */ if (F_ISSET(dbenv, DB_ENV_NOLOCKING)) return; db_rep = dbenv->rep_handle; rep = db_rep->region; MUTEX_LOCK(dbenv, db_rep->rep_mutexp); for (cnt = 0; rep->in_recovery;) { MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp); __os_sleep(dbenv, 1, 0); MUTEX_LOCK(dbenv, db_rep->rep_mutexp); if (++cnt % 60 == 0) __db_err(dbenv, "DB_ENV handle waiting %d minutes for replication recovery to complete", cnt / 60); } rep->handle_cnt++; MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);}/* * __env_db_rep_exit -- * * Decrement handle count upon routine exit. * * PUBLIC: void __env_db_rep_exit __P((DB_ENV *)); */void__env_db_rep_exit(dbenv) DB_ENV *dbenv;{ DB_REP *db_rep; REP *rep; /* Check if locks have been globally turned off. */ if (F_ISSET(dbenv, DB_ENV_NOLOCKING)) return; db_rep = dbenv->rep_handle; rep = db_rep->region; MUTEX_LOCK(dbenv, db_rep->rep_mutexp); rep->handle_cnt--; MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);}/* * __db_rep_enter -- * Called in replicated environments to keep track of in-use handles * and prevent any concurrent operation during recovery. If checkgen is * non-zero, then we verify that the dbp has the same handle as the env. * If return_now is non-zero, we'll return DB_DEADLOCK immediately, else we'll * sleep before returning DB_DEADLOCK. * * PUBLIC: int __db_rep_enter __P((DB *, int, int, int)); */int__db_rep_enter(dbp, checkgen, checklock, return_now) DB *dbp; int checkgen, checklock, return_now;{ DB_ENV *dbenv; DB_REP *db_rep; REGENV *renv; REGINFO *infop; REP *rep; time_t timestamp; dbenv = dbp->dbenv; /* Check if locks have been globally turned off. */ if (F_ISSET(dbenv, DB_ENV_NOLOCKING)) return (0); db_rep = dbenv->rep_handle; rep = db_rep->region; infop = dbenv->reginfo; renv = infop->primary; if (checklock && F_ISSET(renv, DB_REGENV_REPLOCKED)) { (void)time(×tamp); TIMESTAMP_CHECK(dbenv, timestamp, renv); /* * Check if we're still locked out after checking * the timestamp. */ if (F_ISSET(renv, DB_REGENV_REPLOCKED)) return (EINVAL); } MUTEX_LOCK(dbenv, db_rep->rep_mutexp); if (F_ISSET(rep, REP_F_READY)) { MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp); if (!return_now) __os_sleep(dbenv, 5, 0); return (DB_LOCK_DEADLOCK); } if (checkgen && dbp->timestamp != renv->rep_timestamp) { MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp); __db_err(dbenv, "%s %s", "replication recovery unrolled committed transactions;", "open DB and DBcursor handles must be closed"); return (DB_REP_HANDLE_DEAD); } rep->handle_cnt++; MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp); return (0);}/* * __op_rep_enter -- * * Check if we are in the middle of replication initialization and/or * recovery, and if so, disallow new multi-step operations, such as * transaction and memp gets. If operations are allowed, * increment the op_cnt, so that we do not start recovery while we have * active operations. * * PUBLIC: void __op_rep_enter __P((DB_ENV *)); */void__op_rep_enter(dbenv) DB_ENV *dbenv;{ DB_REP *db_rep; REP *rep; int cnt; /* Check if locks have been globally turned off. */ if (F_ISSET(dbenv, DB_ENV_NOLOCKING)) return; db_rep = dbenv->rep_handle; rep = db_rep->region; MUTEX_LOCK(dbenv, db_rep->rep_mutexp); for (cnt = 0; F_ISSET(rep, REP_F_READY);) { MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp); __os_sleep(dbenv, 5, 0); MUTEX_LOCK(dbenv, db_rep->rep_mutexp); if (++cnt % 60 == 0) __db_err(dbenv, "__op_rep_enter waiting %d minutes for op count to drain", cnt / 60); } rep->op_cnt++; MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);}/* * __op_rep_exit -- * * Decrement op count upon transaction commit/abort/discard or * memp_fput. * * PUBLIC: void __op_rep_exit __P((DB_ENV *)); */void__op_rep_exit(dbenv) DB_ENV *dbenv;{ DB_REP *db_rep; REP *rep; /* Check if locks have been globally turned off. */ if (F_ISSET(dbenv, DB_ENV_NOLOCKING)) return; db_rep = dbenv->rep_handle; rep = db_rep->region; MUTEX_LOCK(dbenv, db_rep->rep_mutexp); DB_ASSERT(rep->op_cnt > 0); rep->op_cnt--; MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);}/* * __rep_get_gen -- * * Get the generation number from a replicated environment. * * PUBLIC: void __rep_get_gen __P((DB_ENV *, u_int32_t *)); */void__rep_get_gen(dbenv, genp) DB_ENV *dbenv; u_int32_t *genp;{ DB_REP *db_rep; REP *rep; db_rep = dbenv->rep_handle; rep = db_rep->region; MUTEX_LOCK(dbenv, db_rep->rep_mutexp); if (rep->recover_gen > rep->gen) *genp = rep->recover_gen; else *genp = rep->gen; MUTEX_UNLOCK(dbenv, db_rep->rep_mutexp);}#ifdef DIAGNOSTIC/* * PUBLIC: void __rep_print_message __P((DB_ENV *, int, REP_CONTROL *, char *)); */void__rep_print_message(dbenv, eid, rp, str) DB_ENV *dbenv; int eid; REP_CONTROL *rp; char *str;{ DB_MSGBUF mb; char *type; switch (rp->rectype) { case REP_ALIVE: type = "alive"; break; case REP_ALIVE_REQ: type = "alive_req"; break; case REP_ALL_REQ: type = "all_req"; break; case REP_DUPMASTER: type = "dupmaster"; break; case REP_FILE: type = "file"; break; case REP_FILE_FAIL: type = "file_fail"; break; case REP_FILE_REQ: type = "file_req"; break; case REP_LOG: type = "log"; break; case REP_LOG_MORE: type = "log_more"; break; case REP_LOG_REQ: type = "log_req"; break; case REP_MASTER_REQ: type = "master_req"; break; case REP_NEWCLIENT: type = "newclient"; break; case REP_NEWFILE: type = "newfile"; break; case REP_NEWMASTER: type = "newmaster"; break; case REP_NEWSITE: type = "newsite"; break; case REP_PAGE: type = "page"; break; case REP_PAGE_FAIL: type = "page_fail"; break; case REP_PAGE_MORE: type = "page_more"; break; case REP_PAGE_REQ: type = "page_req"; break; case REP_UPDATE: type = "update"; break; case REP_UPDATE_REQ: type = "update_req"; break; case REP_VERIFY: type = "verify"; break; case REP_VERIFY_FAIL: type = "verify_fail"; break; case REP_VERIFY_REQ: type = "verify_req"; break; case REP_VOTE1: type = "vote1"; break; case REP_VOTE2: type = "vote2"; break; default: type = "NOTYPE"; break; } RPRINT(dbenv, ((REP *)((DB_REP *)(dbenv)->rep_handle)->region), (dbenv, &mb, "%s %s: gen = %lu eid %d, type %s, LSN [%lu][%lu]", dbenv->db_home, str, (u_long)rp->gen, eid, type, (u_long)rp->lsn.file, (u_long)rp->lsn.offset));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -