diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/meta/meta_table.c')
-rw-r--r-- | src/third_party/wiredtiger/src/meta/meta_table.c | 141 |
1 files changed, 91 insertions, 50 deletions
diff --git a/src/third_party/wiredtiger/src/meta/meta_table.c b/src/third_party/wiredtiger/src/meta/meta_table.c index e7074a9c1b5..9938cb07a5c 100644 --- a/src/third_party/wiredtiger/src/meta/meta_table.c +++ b/src/third_party/wiredtiger/src/meta/meta_table.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2014-2015 MongoDB, Inc. + * Copyright (c) 2014-2016 MongoDB, Inc. * Copyright (c) 2008-2014 WiredTiger, Inc. * All rights reserved. * @@ -31,21 +31,28 @@ __metadata_turtle(const char *key) } /* - * __wt_metadata_open -- - * Opens the metadata file, sets session->meta_dhandle. + * __wt_metadata_cursor_open -- + * Opens a cursor on the metadata. */ int -__wt_metadata_open(WT_SESSION_IMPL *session) +__wt_metadata_cursor_open( + WT_SESSION_IMPL *session, const char *config, WT_CURSOR **cursorp) { WT_BTREE *btree; + WT_DECL_RET; + const char *open_cursor_cfg[] = { + WT_CONFIG_BASE(session, WT_SESSION_open_cursor), config, NULL }; - if (session->meta_dhandle != NULL) - return (0); - - WT_RET(__wt_session_get_btree(session, WT_METAFILE_URI, NULL, NULL, 0)); + WT_WITHOUT_DHANDLE(session, ret = __wt_open_cursor( + session, WT_METAFILE_URI, NULL, open_cursor_cfg, cursorp)); + WT_RET(ret); - session->meta_dhandle = session->dhandle; - WT_ASSERT(session, session->meta_dhandle != NULL); + /* + * Retrieve the btree from the cursor, rather than the session because + * we don't always switch the metadata handle in to the session before + * entering this function. + */ + btree = ((WT_CURSOR_BTREE *)(*cursorp))->btree; /* * Set special flags for the metadata file: eviction (the metadata file @@ -56,7 +63,6 @@ __wt_metadata_open(WT_SESSION_IMPL *session) * opens (the first update is safe because it's single-threaded from * wiredtiger_open). */ - btree = S2BT(session); if (!F_ISSET(btree, WT_BTREE_IN_MEMORY)) F_SET(btree, WT_BTREE_IN_MEMORY); if (!F_ISSET(btree, WT_BTREE_NO_EVICTION)) @@ -64,44 +70,81 @@ __wt_metadata_open(WT_SESSION_IMPL *session) if (F_ISSET(btree, WT_BTREE_NO_LOGGING)) F_CLR(btree, WT_BTREE_NO_LOGGING); - /* The metadata handle doesn't need to stay locked -- release it. */ - return (__wt_session_release_btree(session)); + return (0); } /* * __wt_metadata_cursor -- - * Opens a cursor on the metadata. + * Returns the session's cached metadata cursor, unless it's in use, in + * which case it opens and returns another metadata cursor. */ int -__wt_metadata_cursor( - WT_SESSION_IMPL *session, const char *config, WT_CURSOR **cursorp) +__wt_metadata_cursor(WT_SESSION_IMPL *session, WT_CURSOR **cursorp) { - WT_DATA_HANDLE *saved_dhandle; - WT_DECL_RET; - bool is_dead; - const char *cfg[] = - { WT_CONFIG_BASE(session, WT_SESSION_open_cursor), config, NULL }; + WT_CURSOR *cursor; - saved_dhandle = session->dhandle; - WT_ERR(__wt_metadata_open(session)); + /* + * If we don't have a cached metadata cursor, or it's already in use, + * we'll need to open a new one. + */ + cursor = NULL; + if (session->meta_cursor == NULL || + F_ISSET(session->meta_cursor, WT_CURSTD_META_INUSE)) { + WT_RET(__wt_metadata_cursor_open(session, NULL, &cursor)); + if (session->meta_cursor == NULL) { + session->meta_cursor = cursor; + cursor = NULL; + } + } - session->dhandle = session->meta_dhandle; + /* + * If there's no cursor return, we're done, our caller should have just + * been triggering the creation of the session's cached cursor. There + * should not be an open local cursor in that case, but caution doesn't + * cost anything. + */ + if (cursorp == NULL) + return (cursor == NULL ? 0 : cursor->close(cursor)); - /* - * We use the metadata a lot, so we have a handle cached; lock it and - * increment the in-use counter once the cursor is open. + /* + * If the cached cursor is in use, return the newly opened cursor, else + * mark the cached cursor in use and return it. */ - WT_ERR(__wt_session_lock_dhandle(session, 0, &is_dead)); + if (F_ISSET(session->meta_cursor, WT_CURSTD_META_INUSE)) + *cursorp = cursor; + else { + *cursorp = session->meta_cursor; + F_SET(session->meta_cursor, WT_CURSTD_META_INUSE); + } + return (0); +} - /* The metadata should never be closed. */ - WT_ASSERT(session, !is_dead); +/* + * __wt_metadata_cursor_release -- + * Release a metadata cursor. + */ +int +__wt_metadata_cursor_release(WT_SESSION_IMPL *session, WT_CURSOR **cursorp) +{ + WT_CURSOR *cursor; - WT_ERR(__wt_curfile_create(session, NULL, cfg, false, false, cursorp)); - __wt_cursor_dhandle_incr_use(session); + WT_UNUSED(session); - /* Restore the caller's btree. */ -err: session->dhandle = saved_dhandle; - return (ret); + if ((cursor = *cursorp) == NULL) + return (0); + *cursorp = NULL; + + /* + * If using the session's cached metadata cursor, clear the in-use flag + * and reset it, otherwise, discard the cursor. + */ + if (F_ISSET(cursor, WT_CURSTD_META_INUSE)) { + WT_ASSERT(session, cursor == session->meta_cursor); + + F_CLR(cursor, WT_CURSTD_META_INUSE); + return (cursor->reset(cursor)); + } + return (cursor->close(cursor)); } /* @@ -124,14 +167,13 @@ __wt_metadata_insert( WT_RET_MSG(session, EINVAL, "%s: insert not supported on the turtle file", key); - WT_RET(__wt_metadata_cursor(session, NULL, &cursor)); + WT_RET(__wt_metadata_cursor(session, &cursor)); cursor->set_key(cursor, key); cursor->set_value(cursor, value); WT_ERR(cursor->insert(cursor)); if (WT_META_TRACKING(session)) WT_ERR(__wt_meta_track_insert(session, key)); - -err: WT_TRET(cursor->close(cursor)); +err: WT_TRET(__wt_metadata_cursor_release(session, &cursor)); return (ret); } @@ -152,7 +194,7 @@ __wt_metadata_update( __metadata_turtle(key) ? "" : "not ")); if (__metadata_turtle(key)) { - WT_WITH_TURTLE_LOCK(session, + WT_WITH_TURTLE_LOCK(session, ret, ret = __wt_turtle_update(session, key, value)); return (ret); } @@ -160,12 +202,14 @@ __wt_metadata_update( if (WT_META_TRACKING(session)) WT_RET(__wt_meta_track_update(session, key)); - WT_RET(__wt_metadata_cursor(session, "overwrite", &cursor)); + WT_RET(__wt_metadata_cursor(session, &cursor)); + /* This cursor needs to have overwrite semantics. */ + WT_ASSERT(session, F_ISSET(cursor, WT_CURSTD_OVERWRITE)); + cursor->set_key(cursor, key); cursor->set_value(cursor, value); WT_ERR(cursor->insert(cursor)); - -err: WT_TRET(cursor->close(cursor)); +err: WT_TRET(__wt_metadata_cursor_release(session, &cursor)); return (ret); } @@ -188,14 +232,13 @@ __wt_metadata_remove(WT_SESSION_IMPL *session, const char *key) WT_RET_MSG(session, EINVAL, "%s: remove not supported on the turtle file", key); - WT_RET(__wt_metadata_cursor(session, NULL, &cursor)); + WT_RET(__wt_metadata_cursor(session, &cursor)); cursor->set_key(cursor, key); WT_ERR(cursor->search(cursor)); if (WT_META_TRACKING(session)) WT_ERR(__wt_meta_track_update(session, key)); WT_ERR(cursor->remove(cursor)); - -err: WT_TRET(cursor->close(cursor)); +err: WT_TRET(__wt_metadata_cursor_release(session, &cursor)); return (ret); } @@ -205,8 +248,7 @@ err: WT_TRET(cursor->close(cursor)); * The caller is responsible for freeing the allocated memory. */ int -__wt_metadata_search( - WT_SESSION_IMPL *session, const char *key, char **valuep) +__wt_metadata_search(WT_SESSION_IMPL *session, const char *key, char **valuep) { WT_CURSOR *cursor; WT_DECL_RET; @@ -230,7 +272,7 @@ __wt_metadata_search( * Metadata updates use non-transactional techniques (such as the * schema and metadata locks) to protect access to in-flight updates. */ - WT_RET(__wt_metadata_cursor(session, NULL, &cursor)); + WT_RET(__wt_metadata_cursor(session, &cursor)); cursor->set_key(cursor, key); WT_WITH_TXN_ISOLATION(session, WT_ISO_READ_UNCOMMITTED, ret = cursor->search(cursor)); @@ -238,7 +280,6 @@ __wt_metadata_search( WT_ERR(cursor->get_value(cursor, &value)); WT_ERR(__wt_strdup(session, value, valuep)); - -err: WT_TRET(cursor->close(cursor)); +err: WT_TRET(__wt_metadata_cursor_release(session, &cursor)); return (ret); } |