📄 rep_util.c
字号:
cur_fid = DB_LOGFILEID_INVALID; cur_pgno = PGNO_INVALID; unique = 0; for (i = 0; i < t->npages; i++) { if (F_ISSET(&t->array[i], LSN_PAGE_NOLOCK)) continue; if (t->array[i].pgdesc.pgno != cur_pgno || t->array[i].fid != cur_fid) { cur_pgno = t->array[i].pgdesc.pgno; cur_fid = t->array[i].fid; unique++; } } if (unique == 0) goto out; /* Handle single lock case specially, else allocate space for locks. */ if (unique == 1) { memset(&lo, 0, sizeof(lo)); lo.data = &t->array[0].pgdesc; lo.size = sizeof(t->array[0].pgdesc); ret = dbenv->lock_get(dbenv, lid, 0, &lo, DB_LOCK_WRITE, &l); goto out2; } /* Multi-lock case. */ locks.n = unique; if ((ret = __os_calloc(dbenv, unique, sizeof(DB_LOCKREQ), &locks.reqs)) != 0) goto err; if ((ret = __os_calloc(dbenv, unique, sizeof(DBT), &locks.objs)) != 0) goto err; unique = 0; cur_fid = DB_LOGFILEID_INVALID; cur_pgno = PGNO_INVALID; for (i = 0; i < t->npages; i++) { if (F_ISSET(&t->array[i], LSN_PAGE_NOLOCK)) continue; if (t->array[i].pgdesc.pgno != cur_pgno || t->array[i].fid != cur_fid) { cur_pgno = t->array[i].pgdesc.pgno; cur_fid = t->array[i].fid; locks.reqs[unique].op = DB_LOCK_GET; locks.reqs[unique].mode = DB_LOCK_WRITE; locks.reqs[unique].obj = &locks.objs[unique]; locks.objs[unique].data = &t->array[i].pgdesc; locks.objs[unique].size = sizeof(t->array[i].pgdesc); unique++; } } /* Finally, get the locks. */ if ((ret = dbenv->lock_vec(dbenv, lid, 0, locks.reqs, unique, &lvp)) != 0) { /* * If we were unsuccessful, unlock any locks we acquired before * the error and return the original error value. */ (void)__rep_unlockpages(dbenv, lid); }err:out: if (locks.objs != NULL) __os_free(dbenv, locks.objs); if (locks.reqs != NULL) __os_free(dbenv, locks.reqs); /* * Before we return, sort by LSN so that we apply records in the * right order. */ qsort(t->array, t->npages, sizeof(LSN_PAGE), __rep_cmp_bylsn);out2: if ((ret != 0 || recs == NULL) && t->nalloc != 0) { __os_free(dbenv, t->array); t->array = NULL; t->npages = t->nalloc = 0; } if (F_ISSET(&data_dbt, DB_DBT_REALLOC) && data_dbt.data != NULL) __os_ufree(dbenv, data_dbt.data); return (ret);}/* * __rep_cmp_bypage and __rep_cmp_bylsn -- * Sort functions for qsort. "bypage" sorts first by page numbers and * then by the LSN. "bylsn" sorts first by the LSN, then by page numbers. */static int__rep_cmp_bypage(a, b) const void *a, *b;{ LSN_PAGE *ap, *bp; ap = (LSN_PAGE *)a; bp = (LSN_PAGE *)b; if (ap->fid < bp->fid) return (-1); if (ap->fid > bp->fid) return (1); if (ap->pgdesc.pgno < bp->pgdesc.pgno) return (-1); if (ap->pgdesc.pgno > bp->pgdesc.pgno) return (1); if (ap->lsn.file < bp->lsn.file) return (-1); if (ap->lsn.file > bp->lsn.file) return (1); if (ap->lsn.offset < bp->lsn.offset) return (-1); if (ap->lsn.offset > bp->lsn.offset) return (1); return (0);}static int__rep_cmp_bylsn(a, b) const void *a, *b;{ LSN_PAGE *ap, *bp; ap = (LSN_PAGE *)a; bp = (LSN_PAGE *)b; if (ap->lsn.file < bp->lsn.file) return (-1); if (ap->lsn.file > bp->lsn.file) return (1); if (ap->lsn.offset < bp->lsn.offset) return (-1); if (ap->lsn.offset > bp->lsn.offset) return (1); if (ap->fid < bp->fid) return (-1); if (ap->fid > bp->fid) return (1); if (ap->pgdesc.pgno < bp->pgdesc.pgno) return (-1); if (ap->pgdesc.pgno > bp->pgdesc.pgno) return (1); return (0);}/* * __rep_is_client * Used by other subsystems to figure out if this is a replication * client sites. * * PUBLIC: int __rep_is_client __P((DB_ENV *)); */int__rep_is_client(dbenv) DB_ENV *dbenv;{ DB_REP *db_rep; REP *rep; int ret; if ((db_rep = dbenv->rep_handle) == NULL) return (0); rep = db_rep->region; MUTEX_LOCK(dbenv, db_rep->mutexp); ret = F_ISSET(rep, REP_F_UPGRADE | REP_F_LOGSONLY); MUTEX_UNLOCK(dbenv, db_rep->mutexp); return (ret);}/* * __rep_send_vote * Send this site's vote for the election. * * PUBLIC: int __rep_send_vote __P((DB_ENV *, DB_LSN *, int, int, int)); */int__rep_send_vote(dbenv, lsnp, nsites, pri, tiebreaker) DB_ENV *dbenv; DB_LSN *lsnp; int nsites, pri, tiebreaker;{ DBT vote_dbt; REP_VOTE_INFO vi; memset(&vi, 0, sizeof(vi)); vi.priority = pri; vi.nsites = nsites; vi.tiebreaker = tiebreaker; memset(&vote_dbt, 0, sizeof(vote_dbt)); vote_dbt.data = &vi; vote_dbt.size = sizeof(vi); return (__rep_send_message(dbenv, DB_EID_BROADCAST, REP_VOTE1, lsnp, &vote_dbt, 0));}/* * __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); if ((ret = __db_shalloc(infop->addr, sizeof(nalloc * sizeof(int)), sizeof(int), &tally)) == 0) { if (rep->tally_off != INVALID_ROFF) __db_shalloc_free(infop->addr, R_ADDR(infop, rep->tally_off)); rep->asites = nalloc; rep->nsites = nsites; rep->tally_off = R_OFFSET(infop, tally); } MUTEX_UNLOCK(dbenv, &renv->mutex); return (ret);}#ifdef NOTYETstatic int __rep_send_file __P((DB_ENV *, DBT *, u_int32_t));/* * __rep_send_file -- * Send an entire file, one block at a time. */static int__rep_send_file(dbenv, rec, eid) DB_ENV *dbenv; DBT *rec; u_int32_t eid;{ DB *dbp; DB_LOCK lk; DB_MPOOLFILE *mpf; DBC *dbc; DBT rec_dbt; PAGE *pagep; db_pgno_t last_pgno, pgno; int ret, t_ret; dbp = NULL; dbc = NULL; pagep = NULL; mpf = NULL; LOCK_INIT(lk); if ((ret = db_create(&dbp, dbenv, 0)) != 0) goto err; if ((ret = dbp->open(dbp, rec->data, NULL, DB_UNKNOWN, 0, 0)) != 0) goto err; if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) goto err; /* * Force last_pgno to some value that will let us read the meta-dat * page in the following loop. */ memset(&rec_dbt, 0, sizeof(rec_dbt)); last_pgno = 1; for (pgno = 0; pgno <= last_pgno; pgno++) { if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &lk)) != 0) goto err; if ((ret = mpf->get(mpf, &pgno, 0, &pagep)) != 0) goto err; if (pgno == 0) last_pgno = ((DBMETA *)pagep)->last_pgno; rec_dbt.data = pagep; rec_dbt.size = dbp->pgsize; if ((ret = __rep_send_message(dbenv, eid, REP_FILE, NULL, &rec_dbt, pgno == last_pgno)) != 0) goto err; ret = mpf->put(mpf, pagep, 0); pagep = NULL; if (ret != 0) goto err; ret = __LPUT(dbc, lk); LOCK_INIT(lk); if (ret != 0) goto err; }err: if (LOCK_ISSET(lk) && (t_ret = __LPUT(dbc, lk)) != 0 && ret == 0) ret = t_ret; if (dbc != NULL && (t_ret = dbc->c_close(dbc)) != 0 && ret == 0) ret = t_ret; if (pagep != NULL && (t_ret = mpf->put(mpf, pagep, 0)) != 0 && ret == 0) ret = t_ret; if (dbp != NULL && (t_ret = dbp->close(dbp, 0)) != 0 && ret == 0) ret = t_ret; return (ret);}#endif#if 0/* * 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;{ 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_ELECT: type = "elect"; break; case REP_FILE: type = "file"; 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_REQ: type = "page_req"; break; case REP_PLIST: type = "plist"; break; case REP_PLIST_REQ: type = "plist_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; } printf("%s %s: gen = %d eid %d, type %s, LSN [%u][%u]\n", dbenv->db_home, str, rp->gen, eid, type, rp->lsn.file, rp->lsn.offset);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -