/* * __wt_exclusive_handle_operation -- * Get exclusive access to a file and apply a function. */ int __wt_exclusive_handle_operation(WT_SESSION_IMPL *session, const char *uri, int (*file_func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[], uint32_t open_flags) { WT_DECL_RET; /* * If the operation requires exclusive access, close * any open file handles, including checkpoints. */ if (FLD_ISSET(open_flags, WT_DHANDLE_EXCLUSIVE)) { WT_WITH_HANDLE_LIST_WRITE_LOCK(session, ret = __wt_conn_dhandle_close_all( session, uri, false, false)); WT_RET(ret); } WT_RET(__wt_session_get_btree_ckpt(session, uri, cfg, open_flags)); WT_SAVE_DHANDLE(session, ret = file_func(session, cfg)); WT_TRET(__wt_session_release_dhandle(session)); return (ret); }
/* * __conn_btree_apply_internal -- * Apply a function to the open btree handles. */ static int __conn_btree_apply_internal(WT_SESSION_IMPL *session, WT_DATA_HANDLE *dhandle, int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[]) { WT_DECL_RET; /* * We need to pull the handle into the session handle cache and make * sure it's referenced to stop other internal code dropping the handle * (e.g in LSM when cleaning up obsolete chunks). */ ret = __wt_session_get_btree(session, dhandle->name, dhandle->checkpoint, NULL, 0); if (ret == 0) { WT_SAVE_DHANDLE(session, ret = func(session, cfg)); if (WT_META_TRACKING(session)) WT_TRET(__wt_meta_track_handle_lock(session, 0)); else WT_TRET(__wt_session_release_btree(session)); } else if (ret == EBUSY) ret = __wt_conn_btree_apply_single(session, dhandle->name, dhandle->checkpoint, func, cfg); return (ret); }
/* * __meta_btree_apply -- * Apply a function to all files listed in the metadata, apart from the * metadata file. */ static inline int __meta_btree_apply(WT_SESSION_IMPL *session, WT_CURSOR *cursor, int (*file_func)(WT_SESSION_IMPL *, const char *[]), int (*name_func)(WT_SESSION_IMPL *, const char *, bool *), const char *cfg[]) { WT_DECL_RET; int t_ret; const char *uri; bool skip; /* * Accumulate errors but continue through to the end of the metadata. */ while ((t_ret = cursor->next(cursor)) == 0) { if ((t_ret = cursor->get_key(cursor, &uri)) != 0 || strcmp(uri, WT_METAFILE_URI) == 0) { WT_TRET(t_ret); continue; } skip = false; if (name_func != NULL && (t_ret = name_func(session, uri, &skip)) != 0) { WT_TRET(t_ret); continue; } if (file_func == NULL || skip || !WT_PREFIX_MATCH(uri, "file:")) continue; /* * We need to pull the handle into the session handle cache * and make sure it's referenced to stop other internal code * dropping the handle (e.g in LSM when cleaning up obsolete * chunks). Holding the schema lock isn't enough. * * Handles that are busy are skipped without the whole * operation failing. This deals among other cases with * checkpoint encountering handles that are locked (e.g., for * bulk loads or verify operations). */ if ((t_ret = __wt_session_get_dhandle( session, uri, NULL, NULL, 0)) != 0) { WT_TRET_BUSY_OK(t_ret); continue; } WT_SAVE_DHANDLE(session, WT_TRET(file_func(session, cfg))); WT_TRET(__wt_session_release_dhandle(session)); } WT_TRET_NOTFOUND_OK(t_ret); return (ret); }
/* * __wt_meta_btree_apply -- * Apply a function to all files listed in the metadata, apart from the * metadata file. */ int __wt_meta_btree_apply(WT_SESSION_IMPL *session, int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[]) { WT_CURSOR *cursor; WT_DECL_RET; WT_RET(__wt_metadata_cursor(session, &cursor)); WT_SAVE_DHANDLE(session, ret = __meta_btree_apply(session, cursor, func, cfg)); WT_TRET(__wt_metadata_cursor_release(session, &cursor)); return (ret); }
/* * __wt_meta_btree_apply -- * Apply a function to all files listed in the metadata, apart from the * metadata file. */ int __wt_meta_btree_apply(WT_SESSION_IMPL *session, int (*func)(WT_SESSION_IMPL *, const char *[]), const char *cfg[]) { WT_CURSOR *cursor; WT_DATA_HANDLE *saved_dhandle; WT_DECL_RET; const char *uri; int cmp, tret; saved_dhandle = session->dhandle; WT_RET(__wt_metadata_cursor(session, NULL, &cursor)); cursor->set_key(cursor, "file:"); if ((tret = cursor->search_near(cursor, &cmp)) == 0 && cmp < 0) tret = cursor->next(cursor); for (; tret == 0; tret = cursor->next(cursor)) { WT_ERR(cursor->get_key(cursor, &uri)); if (!WT_PREFIX_MATCH(uri, "file:")) break; else if (strcmp(uri, WT_METAFILE_URI) == 0) continue; /* * We need to pull the handle into the session handle cache * and make sure it's referenced to stop other internal code * dropping the handle (e.g in LSM when cleaning up obsolete * chunks). Holding the metadata lock isn't enough. */ ret = __wt_session_get_btree(session, uri, NULL, NULL, 0); if (ret == 0) { WT_SAVE_DHANDLE(session, ret = func(session, cfg)); if (WT_META_TRACKING(session)) WT_TRET( __wt_meta_track_handle_lock(session, 0)); else WT_TRET(__wt_session_release_btree(session)); } else if (ret == EBUSY) ret = __wt_conn_btree_apply_single( session, uri, NULL, func, cfg); WT_ERR(ret); } if (tret != WT_NOTFOUND) WT_TRET(tret); err: WT_TRET(cursor->close(cursor)); session->dhandle = saved_dhandle; return (ret); }
/* * __wt_meta_apply_all -- * Apply a function to all files listed in the metadata, apart from the * metadata file. */ int __wt_meta_apply_all(WT_SESSION_IMPL *session, int (*file_func)(WT_SESSION_IMPL *, const char *[]), int (*name_func)(WT_SESSION_IMPL *, const char *, bool *), const char *cfg[]) { WT_CURSOR *cursor; WT_DECL_RET; WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_SCHEMA)); WT_RET(__wt_metadata_cursor(session, &cursor)); WT_SAVE_DHANDLE(session, ret = __meta_btree_apply(session, cursor, file_func, name_func, cfg)); WT_TRET(__wt_metadata_cursor_release(session, &cursor)); return (ret); }
/* * __meta_btree_apply -- * Apply a function to all files listed in the metadata, apart from the * metadata file. */ static inline int __meta_btree_apply(WT_SESSION_IMPL *session, WT_CURSOR *cursor, int (*file_func)(WT_SESSION_IMPL *, const char *[]), int (*name_func)(WT_SESSION_IMPL *, const char *, bool *), const char *cfg[]) { WT_DECL_RET; const char *uri; bool skip; while ((ret = cursor->next(cursor)) == 0) { WT_RET(cursor->get_key(cursor, &uri)); if (strcmp(uri, WT_METAFILE_URI) == 0) continue; skip = false; if (name_func != NULL) WT_RET(name_func(session, uri, &skip)); if (file_func == NULL || skip || !WT_PREFIX_MATCH(uri, "file:")) continue; /* * We need to pull the handle into the session handle cache * and make sure it's referenced to stop other internal code * dropping the handle (e.g in LSM when cleaning up obsolete * chunks). Holding the metadata lock isn't enough. */ if ((ret = __wt_session_get_btree( session, uri, NULL, NULL, 0)) != 0) return (ret == EBUSY ? 0 : ret); WT_SAVE_DHANDLE(session, ret = file_func(session, cfg)); WT_TRET(__wt_session_release_btree(session)); WT_RET(ret); } WT_RET_NOTFOUND_OK(ret); return (0); }