diff options
author | Keith Bostic <keith@wiredtiger.com> | 2012-03-10 13:53:53 -0500 |
---|---|---|
committer | Keith Bostic <keith@wiredtiger.com> | 2012-03-10 13:53:53 -0500 |
commit | ab450e3d58490df0515b00f284e2ba0cd1b1bfab (patch) | |
tree | 7c057a46eebf39ffd85df1ca4a50b56302fcce1f | |
parent | aec33706bb1e8ba210322be9ac4dbfd1eb77a390 (diff) | |
download | mongo-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.c | 72 |
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); } |