diff options
Diffstat (limited to 'src/third_party/wiredtiger/src/session/session_dhandle.c')
-rw-r--r-- | src/third_party/wiredtiger/src/session/session_dhandle.c | 85 |
1 files changed, 43 insertions, 42 deletions
diff --git a/src/third_party/wiredtiger/src/session/session_dhandle.c b/src/third_party/wiredtiger/src/session/session_dhandle.c index 0825f783ca3..ce5f95a40d0 100644 --- a/src/third_party/wiredtiger/src/session/session_dhandle.c +++ b/src/third_party/wiredtiger/src/session/session_dhandle.c @@ -47,7 +47,7 @@ __session_add_dhandle( * the schema lock. */ int -__wt_session_lock_dhandle(WT_SESSION_IMPL *session, uint32_t flags) +__wt_session_lock_dhandle(WT_SESSION_IMPL *session, uint32_t flags, int *deadp) { enum { NOLOCK, READLOCK, WRITELOCK } locked; WT_BTREE *btree; @@ -57,6 +57,8 @@ __wt_session_lock_dhandle(WT_SESSION_IMPL *session, uint32_t flags) btree = S2BT(session); dhandle = session->dhandle; locked = NOLOCK; + if (deadp != NULL) + *deadp = 0; /* * Special operation flags will cause the handle to be reopened. @@ -95,7 +97,10 @@ __wt_session_lock_dhandle(WT_SESSION_IMPL *session, uint32_t flags) * required, we're done. Otherwise, check that the handle is open and * that no special flags are required. */ - if (LF_ISSET(WT_DHANDLE_LOCK_ONLY) || + if (F_ISSET(dhandle, WT_DHANDLE_DEAD)) { + WT_ASSERT(session, deadp != NULL); + *deadp = 1; + } else if (LF_ISSET(WT_DHANDLE_LOCK_ONLY) || (F_ISSET(dhandle, WT_DHANDLE_OPEN) && special_flags == 0)) return (0); @@ -135,46 +140,25 @@ __wt_session_release_btree(WT_SESSION_IMPL *session) dhandle = session->dhandle; locked = F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE) ? WRITELOCK : READLOCK; - if (F_ISSET(dhandle, WT_DHANDLE_DISCARD_CLOSE)) { - /* - * If configured to discard on last close, trade any read lock - * for an exclusive lock. If the exchange succeeds, setup for - * discard. It is expected acquiring an exclusive lock will fail - * sometimes since the handle may still be in use: in that case - * we're done. - */ - if (locked == READLOCK) { - locked = NOLOCK; - WT_ERR(__wt_readunlock(session, dhandle->rwlock)); - ret = __wt_try_writelock(session, dhandle->rwlock); - if (ret != 0) { - if (ret == EBUSY) - ret = 0; - goto err; - } - locked = WRITELOCK; - F_CLR(dhandle, WT_DHANDLE_DISCARD_CLOSE); - F_SET(dhandle, - WT_DHANDLE_DISCARD | WT_DHANDLE_EXCLUSIVE); - } - } - /* * If we had special flags set, close the handle so that future access * can get a handle without special flags. */ - if (F_ISSET(dhandle, WT_DHANDLE_DISCARD) || + if (F_ISSET(dhandle, WT_DHANDLE_DISCARD_FORCE)) { + WT_WITH_DHANDLE_LOCK(session, + ret = __wt_conn_btree_sync_and_close(session, 0, 1)); + F_CLR(dhandle, WT_DHANDLE_DISCARD_FORCE); + } else if (F_ISSET(dhandle, WT_DHANDLE_DISCARD) || F_ISSET(btree, WT_BTREE_SPECIAL_FLAGS)) { WT_ASSERT(session, F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE)); + ret = __wt_conn_btree_sync_and_close(session, 0, 0); F_CLR(dhandle, WT_DHANDLE_DISCARD); - - WT_TRET(__wt_conn_btree_sync_and_close(session, 0, 0)); } if (F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE)) F_CLR(dhandle, WT_DHANDLE_EXCLUSIVE); -err: switch (locked) { + switch (locked) { case NOLOCK: break; case READLOCK: @@ -312,7 +296,8 @@ __session_dhandle_sweep(WT_SESSION_IMPL *session) dhandle = dhandle_cache->dhandle; if (dhandle != session->dhandle && dhandle->session_inuse == 0 && - now - dhandle->timeofdeath > conn->sweep_idle_time) { + (F_ISSET(dhandle, WT_DHANDLE_DEAD) || + now - dhandle->timeofdeath > conn->sweep_idle_time)) { WT_STAT_FAST_CONN_INCR(session, dh_session_handles); __session_discard_btree(session, dhandle_cache); } @@ -348,6 +333,7 @@ __wt_session_get_btree(WT_SESSION_IMPL *session, WT_DATA_HANDLE_CACHE *dhandle_cache; WT_DECL_RET; uint64_t bucket; + int is_dead; WT_ASSERT(session, !F_ISSET(session, WT_SESSION_NO_DATA_HANDLES)); WT_ASSERT(session, !LF_ISSET(WT_DHANDLE_HAVE_REF)); @@ -381,7 +367,8 @@ __wt_session_get_btree(WT_SESSION_IMPL *session, if (dhandle != NULL) { /* Try to lock the handle; if this succeeds, we're done. */ - if ((ret = __wt_session_lock_dhandle(session, flags)) == 0) + if ((ret = + __wt_session_lock_dhandle(session, flags, &is_dead)) == 0) goto done; /* Propagate errors we don't expect. */ @@ -389,17 +376,23 @@ __wt_session_get_btree(WT_SESSION_IMPL *session, return (ret); /* - * Don't try harder to get the btree handle if our caller - * hasn't allowed us to take the schema lock - they do so on - * purpose and will handle error returns. + * Don't try harder to get the handle if we're only checking + * for locks or our caller hasn't allowed us to take the schema + * lock - they do so on purpose and will handle error returns. */ - if (!F_ISSET(session, WT_SESSION_SCHEMA_LOCKED) && + if ((LF_ISSET(WT_DHANDLE_LOCK_ONLY) && ret == EBUSY) || + (!F_ISSET(session, WT_SESSION_SCHEMA_LOCKED) && F_ISSET(session, - WT_SESSION_HANDLE_LIST_LOCKED | WT_SESSION_TABLE_LOCKED)) + WT_SESSION_HANDLE_LIST_LOCKED | WT_SESSION_TABLE_LOCKED))) return (ret); - /* We found the data handle, don't try to get it again. */ - LF_SET(WT_DHANDLE_HAVE_REF); + /* If we found the handle and it isn't dead, reopen it. */ + if (is_dead) { + __session_discard_btree(session, dhandle_cache); + dhandle_cache = NULL; + session->dhandle = dhandle = NULL; + } else + LF_SET(WT_DHANDLE_HAVE_REF); } /* @@ -419,11 +412,11 @@ __wt_session_get_btree(WT_SESSION_IMPL *session, WT_RET(__session_add_dhandle(session, NULL)); WT_ASSERT(session, LF_ISSET(WT_DHANDLE_LOCK_ONLY) || - F_ISSET(session->dhandle, WT_DHANDLE_OPEN)); + (F_ISSET(session->dhandle, WT_DHANDLE_OPEN) && + !F_ISSET(session->dhandle, WT_DHANDLE_DEAD))); done: WT_ASSERT(session, LF_ISSET(WT_DHANDLE_EXCLUSIVE) == F_ISSET(session->dhandle, WT_DHANDLE_EXCLUSIVE)); - F_SET(session->dhandle, LF_ISSET(WT_DHANDLE_DISCARD_CLOSE)); return (0); } @@ -438,9 +431,18 @@ __wt_session_lock_checkpoint(WT_SESSION_IMPL *session, const char *checkpoint) WT_DATA_HANDLE *dhandle, *saved_dhandle; WT_DECL_RET; + WT_ASSERT(session, WT_META_TRACKING(session)); saved_dhandle = session->dhandle; /* + * If we already have the checkpoint locked, don't attempt to lock + * it again. + */ + if ((ret = __wt_meta_track_find_handle( + session, saved_dhandle->name, checkpoint)) != WT_NOTFOUND) + return (ret); + + /* * Get the checkpoint handle exclusive, so no one else can access it * while we are creating the new checkpoint. */ @@ -463,7 +465,6 @@ __wt_session_lock_checkpoint(WT_SESSION_IMPL *session, const char *checkpoint) dhandle = session->dhandle; F_SET(dhandle, WT_DHANDLE_DISCARD); - WT_ASSERT(session, WT_META_TRACKING(session)); WT_ERR(__wt_meta_track_handle_lock(session, 0)); /* Restore the original btree in the session. */ |