本文整理汇总了C++中F_ISSET函数的典型用法代码示例。如果您正苦于以下问题:C++ F_ISSET函数的具体用法?C++ F_ISSET怎么用?C++ F_ISSET使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了F_ISSET函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: __wt_btcur_insert
/*
* __wt_btcur_insert --
* Insert a record into the tree.
*/
int
__wt_btcur_insert(WT_CURSOR_BTREE *cbt)
{
WT_BTREE *btree;
WT_CURSOR *cursor;
WT_DECL_RET;
WT_SESSION_IMPL *session;
btree = cbt->btree;
cursor = &cbt->iface;
session = (WT_SESSION_IMPL *)cursor->session;
WT_STAT_CONN_INCR(session, cursor_insert);
WT_STAT_DATA_INCR(session, cursor_insert);
WT_STAT_DATA_INCRV(session,
cursor_insert_bytes, cursor->key.size + cursor->value.size);
if (btree->type == BTREE_ROW)
WT_RET(__cursor_size_chk(session, &cursor->key));
WT_RET(__cursor_size_chk(session, &cursor->value));
/*
* The tree is no longer empty: eviction should pay attention to it,
* and it's no longer possible to bulk-load into it.
*/
if (btree->bulk_load_ok) {
btree->bulk_load_ok = false;
__wt_btree_evictable(session, true);
}
retry: WT_RET(__cursor_func_init(cbt, true));
switch (btree->type) {
case BTREE_COL_FIX:
case BTREE_COL_VAR:
/*
* If WT_CURSTD_APPEND is set, insert a new record (ignoring
* the application's record number). The real record number
* is assigned by the serialized append operation.
*/
if (F_ISSET(cursor, WT_CURSTD_APPEND))
cbt->iface.recno = WT_RECNO_OOB;
WT_ERR(__cursor_col_search(session, cbt, NULL));
/*
* If not overwriting, fail if the key exists. Creating a
* record past the end of the tree in a fixed-length
* column-store implicitly fills the gap with empty records.
* Fail in that case, the record exists.
*/
if (!F_ISSET(cursor, WT_CURSTD_OVERWRITE) &&
((cbt->compare == 0 && __cursor_valid(cbt, NULL)) ||
(cbt->compare != 0 && __cursor_fix_implicit(btree, cbt))))
WT_ERR(WT_DUPLICATE_KEY);
WT_ERR(__cursor_col_modify(session, cbt, false));
if (F_ISSET(cursor, WT_CURSTD_APPEND))
cbt->iface.recno = cbt->recno;
break;
case BTREE_ROW:
WT_ERR(__cursor_row_search(session, cbt, NULL, true));
/*
* If not overwriting, fail if the key exists, else insert the
* key/value pair.
*/
if (!F_ISSET(cursor, WT_CURSTD_OVERWRITE) &&
cbt->compare == 0 && __cursor_valid(cbt, NULL))
WT_ERR(WT_DUPLICATE_KEY);
ret = __cursor_row_modify(session, cbt, false);
break;
}
err: if (ret == WT_RESTART) {
WT_STAT_CONN_INCR(session, cursor_restart);
WT_STAT_DATA_INCR(session, cursor_restart);
goto retry;
}
/* Insert doesn't maintain a position across calls, clear resources. */
if (ret == 0)
WT_TRET(__curfile_leave(cbt));
if (ret != 0)
WT_TRET(__cursor_reset(cbt));
return (ret);
}
示例2: __wt_btcur_prev
/*
* __wt_btcur_prev --
* Move to the previous record in the tree.
*/
int
__wt_btcur_prev(WT_CURSOR_BTREE *cbt, bool truncating)
{
WT_CURSOR *cursor;
WT_DECL_RET;
WT_PAGE *page;
WT_SESSION_IMPL *session;
uint32_t flags;
bool newpage;
cursor = &cbt->iface;
session = (WT_SESSION_IMPL *)cbt->iface.session;
WT_STAT_CONN_INCR(session, cursor_prev);
WT_STAT_DATA_INCR(session, cursor_prev);
F_CLR(cursor, WT_CURSTD_KEY_SET | WT_CURSTD_VALUE_SET);
WT_RET(__cursor_func_init(cbt, false));
/*
* If we aren't already iterating in the right direction, there's
* some setup to do.
*/
if (!F_ISSET(cbt, WT_CBT_ITERATE_PREV))
__wt_btcur_iterate_setup(cbt);
/*
* Walk any page we're holding until the underlying call returns not-
* found. Then, move to the previous page, until we reach the start
* of the file.
*/
flags = WT_READ_PREV | WT_READ_SKIP_INTL; /* tree walk flags */
LF_SET(WT_READ_NO_SPLIT); /* don't try to split */
if (truncating)
LF_SET(WT_READ_TRUNCATE);
for (newpage = false;; newpage = true) {
page = cbt->ref == NULL ? NULL : cbt->ref->page;
/*
* Column-store pages may have appended entries. Handle it
* separately from the usual cursor code, it's in a simple
* format.
*/
if (newpage && page != NULL && page->type != WT_PAGE_ROW_LEAF &&
(cbt->ins_head = WT_COL_APPEND(page)) != NULL)
F_SET(cbt, WT_CBT_ITERATE_APPEND);
if (F_ISSET(cbt, WT_CBT_ITERATE_APPEND)) {
switch (page->type) {
case WT_PAGE_COL_FIX:
ret = __cursor_fix_append_prev(cbt, newpage);
break;
case WT_PAGE_COL_VAR:
ret = __cursor_var_append_prev(cbt, newpage);
break;
WT_ILLEGAL_VALUE_ERR(session);
}
if (ret == 0)
break;
F_CLR(cbt, WT_CBT_ITERATE_APPEND);
if (ret != WT_NOTFOUND)
break;
newpage = true;
}
if (page != NULL) {
switch (page->type) {
case WT_PAGE_COL_FIX:
ret = __cursor_fix_prev(cbt, newpage);
break;
case WT_PAGE_COL_VAR:
ret = __cursor_var_prev(cbt, newpage);
break;
case WT_PAGE_ROW_LEAF:
ret = __cursor_row_prev(cbt, newpage);
break;
WT_ILLEGAL_VALUE_ERR(session);
}
if (ret != WT_NOTFOUND)
break;
}
/*
* If we saw a lot of deleted records on this page, or we went
* all the way through a page and only saw deleted records, try
* to evict the page when we release it. Otherwise repeatedly
* deleting from the beginning of a tree can have quadratic
* performance. Take care not to force eviction of pages that
* are genuinely empty, in new trees.
*/
if (page != NULL &&
(cbt->page_deleted_count > WT_BTREE_DELETE_THRESHOLD ||
(newpage && cbt->page_deleted_count > 0)))
__wt_page_evict_soon(session, cbt->ref);
cbt->page_deleted_count = 0;
//.........这里部分代码省略.........
示例3: __wt_txn_rollback
/*
* __wt_txn_rollback --
* Roll back the current transaction.
*/
int
__wt_txn_rollback(WT_SESSION_IMPL *session, const char *cfg[])
{
WT_DECL_RET;
WT_TXN *txn;
WT_TXN_OP *op;
u_int i;
bool readonly;
WT_UNUSED(cfg);
txn = &session->txn;
readonly = txn->mod_count == 0;
WT_ASSERT(session, F_ISSET(txn, WT_TXN_RUNNING));
/* Rollback notification. */
if (txn->notify != NULL)
WT_TRET(txn->notify->notify(txn->notify, (WT_SESSION *)session,
txn->id, 0));
/* Rollback updates. */
for (i = 0, op = txn->mod; i < txn->mod_count; i++, op++) {
/* Metadata updates are never rolled back. */
if (op->fileid == WT_METAFILE_ID)
continue;
switch (op->type) {
case WT_TXN_OP_BASIC:
case WT_TXN_OP_BASIC_TS:
case WT_TXN_OP_INMEM:
WT_ASSERT(session, op->u.upd->txnid == txn->id);
WT_ASSERT(session,
S2C(session)->cache->las_fileid == 0 ||
op->fileid != S2C(session)->cache->las_fileid);
op->u.upd->txnid = WT_TXN_ABORTED;
break;
case WT_TXN_OP_REF:
__wt_delete_page_rollback(session, op->u.ref);
break;
case WT_TXN_OP_TRUNCATE_COL:
case WT_TXN_OP_TRUNCATE_ROW:
/*
* Nothing to do: these operations are only logged for
* recovery. The in-memory changes will be rolled back
* with a combination of WT_TXN_OP_REF and
* WT_TXN_OP_INMEM operations.
*/
break;
}
/* Free any memory allocated for the operation. */
__wt_txn_op_free(session, op);
}
txn->mod_count = 0;
__wt_txn_release(session);
/*
* We're between transactions, if we need to block for eviction, it's
* a good time to do so. Note that we must ignore any error return
* because the user's data is committed.
*/
if (!readonly)
(void)__wt_cache_eviction_check(session, false, false, NULL);
return (ret);
}
示例4: ex_aci
/*
* ex_aci --
* Append, change, insert in ex.
*/
static int
ex_aci(SCR *sp, EXCMD *cmdp, enum which cmd)
{
CHAR_T *p, *t;
GS *gp;
TEXT *tp;
TEXTH tiq[] = {{ 0 }};
recno_t cnt = 0, lno;
size_t len;
u_int32_t flags;
int need_newline;
gp = sp->gp;
NEEDFILE(sp, cmdp);
/*
* If doing a change, replace lines for as long as possible. Then,
* append more lines or delete remaining lines. Changes to an empty
* file are appends, inserts are the same as appends to the previous
* line.
*
* !!!
* Set the address to which we'll append. We set sp->lno to this
* address as well so that autoindent works correctly when get text
* from the user.
*/
lno = cmdp->addr1.lno;
sp->lno = lno;
if ((cmd == CHANGE || cmd == INSERT) && lno != 0)
--lno;
/*
* !!!
* If the file isn't empty, cut changes into the unnamed buffer.
*/
if (cmd == CHANGE && cmdp->addr1.lno != 0 &&
(cut(sp, NULL, &cmdp->addr1, &cmdp->addr2, CUT_LINEMODE) ||
del(sp, &cmdp->addr1, &cmdp->addr2, 1)))
return (1);
/*
* !!!
* Anything that was left after the command separator becomes part
* of the inserted text. Apparently, it was common usage to enter:
*
* :g/pattern/append|stuff1
*
* and append the line of text "stuff1" to the lines containing the
* pattern. It was also historically legal to enter:
*
* :append|stuff1
* stuff2
* .
*
* and the text on the ex command line would be appended as well as
* the text inserted after it. There was an historic bug however,
* that the user had to enter *two* terminating lines (the '.' lines)
* to terminate text input mode, in this case. This whole thing
* could be taken too far, however. Entering:
*
* :append|stuff1\
* stuff2
* stuff3
* .
*
* i.e. mixing and matching the forms confused the historic vi, and,
* not only did it take two terminating lines to terminate text input
* mode, but the trailing backslashes were retained on the input. We
* match historic practice except that we discard the backslashes.
*
* Input lines specified on the ex command line lines are separated by
* <newline>s. If there is a trailing delimiter an empty line was
* inserted. There may also be a leading delimiter, which is ignored
* unless it's also a trailing delimiter. It is possible to encounter
* a termination line, i.e. a single '.', in a global command, but not
* necessary if the text insert command was the last of the global
* commands.
*/
if (cmdp->save_cmdlen != 0) {
for (p = cmdp->save_cmd,
len = cmdp->save_cmdlen; len > 0; p = t) {
for (t = p; len > 0 && t[0] != '\n'; ++t, --len);
if (t != p || len == 0) {
if (F_ISSET(sp, SC_EX_GLOBAL) &&
t - p == 1 && p[0] == '.') {
++t;
if (len > 0)
--len;
break;
}
if (db_append(sp, 1, lno++, p, t - p))
return (1);
}
if (len != 0) {
++t;
if (--len == 0 &&
//.........这里部分代码省略.........
示例5: cl_event
/*
* cl_event --
* Return a single event.
*
* PUBLIC: int cl_event __P((SCR *, EVENT *, u_int32_t, int));
*/
int
cl_event(SCR *sp, EVENT *evp, u_int32_t flags, int ms)
{
struct timeval t, *tp;
CL_PRIVATE *clp;
size_t lines, columns;
int changed, nr = 0;
CHAR_T *wp;
size_t wlen;
int rc;
/*
* Queue signal based events. We never clear SIGHUP or SIGTERM events,
* so that we just keep returning them until the editor dies.
*/
clp = CLP(sp);
retest: if (LF_ISSET(EC_INTERRUPT) || F_ISSET(clp, CL_SIGINT)) {
if (F_ISSET(clp, CL_SIGINT)) {
F_CLR(clp, CL_SIGINT);
evp->e_event = E_INTERRUPT;
} else
evp->e_event = E_TIMEOUT;
return (0);
}
if (F_ISSET(clp, CL_SIGHUP | CL_SIGTERM | CL_SIGWINCH)) {
if (F_ISSET(clp, CL_SIGHUP)) {
evp->e_event = E_SIGHUP;
return (0);
}
if (F_ISSET(clp, CL_SIGTERM)) {
evp->e_event = E_SIGTERM;
return (0);
}
if (F_ISSET(clp, CL_SIGWINCH)) {
F_CLR(clp, CL_SIGWINCH);
if (cl_ssize(sp, 1, &lines, &columns, &changed))
return (1);
if (changed) {
(void)cl_resize(sp, lines, columns);
evp->e_event = E_WRESIZE;
return (0);
}
/* No real change, ignore the signal. */
}
}
/* Set timer. */
if (ms == 0)
tp = NULL;
else {
t.tv_sec = ms / 1000;
t.tv_usec = (ms % 1000) * 1000;
tp = &t;
}
/* Read input characters. */
read:
switch (cl_read(sp, LF_ISSET(EC_QUOTED | EC_RAW),
clp->ibuf + clp->skip, SIZE(clp->ibuf) - clp->skip, &nr, tp)) {
case INP_OK:
rc = INPUT2INT5(sp, clp->cw, clp->ibuf, nr + clp->skip,
wp, wlen);
evp->e_csp = wp;
evp->e_len = wlen;
evp->e_event = E_STRING;
if (rc < 0) {
int n = -rc;
memmove(clp->ibuf, clp->ibuf + nr + clp->skip - n, n);
clp->skip = n;
if (wlen == 0)
goto read;
} else if (rc == 0)
clp->skip = 0;
else
msgq(sp, M_ERR, "323|Invalid input. Truncated.");
break;
case INP_EOF:
evp->e_event = E_EOF;
break;
case INP_ERR:
evp->e_event = E_ERR;
break;
case INP_INTR:
goto retest;
case INP_TIMEOUT:
evp->e_event = E_TIMEOUT;
break;
default:
abort();
}
return (0);
}
示例6: __rec_review
/*
* __rec_review --
* Get exclusive access to the page and review the page and its subtree
* for conditions that would block its eviction.
*
* The ref and page arguments may appear to be redundant, because usually
* ref->page == page and page->ref == ref. However, we need both because
* (a) there are cases where ref == NULL (e.g., for root page or during
* salvage), and (b) we can't safely look at page->ref until we have a
* hazard reference.
*/
static int
__rec_review(WT_SESSION_IMPL *session,
WT_REF *ref, WT_PAGE *page, uint32_t flags, int top)
{
WT_DECL_RET;
WT_PAGE_MODIFY *mod;
WT_TXN *txn;
uint32_t i;
txn = &session->txn;
/*
* Get exclusive access to the page if our caller doesn't have the tree
* locked down.
*/
if (!LF_ISSET(WT_REC_SINGLE))
WT_RET(__hazard_exclusive(session, ref, top));
/*
* Recurse through the page's subtree: this happens first because we
* have to write pages in depth-first order, otherwise we'll dirty
* pages after we've written them.
*/
if (page->type == WT_PAGE_COL_INT || page->type == WT_PAGE_ROW_INT)
WT_REF_FOREACH(page, ref, i)
switch (ref->state) {
case WT_REF_DISK: /* On-disk */
case WT_REF_DELETED: /* On-disk, deleted */
break;
case WT_REF_MEM: /* In-memory */
WT_RET(__rec_review(
session, ref, ref->page, flags, 0));
break;
case WT_REF_EVICT_WALK: /* Walk point */
case WT_REF_LOCKED: /* Being evicted */
case WT_REF_READING: /* Being read */
return (EBUSY);
}
/*
* Check if this page can be evicted:
*
* Fail if the top-level page is a page expected to be removed from the
* tree as part of eviction (an empty page or a split-merge page). Note
* "split" pages are NOT included in this test, because a split page can
* be separately evicted, at which point it's replaced in its parent by
* a reference to a split-merge page. That's a normal part of the leaf
* page life-cycle if it grows too large and must be pushed out of the
* cache. There is also an exception for empty pages, the root page may
* be empty when evicted, but that only happens when the tree is closed.
*
* Fail if any page in the top-level page's subtree can't be merged into
* its parent. You can't evict a page that references such in-memory
* pages, they must be evicted first. The test is necessary but should
* not fire much: the LRU-based eviction code is biased for leaf pages,
* an internal page shouldn't be selected for LRU-based eviction until
* its children have been evicted. Empty, split and split-merge pages
* are all included in this test, they can all be merged into a parent.
*
* We have to write dirty pages to know their final state, a page marked
* empty may have had records added since reconciliation, a page marked
* split may have had records deleted and no longer need to split.
* Split-merge pages are the exception: they can never be change into
* anything other than a split-merge page and are merged regardless of
* being clean or dirty.
*
* Writing the page is expensive, do a cheap test first: if it doesn't
* appear a subtree page can be merged, quit. It's possible the page
* has been emptied since it was last reconciled, and writing it before
* testing might be worthwhile, but it's more probable we're attempting
* to evict an internal page with live children, and that's a waste of
* time.
*
* We don't do a cheap test for the top-level page: we're not called
* to evict split-merge pages, which means the only interesting case
* is an empty page. If the eviction thread picked an "empty" page
* for eviction, it must have had reason, probably the empty page got
* really, really full.
*/
mod = page->modify;
if (!top && (mod == NULL || !F_ISSET(mod,
WT_PM_REC_EMPTY | WT_PM_REC_SPLIT | WT_PM_REC_SPLIT_MERGE)))
return (EBUSY);
/* If the page is dirty, write it so we know the final state. */
if (__wt_page_is_modified(page) &&
!F_ISSET(mod, WT_PM_REC_SPLIT_MERGE)) {
ret = __wt_rec_write(session, page, NULL, flags);
//.........这里部分代码省略.........
示例7: __wt_page_in_func
/*
* __wt_page_in_func --
* Acquire a hazard pointer to a page; if the page is not in-memory,
* read it from the disk and build an in-memory version.
*/
int
__wt_page_in_func(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags
#ifdef HAVE_DIAGNOSTIC
, const char *file, int line
#endif
)
{
WT_DECL_RET;
WT_PAGE *page;
int busy, force_attempts, oldgen;
for (force_attempts = oldgen = 0;;) {
switch (ref->state) {
case WT_REF_DISK:
case WT_REF_DELETED:
if (LF_ISSET(WT_READ_CACHE))
return (WT_NOTFOUND);
/*
* The page isn't in memory, attempt to read it.
* Make sure there is space in the cache.
*/
WT_RET(__wt_cache_full_check(session));
WT_RET(__wt_cache_read(session, ref));
oldgen = LF_ISSET(WT_READ_WONT_NEED) ||
F_ISSET(session, WT_SESSION_NO_CACHE);
continue;
case WT_REF_READING:
if (LF_ISSET(WT_READ_CACHE))
return (WT_NOTFOUND);
/* FALLTHROUGH */
case WT_REF_LOCKED:
if (LF_ISSET(WT_READ_NO_WAIT))
return (WT_NOTFOUND);
/* The page is busy -- wait. */
break;
case WT_REF_SPLIT:
return (WT_RESTART);
case WT_REF_MEM:
/*
* The page is in memory: get a hazard pointer, update
* the page's LRU and return. The expected reason we
* can't get a hazard pointer is because the page is
* being evicted; yield and try again.
*/
#ifdef HAVE_DIAGNOSTIC
WT_RET(
__wt_hazard_set(session, ref, &busy, file, line));
#else
WT_RET(__wt_hazard_set(session, ref, &busy));
#endif
if (busy)
break;
page = ref->page;
WT_ASSERT(session, page != NULL);
/* Forcibly evict pages that are too big. */
if (!LF_ISSET(WT_READ_NO_EVICT) &&
force_attempts < 10 &&
__evict_force_check(session, page)) {
++force_attempts;
WT_RET(__wt_page_release(session, ref, flags));
break;
}
/* Check if we need an autocommit transaction. */
if ((ret = __wt_txn_autocommit_check(session)) != 0) {
WT_TRET(__wt_hazard_clear(session, page));
return (ret);
}
/*
* If we read the page and we are configured to not
* trash the cache, set the oldest read generation so
* the page is forcibly evicted as soon as possible.
*
* Otherwise, update the page's read generation.
*/
if (oldgen && page->read_gen == WT_READGEN_NOTSET)
__wt_page_evict_soon(page);
else if (!LF_ISSET(WT_READ_NO_GEN) &&
page->read_gen < __wt_cache_read_gen(session))
page->read_gen =
__wt_cache_read_gen_set(session);
return (0);
WT_ILLEGAL_VALUE(session);
}
/* We failed to get the page -- yield before retrying. */
__wt_yield();
}
}
示例8: __rec_open
DB *
__rec_open(const char *fname, int flags, mode_t mode, const RECNOINFO *openinfo,
int dflags)
{
BTREE *t;
BTREEINFO btopeninfo;
DB *dbp;
PAGE *h;
struct stat sb;
int rfd = -1; /* pacify gcc */
int sverrno;
dbp = NULL;
/* Open the user's file -- if this fails, we're done. */
if (fname != NULL) {
if ((rfd = open(fname, flags | O_CLOEXEC, mode)) == -1)
return NULL;
}
/* Create a btree in memory (backed by disk). */
if (openinfo) {
if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
goto einval;
btopeninfo.flags = 0;
btopeninfo.cachesize = openinfo->cachesize;
btopeninfo.maxkeypage = 0;
btopeninfo.minkeypage = 0;
btopeninfo.psize = openinfo->psize;
btopeninfo.compare = NULL;
btopeninfo.prefix = NULL;
btopeninfo.lorder = openinfo->lorder;
dbp = __bt_open(openinfo->bfname,
O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
} else
dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
if (dbp == NULL)
goto err;
/*
* Some fields in the tree structure are recno specific. Fill them
* in and make the btree structure look like a recno structure. We
* don't change the bt_ovflsize value, it's close enough and slightly
* bigger.
*/
t = dbp->internal;
if (openinfo) {
if (openinfo->flags & R_FIXEDLEN) {
F_SET(t, R_FIXLEN);
t->bt_reclen = openinfo->reclen;
if (t->bt_reclen == 0)
goto einval;
}
t->bt_bval = openinfo->bval;
} else
t->bt_bval = '\n';
F_SET(t, R_RECNO);
if (fname == NULL)
F_SET(t, R_EOF | R_INMEM);
else
t->bt_rfd = rfd;
if (fname != NULL) {
/*
* In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
* Unfortunately, that's not portable, so we use lseek
* and check the errno values.
*/
errno = 0;
if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
switch (flags & O_ACCMODE) {
case O_RDONLY:
F_SET(t, R_RDONLY);
break;
default:
goto einval;
}
slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
goto err;
F_SET(t, R_CLOSEFP);
t->bt_irec =
F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
} else {
switch (flags & O_ACCMODE) {
case O_RDONLY:
F_SET(t, R_RDONLY);
break;
case O_RDWR:
break;
default:
goto einval;
}
if (fstat(rfd, &sb))
goto err;
/*
* Kluge -- we'd like to test to see if the file is too
* big to mmap. Since, we don't know what size or type
* off_t's or size_t's are, what the largest unsigned
* integral type is, or what random insanity the local
//.........这里部分代码省略.........
示例9: __wt_page_out
/*
* __wt_page_out --
* Discard an in-memory page, freeing all memory associated with it.
*/
void
__wt_page_out(WT_SESSION_IMPL *session, WT_PAGE **pagep)
{
WT_PAGE *page;
WT_PAGE_HEADER *dsk;
WT_PAGE_MODIFY *mod;
/*
* Kill our caller's reference, do our best to catch races.
*/
page = *pagep;
*pagep = NULL;
if (F_ISSET(session->dhandle, WT_DHANDLE_DEAD))
__wt_page_modify_clear(session, page);
/*
* We should never discard:
* - a dirty page,
* - a page queued for eviction, or
* - a locked page.
*/
WT_ASSERT(session, !__wt_page_is_modified(page));
WT_ASSERT(session, !F_ISSET_ATOMIC(page, WT_PAGE_EVICT_LRU));
WT_ASSERT(session, !__wt_rwlock_islocked(session, &page->page_lock));
/*
* If a root page split, there may be one or more pages linked from the
* page; walk the list, discarding pages.
*/
switch (page->type) {
case WT_PAGE_COL_INT:
case WT_PAGE_ROW_INT:
mod = page->modify;
if (mod != NULL && mod->mod_root_split != NULL)
__wt_page_out(session, &mod->mod_root_split);
break;
}
/* Update the cache's information. */
__wt_cache_page_evict(session, page);
dsk = (WT_PAGE_HEADER *)page->dsk;
if (F_ISSET_ATOMIC(page, WT_PAGE_DISK_ALLOC))
__wt_cache_page_image_decr(session, dsk->mem_size);
/* Discard any mapped image. */
if (F_ISSET_ATOMIC(page, WT_PAGE_DISK_MAPPED))
(void)S2BT(session)->bm->map_discard(
S2BT(session)->bm, session, dsk, (size_t)dsk->mem_size);
/*
* If discarding the page as part of process exit, the application may
* configure to leak the memory rather than do the work.
*/
if (F_ISSET(S2C(session), WT_CONN_LEAK_MEMORY))
return;
/* Free the page modification information. */
if (page->modify != NULL)
__free_page_modify(session, page);
switch (page->type) {
case WT_PAGE_COL_FIX:
break;
case WT_PAGE_COL_INT:
case WT_PAGE_ROW_INT:
__free_page_int(session, page);
break;
case WT_PAGE_COL_VAR:
__free_page_col_var(session, page);
break;
case WT_PAGE_ROW_LEAF:
__free_page_row_leaf(session, page);
break;
}
/* Discard any allocated disk image. */
if (F_ISSET_ATOMIC(page, WT_PAGE_DISK_ALLOC))
__wt_overwrite_and_free_len(session, dsk, dsk->mem_size);
__wt_overwrite_and_free(session, page);
}
示例10: __cursor_valid
//.........这里部分代码省略.........
* Column-store is more complicated because an insert object can have
* the same key as an on-page object: updates to column-store rows
* are insert/object pairs, and an invisible update isn't the end as
* there may be an on-page object that is visible. This changes the
* logic to:
* if there's an insert object:
* if there's a visible update:
* exact match
* else if the on-page object's key matches the insert key
* use the on-page object
* else
* use the on-page object
*
* First, check for an insert object with a visible update (a visible
* update that's been deleted is not a valid key/value pair).
*/
if (cbt->ins != NULL &&
(upd = __wt_txn_read(session, cbt->ins->upd)) != NULL) {
if (WT_UPDATE_DELETED_ISSET(upd))
return (false);
if (updp != NULL)
*updp = upd;
return (true);
}
/*
* If we don't have an insert object, or in the case of column-store,
* there's an insert object but no update was visible to us and the key
* on the page is the same as the insert object's key, and the slot as
* set by the search function is valid, we can use the original page
* information.
*/
switch (btree->type) {
case BTREE_COL_FIX:
/*
* If search returned an insert object, there may or may not be
* a matching on-page object, we have to check. Fixed-length
* column-store pages don't have slots, but map one-to-one to
* keys, check for retrieval past the end of the page.
*/
if (cbt->recno >= cbt->ref->ref_recno + page->pg_fix_entries)
return (false);
/*
* An update would have appeared as an "insert" object; no
* further checks to do.
*/
break;
case BTREE_COL_VAR:
/* The search function doesn't check for empty pages. */
if (page->pg_var_entries == 0)
return (false);
WT_ASSERT(session, cbt->slot < page->pg_var_entries);
/*
* Column-store updates are stored as "insert" objects. If
* search returned an insert object we can't return, the
* returned on-page object must be checked for a match.
*/
if (cbt->ins != NULL && !F_ISSET(cbt, WT_CBT_VAR_ONPAGE_MATCH))
return (false);
/*
* Although updates would have appeared as an "insert" objects,
* variable-length column store deletes are written into the
* backing store; check the cell for a record already deleted
* when read.
*/
cip = &page->pg_var_d[cbt->slot];
if ((cell = WT_COL_PTR(page, cip)) == NULL ||
__wt_cell_type(cell) == WT_CELL_DEL)
return (false);
break;
case BTREE_ROW:
/* The search function doesn't check for empty pages. */
if (page->pg_row_entries == 0)
return (false);
WT_ASSERT(session, cbt->slot < page->pg_row_entries);
/*
* See above: for row-store, no insert object can have the same
* key as an on-page object, we're done.
*/
if (cbt->ins != NULL)
return (false);
/* Check for an update. */
if (page->modify != NULL &&
page->modify->mod_row_update != NULL &&
(upd = __wt_txn_read(session,
page->modify->mod_row_update[cbt->slot])) != NULL) {
if (WT_UPDATE_DELETED_ISSET(upd))
return (false);
if (updp != NULL)
*updp = upd;
}
break;
}
return (true);
}
示例11: __wt_btcur_update
/*
* __wt_btcur_update --
* Update a record in the tree.
*/
int
__wt_btcur_update(WT_CURSOR_BTREE *cbt)
{
WT_BTREE *btree;
WT_CURSOR *cursor;
WT_DECL_RET;
WT_SESSION_IMPL *session;
btree = cbt->btree;
cursor = &cbt->iface;
session = (WT_SESSION_IMPL *)cursor->session;
WT_STAT_CONN_INCR(session, cursor_update);
WT_STAT_DATA_INCR(session, cursor_update);
WT_STAT_DATA_INCRV(session, cursor_update_bytes, cursor->value.size);
if (btree->type == BTREE_ROW)
WT_RET(__cursor_size_chk(session, &cursor->key));
WT_RET(__cursor_size_chk(session, &cursor->value));
/*
* The tree is no longer empty: eviction should pay attention to it,
* and it's no longer possible to bulk-load into it.
*/
if (btree->bulk_load_ok) {
btree->bulk_load_ok = false;
__wt_btree_evictable(session, true);
}
retry: WT_RET(__cursor_func_init(cbt, true));
switch (btree->type) {
case BTREE_COL_FIX:
case BTREE_COL_VAR:
WT_ERR(__cursor_col_search(session, cbt, NULL));
/*
* If not overwriting, fail if the key doesn't exist. If we
* find an update for the key, check for conflicts. Update the
* record if it exists. Creating a record past the end of the
* tree in a fixed-length column-store implicitly fills the gap
* with empty records. Update the record in that case, the
* record exists.
*/
if (!F_ISSET(cursor, WT_CURSTD_OVERWRITE)) {
WT_ERR(__curfile_update_check(cbt));
if ((cbt->compare != 0 || !__cursor_valid(cbt, NULL)) &&
!__cursor_fix_implicit(btree, cbt))
WT_ERR(WT_NOTFOUND);
}
ret = __cursor_col_modify(session, cbt, false);
break;
case BTREE_ROW:
WT_ERR(__cursor_row_search(session, cbt, NULL, true));
/*
* If not overwriting, check for conflicts and fail if the key
* does not exist.
*/
if (!F_ISSET(cursor, WT_CURSTD_OVERWRITE)) {
WT_ERR(__curfile_update_check(cbt));
if (cbt->compare != 0 || !__cursor_valid(cbt, NULL))
WT_ERR(WT_NOTFOUND);
}
ret = __cursor_row_modify(session, cbt, false);
break;
}
err: if (ret == WT_RESTART) {
WT_STAT_CONN_INCR(session, cursor_restart);
WT_STAT_DATA_INCR(session, cursor_restart);
goto retry;
}
/*
* If successful, point the cursor at internal copies of the data. We
* could shuffle memory in the cursor so the key/value pair are in local
* buffer memory, but that's a data copy. We don't want to do another
* search (and we might get a different update structure if we race).
* To make this work, we add a field to the btree cursor to pass back a
* pointer to the modify function's allocated update structure.
*/
if (ret == 0)
WT_TRET(__wt_kv_return(session, cbt, cbt->modify_update));
if (ret != 0)
WT_TRET(__cursor_reset(cbt));
return (ret);
}
示例12: __wt_btcur_remove
/*
* __wt_btcur_remove --
* Remove a record from the tree.
*/
int
__wt_btcur_remove(WT_CURSOR_BTREE *cbt)
{
WT_BTREE *btree;
WT_CURSOR *cursor;
WT_DECL_RET;
WT_SESSION_IMPL *session;
btree = cbt->btree;
cursor = &cbt->iface;
session = (WT_SESSION_IMPL *)cursor->session;
WT_STAT_CONN_INCR(session, cursor_remove);
WT_STAT_DATA_INCR(session, cursor_remove);
WT_STAT_DATA_INCRV(session, cursor_remove_bytes, cursor->key.size);
retry: WT_RET(__cursor_func_init(cbt, true));
switch (btree->type) {
case BTREE_COL_FIX:
case BTREE_COL_VAR:
WT_ERR(__cursor_col_search(session, cbt, NULL));
/*
* If we find a matching record, check whether an update would
* conflict. Do this before checking if the update is visible
* in __cursor_valid, or we can miss conflict.
*/
WT_ERR(__curfile_update_check(cbt));
/* Remove the record if it exists. */
if (cbt->compare != 0 || !__cursor_valid(cbt, NULL)) {
if (!__cursor_fix_implicit(btree, cbt))
WT_ERR(WT_NOTFOUND);
/*
* Creating a record past the end of the tree in a
* fixed-length column-store implicitly fills the
* gap with empty records. Return success in that
* case, the record was deleted successfully.
*
* Correct the btree cursor's location: the search
* will have pointed us at the previous/next item,
* and that's not correct.
*/
cbt->recno = cursor->recno;
} else
ret = __cursor_col_modify(session, cbt, true);
break;
case BTREE_ROW:
/* Remove the record if it exists. */
WT_ERR(__cursor_row_search(session, cbt, NULL, false));
/* Check whether an update would conflict. */
WT_ERR(__curfile_update_check(cbt));
if (cbt->compare != 0 || !__cursor_valid(cbt, NULL))
WT_ERR(WT_NOTFOUND);
ret = __cursor_row_modify(session, cbt, true);
break;
}
err: if (ret == WT_RESTART) {
WT_STAT_CONN_INCR(session, cursor_restart);
WT_STAT_DATA_INCR(session, cursor_restart);
goto retry;
}
/*
* If the cursor is configured to overwrite and the record is not
* found, that is exactly what we want.
*/
if (F_ISSET(cursor, WT_CURSTD_OVERWRITE) && ret == WT_NOTFOUND)
ret = 0;
if (ret != 0)
WT_TRET(__cursor_reset(cbt));
return (ret);
}
示例13: __wt_verify
/*
* __wt_verify --
* Verify a file.
*/
int
__wt_verify(WT_SESSION_IMPL *session, const char *cfg[])
{
WT_BM *bm;
WT_BTREE *btree;
WT_CKPT *ckptbase, *ckpt;
WT_DECL_RET;
WT_VSTUFF *vs, _vstuff;
uint32_t root_addr_size;
uint8_t root_addr[WT_BTREE_MAX_ADDR_COOKIE];
btree = S2BT(session);
bm = btree->bm;
ckptbase = NULL;
WT_CLEAR(_vstuff);
vs = &_vstuff;
WT_ERR(__wt_scr_alloc(session, 0, &vs->max_key));
WT_ERR(__wt_scr_alloc(session, 0, &vs->max_addr));
WT_ERR(__wt_scr_alloc(session, 0, &vs->tmp1));
WT_ERR(__wt_scr_alloc(session, 0, &vs->tmp2));
/* Check configuration strings. */
WT_ERR(__verify_config(session, cfg, vs));
/* Get a list of the checkpoints for this file. */
WT_ERR(
__wt_meta_ckptlist_get(session, btree->dhandle->name, &ckptbase));
/* Inform the underlying block manager we're verifying. */
WT_ERR(bm->verify_start(bm, session, ckptbase));
/* Loop through the file's checkpoints, verifying each one. */
WT_CKPT_FOREACH(ckptbase, ckpt) {
WT_VERBOSE_ERR(session, verify,
"%s: checkpoint %s", btree->dhandle->name, ckpt->name);
#ifdef HAVE_DIAGNOSTIC
if (vs->dump_address || vs->dump_blocks || vs->dump_pages)
WT_ERR(__wt_msg(session, "%s: checkpoint %s",
btree->dhandle->name, ckpt->name));
#endif
/* Fake checkpoints require no work. */
if (F_ISSET(ckpt, WT_CKPT_FAKE))
continue;
/* House-keeping between checkpoints. */
__verify_checkpoint_reset(vs);
/* Load the checkpoint, ignore trees with no root page. */
WT_ERR(bm->checkpoint_load(bm, session,
ckpt->raw.data, ckpt->raw.size,
root_addr, &root_addr_size, 1));
if (root_addr_size != 0) {
/* Verify then discard the checkpoint from the cache. */
if ((ret = __wt_btree_tree_open(
session, root_addr, root_addr_size)) == 0) {
ret = __verify_tree(
session, btree->root_page, vs);
WT_TRET(__wt_bt_cache_op(
session, NULL, WT_SYNC_DISCARD_NOWRITE));
}
}
/* Unload the checkpoint. */
WT_TRET(bm->checkpoint_unload(bm, session));
WT_ERR(ret);
}
示例14: __wt_rec_evict
/*
* __wt_rec_evict --
* Reconciliation plus eviction.
*/
int
__wt_rec_evict(WT_SESSION_IMPL *session, WT_PAGE *page, uint32_t flags)
{
WT_CONNECTION_IMPL *conn;
WT_DECL_RET;
int single;
conn = S2C(session);
WT_VERBOSE_RET(session, evict,
"page %p (%s)", page, __wt_page_type_string(page->type));
WT_ASSERT(session, session->excl_next == 0);
single = LF_ISSET(WT_REC_SINGLE) ? 1 : 0;
/*
* Get exclusive access to the page and review the page and its subtree
* for conditions that would block our eviction of the page. If the
* check fails (for example, we find a child page that can't be merged),
* we're done. We have to make this check for clean pages, too: while
* unlikely eviction would choose an internal page with children, it's
* not disallowed anywhere.
*
* Note that page->ref may be NULL in some cases (e.g., for root pages
* or during salvage). That's OK if WT_REC_SINGLE is set: we won't
* check hazard references in that case.
*/
WT_ERR(__rec_review(session, page->ref, page, flags, 1));
/* Count evictions of internal pages during normal operation. */
if (!single &&
(page->type == WT_PAGE_COL_INT || page->type == WT_PAGE_ROW_INT))
WT_STAT_INCR(conn->stats, cache_evict_internal);
/* Update the parent and discard the page. */
if (page->modify == NULL || !F_ISSET(page->modify, WT_PM_REC_MASK)) {
WT_STAT_INCR(conn->stats, cache_evict_unmodified);
WT_ASSERT(session, single || page->ref->state == WT_REF_LOCKED);
if (WT_PAGE_IS_ROOT(page))
__rec_root_update(session);
else
__rec_page_clean_update(session, page);
/* Discard the page. */
__rec_discard_page(session, page, single);
} else {
WT_STAT_INCR(conn->stats, cache_evict_modified);
if (WT_PAGE_IS_ROOT(page))
__rec_root_update(session);
else
WT_ERR(__rec_page_dirty_update(session, page));
/* Discard the tree rooted in this page. */
__rec_discard_tree(session, page, single);
}
if (0) {
err: /*
* If unable to evict this page, release exclusive reference(s)
* we've acquired.
*/
__rec_excl_clear(session);
}
session->excl_next = 0;
return (ret);
}
示例15: __wt_curds_create
/*
* __wt_curds_create --
* Initialize a data-source cursor.
*/
int
__wt_curds_create(WT_SESSION_IMPL *session, const char *uri,
const char *cfg[], WT_DATA_SOURCE *dsrc, WT_CURSOR **cursorp)
{
WT_CURSOR_STATIC_INIT(iface,
NULL, /* get-key */
NULL, /* get-value */
NULL, /* set-key */
NULL, /* set-value */
NULL, /* compare */
__curds_next, /* next */
__curds_prev, /* prev */
__curds_reset, /* reset */
__curds_search, /* search */
__curds_search_near, /* search-near */
__curds_insert, /* insert */
__curds_update, /* update */
__curds_remove, /* remove */
__curds_close); /* close */
WT_CONFIG_ITEM cval;
WT_CURSOR *cursor, *dsc;
WT_DECL_RET;
const char *metaconf;
metaconf = NULL;
/* Open the WiredTiger cursor. */
WT_RET(__wt_calloc_def(session, 1, &cursor));
*cursor = iface;
cursor->session = (WT_SESSION *)session;
/*
* XXX
* We'll need the object's key and value formats.
*/
WT_ERR(__wt_metadata_search(session, uri, &metaconf));
WT_ERR(__wt_config_getones(session, metaconf, "key_format", &cval));
WT_ERR(__wt_strndup(session, cval.str, cval.len, &cursor->key_format));
WT_ERR(__wt_config_getones(session, metaconf, "value_format", &cval));
WT_ERR(
__wt_strndup(session, cval.str, cval.len, &cursor->value_format));
WT_ERR(__wt_cursor_init(cursor, uri, NULL, cfg, cursorp));
WT_ERR(dsrc->open_cursor(dsrc,
&session->iface, uri, (WT_CONFIG_ARG *)cfg, &dsc));
dsc->session = (WT_SESSION *)session;
memset(&dsc->q, 0, sizeof(dsc->q));
dsc->recno = 0;
memset(dsc->raw_recno_buf, 0, sizeof(dsc->raw_recno_buf));
memset(&dsc->key, 0, sizeof(dsc->key));
memset(&dsc->value, 0, sizeof(dsc->value));
memset(&dsc->saved_err, 0, sizeof(dsc->saved_err));
dsc->data_source = NULL;
memset(&dsc->flags, 0, sizeof(dsc->flags));
/* Reference the underlying application cursor. */
cursor->data_source = dsc;
if (0) {
err: if (F_ISSET(cursor, WT_CURSTD_OPEN))
WT_TRET(cursor->close(cursor));
else
__wt_free(session, cursor);
}
__wt_free(session, metaconf);
return (ret);
}