/* * __wt_clsm_open_bulk -- * WT_SESSION->open_cursor method for LSM bulk cursors. */ int __wt_clsm_open_bulk(WT_CURSOR_LSM *clsm, const char *cfg[]) { WT_CURSOR *cursor, *bulk_cursor; WT_DECL_RET; WT_LSM_TREE *lsm_tree; WT_SESSION_IMPL *session; bulk_cursor = NULL; cursor = &clsm->iface; lsm_tree = clsm->lsm_tree; session = (WT_SESSION_IMPL *)clsm->iface.session; F_SET(clsm, WT_CLSM_BULK); /* Bulk cursors are limited to insert and close. */ __wt_cursor_set_notsup(cursor); cursor->insert = __clsm_insert_bulk; cursor->close = __clsm_close_bulk; /* * Setup the first chunk in the tree. This is the only time we switch * without using the LSM worker threads, it's safe to do here since * we have an exclusive lock on the LSM tree. We need to do this * switch inline, since switch needs a schema lock and online index * creation opens a bulk cursor while holding the schema lock. */ WT_WITH_SCHEMA_LOCK(session, ret, ret = __wt_lsm_tree_switch(session, lsm_tree)); WT_RET(ret); /* * Open a bulk cursor on the first chunk, it's not a regular LSM chunk * cursor, but use the standard storage locations. Allocate the space * for a bloom filter - it makes cleanup simpler. Cleaned up by * cursor close on error. */ WT_RET(__wt_calloc_one(session, &clsm->blooms)); clsm->bloom_alloc = 1; WT_RET(__wt_calloc_one(session, &clsm->cursors)); clsm->cursor_alloc = 1; clsm->nchunks = 1; /* * Open a bulk cursor on the first chunk in the tree - take a read * lock on the LSM tree while we are opening the chunk, to ensure * that the first chunk has been fully created before we succeed. * Pass through the application config to ensure the tree is open * for bulk access. */ WT_RET(__wt_open_cursor(session, lsm_tree->chunk[0]->uri, &clsm->iface, cfg, &bulk_cursor)); clsm->cursors[0] = bulk_cursor; /* LSM cursors are always raw */ F_SET(bulk_cursor, WT_CURSTD_RAW); return (0); }
/* * __wt_clsm_open_bulk -- * WT_SESSION->open_cursor method for LSM bulk cursors. */ int __wt_clsm_open_bulk(WT_CURSOR_LSM *clsm, const char *cfg[]) { WT_CURSOR *cursor, *bulk_cursor; WT_LSM_TREE *lsm_tree; WT_SESSION_IMPL *session; bulk_cursor = NULL; cursor = &clsm->iface; lsm_tree = clsm->lsm_tree; session = (WT_SESSION_IMPL *)clsm->iface.session; F_SET(clsm, WT_CLSM_BULK); /* Bulk cursors are limited to insert and close. */ __wt_cursor_set_notsup(cursor); cursor->insert = __clsm_insert_bulk; cursor->close = __clsm_close_bulk; /* Setup the first chunk in the tree. */ WT_RET(__wt_clsm_request_switch(clsm)); WT_RET(__wt_clsm_await_switch(clsm)); /* * Grab and release the LSM tree lock to ensure that the first chunk * has been fully created before proceeding. We have the LSM tree * open exclusive, so that saves us from needing the lock generally. */ WT_RET(__wt_lsm_tree_readlock(session, lsm_tree)); WT_RET(__wt_lsm_tree_readunlock(session, lsm_tree)); /* * Open a bulk cursor on the first chunk, it's not a regular LSM chunk * cursor, but use the standard storage locations. Allocate the space * for a bloom filter - it makes cleanup simpler. Cleaned up by * cursor close on error. */ WT_RET(__wt_calloc_one(session, &clsm->blooms)); clsm->bloom_alloc = 1; WT_RET(__wt_calloc_one(session, &clsm->cursors)); clsm->cursor_alloc = 1; clsm->nchunks = 1; /* * Open a bulk cursor on the first chunk in the tree - take a read * lock on the LSM tree while we are opening the chunk, to ensure * that the first chunk has been fully created before we succeed. * Pass through the application config to ensure the tree is open * for bulk access. */ WT_RET(__wt_open_cursor(session, lsm_tree->chunk[0]->uri, &clsm->iface, cfg, &bulk_cursor)); clsm->cursors[0] = bulk_cursor; /* LSM cursors are always raw */ F_SET(bulk_cursor, WT_CURSTD_RAW); return (0); }
/* * __wt_curbulk_init -- * Initialize a bulk cursor. */ int __wt_curbulk_init(WT_CURSOR_BULK *cbulk, int bitmap) { WT_CURSOR *c = &cbulk->cbt.iface; /* * Bulk cursors only support insert and close (reset is a no-op). * This is slightly tricky because cursor.reset is called during * checkpoints, which means checkpoints have to handle open bulk * cursors. */ __wt_cursor_set_notsup(c); c->insert = __curbulk_insert; c->close = __curbulk_close; cbulk->bitmap = bitmap; if (bitmap) F_SET(c, WT_CURSTD_RAW); return (__wt_bulk_init(cbulk)); }
/* * __wt_curbulk_init -- * Initialize a bulk cursor. */ int __wt_curbulk_init(WT_SESSION_IMPL *session, WT_CURSOR_BULK *cbulk, bool bitmap, bool skip_sort_check) { WT_CURSOR *c; WT_CURSOR_BTREE *cbt; c = &cbulk->cbt.iface; cbt = &cbulk->cbt; /* Bulk cursors only support insert and close (reset is a no-op). */ __wt_cursor_set_notsup(c); switch (cbt->btree->type) { case BTREE_COL_FIX: c->insert = bitmap ? __curbulk_insert_fix_bitmap : __curbulk_insert_fix; break; case BTREE_COL_VAR: c->insert = __curbulk_insert_var; break; case BTREE_ROW: /* * Row-store order comparisons are expensive, so we optionally * skip them when we know the input is correct. */ c->insert = skip_sort_check ? __curbulk_insert_row_skip_check : __curbulk_insert_row; break; WT_ILLEGAL_VALUE(session); } cbulk->first_insert = true; cbulk->recno = 0; cbulk->bitmap = bitmap; if (bitmap) F_SET(c, WT_CURSTD_RAW); return (__wt_bulk_init(session, cbulk)); }
/* * __wt_curfile_create -- * Open a cursor for a given btree handle. */ int __wt_curfile_create(WT_SESSION_IMPL *session, WT_CURSOR *owner, const char *cfg[], int bulk, int bitmap, WT_CURSOR **cursorp) { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curfile_compare, /* compare */ __curfile_equals, /* equals */ __curfile_next, /* next */ __curfile_prev, /* prev */ __curfile_reset, /* reset */ __curfile_search, /* search */ __curfile_search_near, /* search-near */ __curfile_insert, /* insert */ __curfile_update, /* update */ __curfile_remove, /* remove */ __wt_cursor_reconfigure, /* reconfigure */ __curfile_close); /* close */ WT_BTREE *btree; WT_CONFIG_ITEM cval; WT_CURSOR *cursor; WT_CURSOR_BTREE *cbt; WT_CURSOR_BULK *cbulk; WT_DECL_RET; size_t csize; WT_STATIC_ASSERT(offsetof(WT_CURSOR_BTREE, iface) == 0); cbt = NULL; btree = S2BT(session); WT_ASSERT(session, btree != NULL); csize = bulk ? sizeof(WT_CURSOR_BULK) : sizeof(WT_CURSOR_BTREE); WT_RET(__wt_calloc(session, 1, csize, &cbt)); cursor = &cbt->iface; *cursor = iface; cursor->session = &session->iface; cursor->internal_uri = btree->dhandle->name; cursor->key_format = btree->key_format; cursor->value_format = btree->value_format; cbt->btree = btree; if (bulk) { F_SET(cursor, WT_CURSTD_BULK); cbulk = (WT_CURSOR_BULK *)cbt; /* Optionally skip the validation of each bulk-loaded key. */ WT_ERR(__wt_config_gets_def( session, cfg, "skip_sort_check", 0, &cval)); WT_ERR(__wt_curbulk_init( session, cbulk, bitmap, cval.val == 0 ? 0 : 1)); } /* * random_retrieval * Random retrieval cursors only support next, reset and close. */ WT_ERR(__wt_config_gets_def(session, cfg, "next_random", 0, &cval)); if (cval.val != 0) { __wt_cursor_set_notsup(cursor); cursor->next = __curfile_next_random; cursor->reset = __curfile_reset; } /* Underlying btree initialization. */ __wt_btcur_open(cbt); /* __wt_cursor_init is last so we don't have to clean up on error. */ WT_ERR(__wt_cursor_init( cursor, cursor->internal_uri, owner, cfg, cursorp)); WT_STAT_FAST_CONN_INCR(session, cursor_create); WT_STAT_FAST_DATA_INCR(session, cursor_create); if (0) { err: __wt_free(session, cbt); } return (ret); }
/* * __curfile_create -- * Open a cursor for a given btree handle. */ static int __curfile_create(WT_SESSION_IMPL *session, WT_CURSOR *owner, const char *cfg[], bool bulk, bool bitmap, WT_CURSOR **cursorp) { WT_CURSOR_STATIC_INIT(iface, __wt_cursor_get_key, /* get-key */ __wt_cursor_get_value, /* get-value */ __wt_cursor_set_key, /* set-key */ __wt_cursor_set_value, /* set-value */ __curfile_compare, /* compare */ __curfile_equals, /* equals */ __curfile_next, /* next */ __curfile_prev, /* prev */ __curfile_reset, /* reset */ __curfile_search, /* search */ __curfile_search_near, /* search-near */ __curfile_insert, /* insert */ __wt_cursor_modify_notsup, /* modify */ __curfile_update, /* update */ __curfile_remove, /* remove */ __curfile_reserve, /* reserve */ __wt_cursor_reconfigure, /* reconfigure */ __curfile_close); /* close */ WT_BTREE *btree; WT_CONFIG_ITEM cval; WT_CURSOR *cursor; WT_CURSOR_BTREE *cbt; WT_CURSOR_BULK *cbulk; WT_DECL_RET; size_t csize; WT_STATIC_ASSERT(offsetof(WT_CURSOR_BTREE, iface) == 0); cbt = NULL; btree = S2BT(session); WT_ASSERT(session, btree != NULL); csize = bulk ? sizeof(WT_CURSOR_BULK) : sizeof(WT_CURSOR_BTREE); WT_RET(__wt_calloc(session, 1, csize, &cbt)); cursor = &cbt->iface; *cursor = iface; cursor->session = &session->iface; cursor->internal_uri = btree->dhandle->name; cursor->key_format = btree->key_format; cursor->value_format = btree->value_format; cbt->btree = btree; /* * Increment the data-source's in-use counter; done now because closing * the cursor will decrement it, and all failure paths from here close * the cursor. */ __wt_cursor_dhandle_incr_use(session); if (session->dhandle->checkpoint != NULL) F_SET(cbt, WT_CBT_NO_TXN); if (bulk) { F_SET(cursor, WT_CURSTD_BULK); cbulk = (WT_CURSOR_BULK *)cbt; /* Optionally skip the validation of each bulk-loaded key. */ WT_ERR(__wt_config_gets_def( session, cfg, "skip_sort_check", 0, &cval)); WT_ERR(__wt_curbulk_init( session, cbulk, bitmap, cval.val == 0 ? 0 : 1)); } /* * Random retrieval, row-store only. * Random retrieval cursors support a limited set of methods. */ WT_ERR(__wt_config_gets_def(session, cfg, "next_random", 0, &cval)); if (cval.val != 0) { if (WT_CURSOR_RECNO(cursor)) WT_ERR_MSG(session, ENOTSUP, "next_random configuration not supported for " "column-store objects"); __wt_cursor_set_notsup(cursor); cursor->next = __wt_curfile_next_random; cursor->reset = __curfile_reset; WT_ERR(__wt_config_gets_def( session, cfg, "next_random_sample_size", 0, &cval)); if (cval.val != 0) cbt->next_random_sample_size = (u_int)cval.val; } /* Underlying btree initialization. */ __wt_btcur_open(cbt); /* * WT_CURSOR.modify supported on 'u' value formats, but the fast-path * through the btree code requires log file format changes, it's not * available in all versions. */ if (WT_STREQ(cursor->value_format, "u") && S2C(session)->compat_major >= WT_LOG_V2) cursor->modify = __curfile_modify; WT_ERR(__wt_cursor_init( cursor, cursor->internal_uri, owner, cfg, cursorp)); WT_STAT_CONN_INCR(session, cursor_create); WT_STAT_DATA_INCR(session, cursor_create); if (0) { err: /* * Our caller expects to release the data handle if we fail. * Disconnect it from the cursor before closing. */ if (session->dhandle != NULL) __wt_cursor_dhandle_decr_use(session); cbt->btree = NULL; WT_TRET(__curfile_close(cursor)); *cursorp = NULL; } return (ret); }
/* * __wt_curfile_create -- * Open a cursor for a given btree handle. */ int __wt_curfile_create(WT_SESSION_IMPL *session, WT_CURSOR *owner, const char *cfg[], WT_CURSOR **cursorp) { static WT_CURSOR iface = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, __curfile_compare, __curfile_next, __curfile_prev, __curfile_reset, __curfile_search, __curfile_search_near, __curfile_insert, __curfile_update, __curfile_remove, __curfile_close, { NULL, NULL }, /* TAILQ_ENTRY q */ 0, /* recno key */ { 0 }, /* recno raw buffer */ { NULL, 0, 0, NULL, 0 },/* WT_ITEM key */ { NULL, 0, 0, NULL, 0 },/* WT_ITEM value */ 0, /* int saved_err */ 0 /* uint32_t flags */ }; WT_BTREE *btree; WT_CONFIG_ITEM cval; WT_CURSOR *cursor; WT_CURSOR_BTREE *cbt; WT_DECL_RET; size_t csize; int bitmap, bulk; cbt = NULL; btree = session->btree; WT_ASSERT(session, btree != NULL); WT_RET(__wt_config_gets_defno(session, cfg, "bulk", &cval)); if ((cval.type == ITEM_ID || cval.type == ITEM_STRING) && WT_STRING_MATCH("bitmap", cval.str, cval.len)) bitmap = bulk = 1; else { bitmap = 0; bulk = (cval.val != 0); } csize = bulk ? sizeof(WT_CURSOR_BULK) : sizeof(WT_CURSOR_BTREE); WT_RET(__wt_calloc(session, 1, csize, &cbt)); cursor = &cbt->iface; *cursor = iface; cursor->session = &session->iface; cursor->uri = btree->name; cursor->key_format = btree->key_format; cursor->value_format = btree->value_format; cbt->btree = session->btree; if (bulk) WT_ERR(__wt_curbulk_init((WT_CURSOR_BULK *)cbt, bitmap)); /* * no_cache * No cache cursors are read-only. */ WT_ERR(__wt_config_gets_defno(session, cfg, "no_cache", &cval)); if (cval.val != 0) { cursor->insert = __wt_cursor_notsup; cursor->update = __wt_cursor_notsup; cursor->remove = __wt_cursor_notsup; } /* * random_retrieval * Random retrieval cursors only support next, reset and close. */ WT_ERR(__wt_config_gets_defno(session, cfg, "next_random", &cval)); if (cval.val != 0) { __wt_cursor_set_notsup(cursor); cursor->next = __curfile_next_random; cursor->reset = __curfile_reset; } /* __wt_cursor_init is last so we don't have to clean up on error. */ STATIC_ASSERT(offsetof(WT_CURSOR_BTREE, iface) == 0); WT_ERR(__wt_cursor_init(cursor, cursor->uri, owner, cfg, cursorp)); if (0) { err: __wt_free(session, cbt); } return (ret); }
/* * __wt_curfile_create -- * Open a cursor for a given btree handle. */ int __wt_curfile_create(WT_SESSION_IMPL *session, WT_CURSOR *owner, const char *cfg[], int bulk, int bitmap, WT_CURSOR **cursorp) { WT_CURSOR_STATIC_INIT(iface, NULL, /* get-key */ NULL, /* get-value */ NULL, /* set-key */ NULL, /* set-value */ __curfile_compare, /* compare */ __curfile_next, /* next */ __curfile_prev, /* prev */ __curfile_reset, /* reset */ __curfile_search, /* search */ __curfile_search_near, /* search-near */ __curfile_insert, /* insert */ __curfile_update, /* update */ __curfile_remove, /* remove */ __curfile_close); /* close */ WT_BTREE *btree; WT_CONFIG_ITEM cval; WT_CURSOR *cursor; WT_CURSOR_BTREE *cbt; WT_DECL_RET; size_t csize; cbt = NULL; btree = session->btree; WT_ASSERT(session, btree != NULL); csize = bulk ? sizeof(WT_CURSOR_BULK) : sizeof(WT_CURSOR_BTREE); WT_RET(__wt_calloc(session, 1, csize, &cbt)); cursor = &cbt->iface; *cursor = iface; cursor->session = &session->iface; cursor->uri = btree->name; cursor->key_format = btree->key_format; cursor->value_format = btree->value_format; cbt->btree = session->btree; if (bulk) WT_ERR(__wt_curbulk_init((WT_CURSOR_BULK *)cbt, bitmap)); /* * random_retrieval * Random retrieval cursors only support next, reset and close. */ WT_ERR(__wt_config_gets_defno(session, cfg, "next_random", &cval)); if (cval.val != 0) { __wt_cursor_set_notsup(cursor); cursor->next = __curfile_next_random; cursor->reset = __curfile_reset; } /* __wt_cursor_init is last so we don't have to clean up on error. */ STATIC_ASSERT(offsetof(WT_CURSOR_BTREE, iface) == 0); WT_ERR(__wt_cursor_init(cursor, cursor->uri, owner, cfg, cursorp)); if (0) { err: __wt_free(session, cbt); } return (ret); }