summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2017-08-03 15:29:53 +1000
committerGitHub <noreply@github.com>2017-08-03 15:29:53 +1000
commit74510affecfd4c274988a3f7b8e71448492f2103 (patch)
tree52c1f497ac75db4a65fc4cf495f45030781793d5
parentd2f2eae6d7718a53ac5bacf7141773ee0696f3c6 (diff)
downloadmongo-74510affecfd4c274988a3f7b8e71448492f2103.tar.gz
WT-3471 Sweep the table cache after schema changes. (#3551)
During WT_SESSION::reset, if there has been a schema change (such as a WT_SESSION::drop operation) since the last sweep, do a pass through the table cache and remove any obsolete table handles.
-rw-r--r--src/include/extern.h1
-rw-r--r--src/include/session.h6
-rw-r--r--src/schema/schema_list.c31
-rw-r--r--src/session/session_api.c2
4 files changed, 40 insertions, 0 deletions
diff --git a/src/include/extern.h b/src/include/extern.h
index bf3279d0f94..dfd2d03707f 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -570,6 +570,7 @@ extern int __wt_schema_destroy_index(WT_SESSION_IMPL *session, WT_INDEX **idxp)
extern int __wt_schema_destroy_table(WT_SESSION_IMPL *session, WT_TABLE **tablep) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_schema_remove_table(WT_SESSION_IMPL *session, WT_TABLE *table) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_schema_close_tables(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
+extern int __wt_schema_sweep_tables(WT_SESSION_IMPL *session) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_schema_colgroup_name(WT_SESSION_IMPL *session, WT_TABLE *table, const char *cgname, size_t len, WT_ITEM *buf) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_schema_open_colgroups(WT_SESSION_IMPL *session, WT_TABLE *table) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
extern int __wt_schema_open_index(WT_SESSION_IMPL *session, WT_TABLE *table, const char *idxname, size_t len, WT_INDEX **indexp) WT_GCC_FUNC_DECL_ATTRIBUTE((warn_unused_result));
diff --git a/src/include/session.h b/src/include/session.h
index 0074b4a9d43..d05dee68641 100644
--- a/src/include/session.h
+++ b/src/include/session.h
@@ -98,6 +98,12 @@ struct __wt_session_impl {
*/
TAILQ_HEAD(__tables, __wt_table) tables;
+ /*
+ * Updated when the table cache is swept of all tables older than the
+ * current schema generation.
+ */
+ uint64_t table_sweep_gen;
+
/* Current rwlock for callback. */
WT_RWLOCK *current_rwlock;
uint8_t current_rwticket;
diff --git a/src/schema/schema_list.c b/src/schema/schema_list.c
index 74ef5135a4a..3dc51b6cb43 100644
--- a/src/schema/schema_list.c
+++ b/src/schema/schema_list.c
@@ -249,3 +249,34 @@ __wt_schema_close_tables(WT_SESSION_IMPL *session)
WT_TRET(__wt_schema_remove_table(session, table));
return (ret);
}
+
+/*
+ * __wt_schema_sweep_tables --
+ * Close all idle, obsolete tables in a session.
+ */
+int
+__wt_schema_sweep_tables(WT_SESSION_IMPL *session)
+{
+ WT_TABLE *table, *next;
+ uint64_t schema_gen;
+ bool old_table_busy;
+
+ WT_ORDERED_READ(schema_gen, S2C(session)->schema_gen);
+ if (schema_gen == session->table_sweep_gen)
+ return (0);
+
+ old_table_busy = false;
+ TAILQ_FOREACH_SAFE(table, &session->tables, q, next)
+ if (table->schema_gen != schema_gen) {
+ if (table->refcnt == 0)
+ WT_RET(__wt_schema_remove_table(
+ session, table));
+ else
+ old_table_busy = true;
+ }
+
+ if (!old_table_busy)
+ session->table_sweep_gen = schema_gen;
+
+ return (0);
+}
diff --git a/src/session/session_api.c b/src/session/session_api.c
index 89a5a2c633d..5ce6135cfca 100644
--- a/src/session/session_api.c
+++ b/src/session/session_api.c
@@ -818,6 +818,8 @@ __session_reset(WT_SESSION *wt_session)
WT_TRET(__wt_session_reset_cursors(session, true));
+ WT_TRET(__wt_schema_sweep_tables(session));
+
/* Release common session resources. */
WT_TRET(__wt_session_release_resources(session));