/* * __cursor_truncate_fix -- * Discard a cursor range from fixed-width column-store tree. */ static int __cursor_truncate_fix(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *start, WT_CURSOR_BTREE *stop, int (*rmfunc)(WT_SESSION_IMPL *, WT_CURSOR_BTREE *, int)) { WT_DECL_RET; uint8_t *value; /* * Handle fixed-length column-store objects separately: for row-store * and variable-length column-store objects we have "deleted" values * and so returned objects actually exist: fixed-length column-store * objects are filled-in if they don't exist, that is, if you create * record 37, records 1-36 magically appear. Those records can't be * deleted, which means we have to ignore already "deleted" records. * * First, call the standard cursor remove method to do a full search and * re-position the cursor because we don't have a saved copy of the * page's write generation information, which we need to remove records. * Once that's done, we can delete records without a full search, unless * we encounter a restart error because the page was modified by some * other thread of control; in that case, repeat the full search to * refresh the page's modification information. */ if (start == NULL) { do { WT_RET(__wt_btcur_remove(stop)); for (;;) { if ((ret = __wt_btcur_prev(stop, 1)) != 0) break; stop->compare = 0; /* Exact match */ value = (uint8_t *)stop->iface.value.data; if (*value != 0 && (ret = rmfunc(session, stop, 1)) != 0) break; } } while (ret == WT_RESTART); } else { do { WT_RET(__wt_btcur_remove(start)); for (;;) { if (stop != NULL && __cursor_equals(start, stop)) break; if ((ret = __wt_btcur_next(start, 1)) != 0) break; start->compare = 0; /* Exact match */ value = (uint8_t *)start->iface.value.data; if (*value != 0 && (ret = rmfunc(session, start, 1)) != 0) break; } } while (ret == WT_RESTART); } WT_RET_NOTFOUND_OK(ret); return (0); }
/* * __cursor_truncate -- * Discard a cursor range from row-store or variable-width column-store * tree. */ static int __cursor_truncate(WT_SESSION_IMPL *session, WT_CURSOR_BTREE *start, WT_CURSOR_BTREE *stop, int (*rmfunc)(WT_SESSION_IMPL *, WT_CURSOR_BTREE *, int)) { WT_DECL_RET; /* * First, call the standard cursor remove method to do a full search and * re-position the cursor because we don't have a saved copy of the * page's write generation information, which we need to remove records. * Once that's done, we can delete records without a full search, unless * we encounter a restart error because the page was modified by some * other thread of control; in that case, repeat the full search to * refresh the page's modification information. * * If this is a row-store, we delete leaf pages having no overflow items * without reading them; for that to work, we have to ensure we read the * page referenced by the ending cursor, since we may be deleting only a * partial page at the end of the truncation. Our caller already fully * instantiated the end cursor, so we know that page is pinned in memory * and we can proceed without concern. */ if (start == NULL) { do { WT_RET(__wt_btcur_remove(stop)); for (;;) { if ((ret = __wt_btcur_prev(stop, 1)) != 0) break; stop->compare = 0; /* Exact match */ if ((ret = rmfunc(session, stop, 1)) != 0) break; } } while (ret == WT_RESTART); } else { do { WT_RET(__wt_btcur_remove(start)); /* * Reset ret each time through so that we don't loop * forever in the cursor equals case. */ for (ret = 0;;) { if (stop != NULL && __cursor_equals(start, stop)) break; if ((ret = __wt_btcur_next(start, 1)) != 0) break; start->compare = 0; /* Exact match */ if ((ret = rmfunc(session, start, 1)) != 0) break; } } while (ret == WT_RESTART); } WT_RET_NOTFOUND_OK(ret); return (0); }
/* * __curfile_remove -- * WT_CURSOR->remove method for the btree cursor type. */ static int __curfile_remove(WT_CURSOR *cursor) { WT_CURSOR_BTREE *cbt; WT_DECL_RET; WT_SESSION_IMPL *session; cbt = (WT_CURSOR_BTREE *)cursor; CURSOR_UPDATE_API_CALL(cursor, session, remove, cbt->btree); WT_CURSOR_NEEDKEY(cursor); WT_CURSOR_NOVALUE(cursor); WT_BTREE_CURSOR_SAVE_AND_RESTORE(cursor, __wt_btcur_remove(cbt), ret); /* * After a successful remove, copy the key: the value is not available. */ if (ret == 0) { if (F_ISSET(cursor, WT_CURSTD_KEY_INT) && !WT_DATA_IN_ITEM(&(cursor)->key)) { WT_ERR(__wt_buf_set(session, &cursor->key, cursor->key.data, cursor->key.size)); F_CLR(cursor, WT_CURSTD_KEY_INT); F_SET(cursor, WT_CURSTD_KEY_EXT); } F_CLR(cursor, WT_CURSTD_VALUE_SET); } err: CURSOR_UPDATE_API_END(session, ret); return (ret); }
/* * __curfile_remove -- * WT_CURSOR->remove method for the btree cursor type. */ static int __curfile_remove(WT_CURSOR *cursor) { WT_CURSOR_BTREE *cbt; WT_DECL_RET; WT_SESSION_IMPL *session; cbt = (WT_CURSOR_BTREE *)cursor; CURSOR_REMOVE_API_CALL(cursor, session, cbt->btree); WT_ERR(__cursor_checkkey(cursor)); WT_ERR(__wt_btcur_remove(cbt)); /* * Remove with a search-key is fire-and-forget, no position and no key. * Remove starting from a position maintains the position and a key. * We don't know which it was at this layer, so can only assert the key * is not set at all, or internal. There's never a value. */ WT_ASSERT(session, F_MASK(cursor, WT_CURSTD_KEY_SET) == 0 || F_MASK(cursor, WT_CURSTD_KEY_SET) == WT_CURSTD_KEY_INT); WT_ASSERT(session, F_MASK(cursor, WT_CURSTD_VALUE_SET) == 0); err: CURSOR_UPDATE_API_END(session, ret); return (ret); }
/* * __curfile_remove -- * WT_CURSOR->remove method for the btree cursor type. */ static int __curfile_remove(WT_CURSOR *cursor) { WT_CURSOR_BTREE *cbt; WT_DECL_RET; WT_SESSION_IMPL *session; cbt = (WT_CURSOR_BTREE *)cursor; CURSOR_UPDATE_API_CALL(cursor, session, remove, cbt->btree); WT_CURSOR_NEEDKEY(cursor); ret = __wt_btcur_remove((WT_CURSOR_BTREE *)cursor); err: CURSOR_UPDATE_API_END(session, ret); return (ret); }