summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Bostic <keith@wiredtiger.com>2012-03-10 13:53:53 -0500
committerKeith Bostic <keith@wiredtiger.com>2012-03-10 13:53:53 -0500
commitab450e3d58490df0515b00f284e2ba0cd1b1bfab (patch)
tree7c057a46eebf39ffd85df1ca4a50b56302fcce1f
parentaec33706bb1e8ba210322be9ac4dbfd1eb77a390 (diff)
downloadmongo-ab450e3d58490df0515b00f284e2ba0cd1b1bfab.tar.gz
Changes for issue #178.
Close/discard all of the files but the schema file first, because writing those files may result in updates to the schema file. Updating the schema file may add the schema table to the session's list of btrees: we're about to discard the underlying schema table file object, so manually clear that list before closing the last file and discarding the session handle.
-rw-r--r--src/conn/conn_btree.c72
1 files changed, 57 insertions, 15 deletions
diff --git a/src/conn/conn_btree.c b/src/conn/conn_btree.c
index 99e1b22247c..55fb4ef6f4d 100644
--- a/src/conn/conn_btree.c
+++ b/src/conn/conn_btree.c
@@ -155,6 +155,29 @@ __wt_conn_close_btree(WT_SESSION_IMPL *session)
}
/*
+ * __conn_btree_remove --
+ * Discard a single btree file handle structure.
+ */
+static int
+__conn_btree_remove(WT_SESSION_IMPL *session, WT_BTREE *btree)
+{
+ int ret;
+
+ ret = 0;
+
+ WT_SET_BTREE_IN_SESSION(session, btree);
+ WT_TRET(__wt_btree_close(session));
+ WT_TRET(__wt_rwlock_destroy(session, btree->rwlock));
+ __wt_free(session, btree->filename);
+ __wt_free(session, btree->name);
+ __wt_free(session, btree->config);
+ __wt_free(session, btree);
+ WT_CLEAR_BTREE_IN_SESSION(session);
+
+ return (ret);
+}
+
+/*
* __wt_conn_remove_btree --
* Discard the btree file handle structures.
*/
@@ -162,36 +185,55 @@ int
__wt_conn_remove_btree(WT_CONNECTION_IMPL *conn)
{
WT_BTREE *btree;
+ WT_BTREE_SESSION *btree_session;
WT_SESSION_IMPL *session;
int ret;
ret = 0;
/*
- * Close open btree handles.
- *
* We need a session handle because we're potentially reading/writing
- * pages. Start with the default session to keep error handling simple.
+ * pages.
*/
- session = &conn->default_session;
WT_RET(__wt_open_session(conn, 1, NULL, NULL, &session));
- while ((btree = TAILQ_FIRST(&conn->btqh)) != NULL) {
+ /*
+ * Close open btree handles: first, everything but the schema file (as
+ * closing a normal file may open and write the schema file), then the
+ * schema file. This function isn't called often, and I don't want to
+ * "know" anything about the schema file's position on the list, so we
+ * do it the hard way.
+ */
+restart:
+ TAILQ_FOREACH(btree, &conn->btqh, q) {
+ if (strcmp(btree->filename, WT_SCHEMA_FILENAME) == 0)
+ continue;
+
TAILQ_REMOVE(&conn->btqh, btree, q);
--conn->btqcnt;
+ WT_TRET(__conn_btree_remove(session, btree));
+ goto restart;
+ }
- WT_SET_BTREE_IN_SESSION(session, btree);
- WT_TRET(__wt_btree_close(session));
- F_CLR(btree, WT_BTREE_OPEN);
+ /*
+ * Closing the files may have resulted in entries on our session's list
+ * of open btree handles, specifically, we added the schema file if any
+ * of the files were dirty. Clean up that list before we shut down the
+ * schema file entry, for good.
+ */
+ while ((btree_session = TAILQ_FIRST(&session->btrees)) != NULL)
+ WT_TRET(__wt_session_remove_btree(session, btree_session));
- WT_TRET(__wt_rwlock_destroy(session, btree->rwlock));
- __wt_free(session, btree->filename);
- __wt_free(session, btree->name);
- __wt_free(session, btree->config);
- __wt_free(session, session->btree);
+ /* Close the schema file handle. */
+ while ((btree = TAILQ_FIRST(&conn->btqh)) != NULL) {
+ TAILQ_REMOVE(&conn->btqh, btree, q);
+ --conn->btqcnt;
+ WT_TRET(__conn_btree_remove(session, btree));
}
- if (session != &conn->default_session)
- (void)session->iface.close(&session->iface, NULL);
+
+ /* Discard our session. */
+ WT_TRET(session->iface.close(&session->iface, NULL));
+
return (ret);
}