summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@wiredtiger.com>2011-03-16 13:34:56 +1100
committerMichael Cahill <michael.cahill@wiredtiger.com>2011-03-16 13:34:56 +1100
commitefa1687336ab8d5ba9df65c6f13839f4348af98d (patch)
tree2877827228654c151116a2741d65b1a4f50edb52
parentfb97386f2af9b3b7c1bb1e84e33afaf44652f659 (diff)
downloadmongo-efa1687336ab8d5ba9df65c6f13839f4348af98d.tar.gz
Fix up the public API so that ex_access runs to completion without crashing.
--HG-- extra : rebase_source : eca64ff59c4be8bcbec859c829fc3f33c888ca43
-rw-r--r--examples/c/ex_access.c4
-rw-r--r--src/api/api.c42
-rw-r--r--src/api/cur_btree.c23
-rw-r--r--src/btree/bt_close.c4
-rw-r--r--src/btree/bt_evict.c29
-rw-r--r--src/btree/bt_walk.c18
-rw-r--r--src/env/env_session.c31
-rw-r--r--src/include/api.h9
-rw-r--r--src/include/config.h2
-rw-r--r--src/include/extern.h2
10 files changed, 103 insertions, 61 deletions
diff --git a/examples/c/ex_access.c b/examples/c/ex_access.c
index cb7dfd886be..a94f3000c10 100644
--- a/examples/c/ex_access.c
+++ b/examples/c/ex_access.c
@@ -31,8 +31,8 @@ int main(void)
ret = session->create_table(session, "access",
"key_format=S,value_format=S");
- ret = session->open_cursor(session, "table:access", NULL, "overwrite",
- &cursor);
+ ret = session->open_cursor(session, "table:access",
+ NULL, NULL, &cursor);
/* Insert a record. */
cursor->set_key(cursor, "key1");
diff --git a/src/api/api.c b/src/api/api.c
index 1279f062605..be6308ec5c6 100644
--- a/src/api/api.c
+++ b/src/api/api.c
@@ -14,7 +14,7 @@
static int
__session_close(WT_SESSION *wt_session, const char *config)
{
- BTREE *btree;
+ BTREE_SESSION *btree_session;
CONNECTION *conn;
SESSION *session;
WT_CURSOR *cursor;
@@ -28,15 +28,15 @@ __session_close(WT_SESSION *wt_session, const char *config)
while ((cursor = TAILQ_FIRST(&session->cursors)) != NULL)
WT_TRET(cursor->close(cursor, config));
- while ((btree = TAILQ_FIRST(&session->btrees)) != NULL) {
- TAILQ_REMOVE(&session->btrees, btree, q);
- WT_TRET(btree->close(btree, 0));
+ while ((btree_session = TAILQ_FIRST(&session->btrees)) != NULL) {
+ TAILQ_REMOVE(&session->btrees, btree_session, q);
+ WT_TRET(btree_session->btree->close(btree_session->btree, 0));
+ __wt_free(session, btree_session);
}
+ TAILQ_REMOVE(&conn->sessions_head, session, q);
WT_TRET(__wt_session_close(session));
- TAILQ_REMOVE(&conn->sessions_head, session, q);
- __wt_free(NULL, session);
return (0);
}
@@ -79,9 +79,9 @@ __session_create_table(WT_SESSION *wt_session,
conn = (CONNECTION *)wt_session->connection;
WT_RET(conn->btree(conn, 0, &btree));
- WT_RET(btree->open(btree, name, 0, WT_CREATE));
+ WT_RET(btree->open(btree, name, 0666, WT_CREATE));
- TAILQ_INSERT_HEAD(&session->btrees, btree, q);
+ WT_RET(__wt_session_add_btree(session, btree));
return (0);
}
@@ -347,22 +347,24 @@ __conn_open_session(WT_CONNECTION *wt_conn,
SESSION *session;
int ret;
- WT_UNUSED(error_handler);
WT_UNUSED(config);
conn = (CONNECTION *)wt_conn;
- WT_RET(__wt_calloc(&conn->default_session, 1, sizeof(SESSION), &session));
+ WT_ERR(__wt_connection_session(conn, &session));
+ /*
+ * XXX
+ * Kludge while there is a separate __wt_conection_session method.
+ * We shouldn't be overwriting the connection pointer, particularly not
+ * through a static struct that is shared between threads.
+ */
+ stds.connection = wt_conn;
+ session->iface = stds;
TAILQ_INIT(&session->cursors);
TAILQ_INIT(&session->btrees);
-
- session->iface = stds;
- session->iface.connection = wt_conn;
-
- session->error_handler = (error_handler != NULL) ?
- error_handler : conn->default_session.error_handler;
-
- WT_ERR(__wt_connection_session(conn, &session));
+ WT_ASSERT(NULL, conn->default_session.error_handler != NULL);
+ if (error_handler != NULL)
+ session->error_handler = error_handler;
TAILQ_INSERT_HEAD(&conn->sessions_head, session, q);
@@ -419,10 +421,11 @@ wiredtiger_open(const char *home, WT_ERROR_HANDLER *error_handler,
/*
* !!!
- * We don't have a session handle to pass to the memory allocation
+ * We don't yet have a session handle to pass to the memory allocation
* functions.
*/
WT_RET(__wt_calloc(NULL, 1, sizeof(CONNECTION), &conn));
+ conn->iface = stdc;
WT_ERR(__wt_strdup(NULL, home, &conn->home));
TAILQ_INIT(&conn->sessions_head);
@@ -437,7 +440,6 @@ wiredtiger_open(const char *home, WT_ERROR_HANDLER *error_handler,
WT_ERR(conn->open(conn, home, 0644, 0));
STATIC_ASSERT(offsetof(CONNECTION, iface) == 0);
- conn->iface = stdc;
*wt_connp = &conn->iface;
if (0) {
diff --git a/src/api/cur_btree.c b/src/api/cur_btree.c
index 56d9d2fed59..ccaab10c2e3 100644
--- a/src/api/cur_btree.c
+++ b/src/api/cur_btree.c
@@ -137,6 +137,21 @@ __curbtree_close(WT_CURSOR *cursor, const char *config)
}
/*
+ * __add_btree --
+ * Add a btree handle to the session's cache.
+ */
+int
+__wt_session_add_btree(SESSION *session, BTREE *btree)
+{
+ BTREE_SESSION *btree_session;
+ WT_RET(__wt_calloc(session, 1, sizeof(BTREE_SESSION), &btree_session));
+ btree_session->btree = btree;
+ TAILQ_INSERT_HEAD(&session->btrees, btree_session, q);
+
+ return (0);
+}
+
+/*
* __get_btree --
* Get the btree handle for the named table.
*/
@@ -144,8 +159,10 @@ static int
__get_btree(SESSION *session, const char *name, size_t namelen, BTREE **btreep)
{
BTREE *btree;
+ BTREE_SESSION *btree_session;
- TAILQ_FOREACH(btree, &session->btrees, q) {
+ TAILQ_FOREACH(btree_session, &session->btrees, q) {
+ btree = btree_session->btree;
if (strncmp(name, btree->name, namelen) == 0 &&
btree->name[namelen] == '\0') {
*btreep = btree;
@@ -205,9 +222,9 @@ __wt_cursor_open(SESSION *session,
if (ret == WT_NOTFOUND) {
ret = 0;
WT_RET(conn->btree(conn, 0, &btree));
- WT_RET(btree->open(btree, tablename, 0, 0));
+ WT_RET(btree->open(btree, tablename, 0666, 0));
- TAILQ_INSERT_HEAD(&session->btrees, btree, q);
+ WT_RET(__wt_session_add_btree(session, btree));
} else
WT_RET(ret);
diff --git a/src/btree/bt_close.c b/src/btree/bt_close.c
index 1fed1ca6fdc..5b8ddb8474e 100644
--- a/src/btree/bt_close.c
+++ b/src/btree/bt_close.c
@@ -31,7 +31,7 @@ __wt_bt_close(SESSION *session)
* higher level API has to ensure this.
*/
if (WT_UNOPENED_FILE(btree))
- return (0);
+ goto done;
/*
* The tree walk is depth first, that is, the worker function is not
@@ -54,7 +54,7 @@ __wt_bt_close(SESSION *session)
WT_TRET(__wt_block_write(session));
/* Close the underlying file handle. */
- WT_TRET(__wt_close(session, btree->fh));
+done: WT_TRET(__wt_close(session, btree->fh));
btree->fh = NULL;
return (ret);
diff --git a/src/btree/bt_evict.c b/src/btree/bt_evict.c
index ee04c3031a7..e18db13c9be 100644
--- a/src/btree/bt_evict.c
+++ b/src/btree/bt_evict.c
@@ -99,19 +99,29 @@ void *
__wt_cache_evict_server(void *arg)
{
CONNECTION *conn;
- WT_CACHE *cache;
SESSION *session;
+ WT_CACHE *cache;
+ WT_CONNECTION *wt_conn;
uint64_t bytes_inuse, bytes_max;
int ret;
conn = arg;
+ wt_conn = &conn->iface;
cache = conn->cache;
ret = 0;
- /* We need a thread of control because we're reading/writing pages. */
- session = NULL;
- WT_ERR(__wt_session_api_set(conn,
- "CacheReconciliation", NULL, &session));
+ /*
+ * We need a thread of control because we're reading/writing pages.
+ * Start with the default session to keep error handling simple.
+ *
+ * There is some complexity involved in using the public API, because
+ * public sessions are implicitly closed during WT_CONNECTION->close.
+ * If the eviction thread's session were to go on the public list, the
+ * eviction thread would have to be shut down before the public session
+ * handles are closed.
+ */
+ session = &conn->default_session;
+ WT_ERR(__wt_connection_session(conn, &session));
/*
* Multiple pages are marked for eviction by the eviction server, which
@@ -179,14 +189,15 @@ err: if (cache->evict != NULL)
__wt_free(session, cache->evict);
if (cache->hazard != NULL)
__wt_free(session, cache->hazard);
- if (session != NULL)
- WT_TRET(session->close(session, 0));
if (ret != 0)
__wt_err(session, ret, "cache eviction server error");
- WT_VERBOSE(
- conn, WT_VERB_EVICT, (session, "cache eviction server exiting"));
+ WT_VERBOSE(conn, WT_VERB_EVICT,
+ (session, "cache eviction server exiting"));
+
+ if (session != &conn->default_session)
+ WT_TRET(__wt_session_close(session));
return (NULL);
}
diff --git a/src/btree/bt_walk.c b/src/btree/bt_walk.c
index 38bbed53a4e..c3fdd2be72d 100644
--- a/src/btree/bt_walk.c
+++ b/src/btree/bt_walk.c
@@ -181,15 +181,16 @@ __wt_walk_next(SESSION *session, WT_WALK *walk, uint32_t flags, WT_REF **refp)
page = e->ref->page;
/*
- * Coming into this function we have a tree internal page and we're
- * walking the array of children.
+ * Coming into this function we should have a tree internal page and
+ * we're walking the array of children. If page is NULL, the tree is
+ * empty.
*
* If we've reached the end of this page, and haven't yet returned it,
* do that now. If the page has been returned, traversal is finished:
* pop the stack and call ourselve recursively, unless the entire tree
* has been traversed, in which case we return NULL.
*/
- if (e->visited) {
+ if (e->visited || page == NULL) {
if (walk->tree_slot == 0) {
*refp = NULL;
return (0);
@@ -197,12 +198,11 @@ __wt_walk_next(SESSION *session, WT_WALK *walk, uint32_t flags, WT_REF **refp)
--walk->tree_slot;
return (__wt_walk_next(session, walk, flags, refp));
}
- } else
- if (e->indx == page->indx_count) {
-eop: e->visited = 1;
- *refp = e->ref;
- return (0);
- }
+ } else if (e->indx == page->indx_count) {
+eop: e->visited = 1;
+ *refp = e->ref;
+ return (0);
+ }
/*
* Check to see if the page has sub-trees associated with it, in which
diff --git a/src/env/env_session.c b/src/env/env_session.c
index 8607480d750..16f60f21c4b 100644
--- a/src/env/env_session.c
+++ b/src/env/env_session.c
@@ -19,7 +19,7 @@ __wt_connection_session(CONNECTION *conn, SESSION **sessionp)
*sessionp = NULL;
- /* Check to see if there's an available SESSION slot. */
+ /* Check to see if there's an available session slot. */
if (conn->toc_cnt == conn->session_size - 1) {
__wt_err(&conn->default_session, 0,
"WiredTiger only configured to support %d thread contexts",
@@ -28,18 +28,19 @@ __wt_connection_session(CONNECTION *conn, SESSION **sessionp)
}
/*
- * The SESSION reference list is compact, the SESSION array is not.
- * Find the first empty SESSION slot.
+ * The session reference list is compact, the session array is not.
+ * Find the first empty session slot.
*/
for (slot = 0, session = conn->toc_array;
session->iface.connection != NULL;
++session, ++slot)
;
- /* Clear previous contents of the SESSION entry, they get re-used. */
- memset(session, 0, sizeof(SESSION));
+ /* Session entries are re-used, clear the old contents. */
+ WT_CLEAR(*session);
session->iface.connection = &conn->iface;
+ session->error_handler = conn->default_session.error_handler;
session->hazard = conn->hazard + slot * conn->hazard_size;
/* We can't use the new session: it hasn't been configured yet. */
@@ -77,14 +78,14 @@ __wt_session_close(SESSION *session)
/*
* The "in" reference count is artificially incremented by 1 as
- * long as an SESSION buffer is referenced by the SESSION thread;
+ * long as a session buffer is referenced by the session thread;
* we don't want them freed because a page was evicted and their
* count went to 0. Decrement the reference count on the buffer
* as part of releasing it. There's a similar reference count
- * decrement when the SESSION structure is discarded.
+ * decrement when the session structure is discarded.
*
* XXX
- * There's a race here: if this code, or the SESSION structure
+ * There's a race here: if this code, or the session structure
* close code, and the page discard code race, it's possible
* neither will realize the buffer is no longer needed and free
* it. The fix is to involve the eviction or workQ threads:
@@ -108,9 +109,9 @@ __wt_session_close(SESSION *session)
}
/*
- * Replace the SESSION reference we're closing with the last entry in
+ * Replace the session reference we're closing with the last entry in
* the table, then clear the last entry. As far as the walk of the
- * workQ is concerned, it's OK if the SESSION appears twice, or if it
+ * workQ is concerned, it's OK if the session appears twice, or if it
* doesn't appear at all, so these lines can race all they want.
*/
for (tp = conn->sessions; *tp != session; ++tp)
@@ -119,7 +120,7 @@ __wt_session_close(SESSION *session)
*tp = conn->sessions[conn->toc_cnt];
conn->sessions[conn->toc_cnt] = NULL;
- /* Make the SESSION array entry available for re-use. */
+ /* Make the session array entry available for re-use. */
session->iface.connection = NULL;
WT_MEMORY_FLUSH;
@@ -137,10 +138,10 @@ __wt_session_api_set(
SESSION *session;
/*
- * We pass around SESSIONs internally in the Btree, (rather than a
- * BTREE), because the BTREE's are free-threaded, and the SESSIONs are
+ * We pass around sessions internally in the Btree, (rather than a
+ * BTREE), because the BTREE's are free-threaded, and the sessions are
* per-thread. Lots of the API calls don't require the application to
- * allocate and manage the SESSION, which means we have to do it for
+ * allocate and manage the session, which means we have to do it for
* them.
*
* SESSIONs always reference a BTREE handle, and we do that here, as
@@ -163,7 +164,7 @@ int
__wt_session_api_clr(SESSION *session, const char *name, int islocal)
{
/*
- * The SESSION should hold no more hazard references; this is a
+ * The session should hold no more hazard references; this is a
* diagnostic check, but it's cheap so we do it all the time.
*/
__wt_hazard_empty(session, name);
diff --git a/src/include/api.h b/src/include/api.h
index eeaaaf66382..00aafcc1bfa 100644
--- a/src/include/api.h
+++ b/src/include/api.h
@@ -7,6 +7,7 @@
/* Forward declarations of internal handle types. */
struct __btree; typedef struct __btree BTREE;
+struct __btree_session; typedef struct __btree_session BTREE_SESSION;
struct __connection; typedef struct __connection CONNECTION;
struct __session; typedef struct __session SESSION;
@@ -196,6 +197,12 @@ struct __btree {
uint32_t flags;
};
+struct __btree_session {
+ BTREE *btree;
+
+ TAILQ_ENTRY(__btree_session) q;
+};
+
/*******************************************
* Application session information
*******************************************/
@@ -214,7 +221,7 @@ struct __session {
TAILQ_ENTRY(__session) q;
TAILQ_HEAD(__cursors, wt_cursor) cursors;
- TAILQ_HEAD(__btrees, __btree) btrees;
+ TAILQ_HEAD(__btrees, __btree_session) btrees;
char err_buf[32]; /* Last-ditch error buffer */
diff --git a/src/include/config.h b/src/include/config.h
index 38f9f61b253..b3fbea8b16e 100644
--- a/src/include/config.h
+++ b/src/include/config.h
@@ -31,6 +31,8 @@ struct __wt_config_item
WT_CONFIG_ITEM __ckey; \
int __cret; \
\
+ if (cstr == NULL) \
+ break; \
WT_RET(__wt_config_init(&__conf, (cstr), strlen(cstr))); \
while ((__cret = \
__wt_config_next(&__conf, &__ckey, &(cvalue))) == 0) { \
diff --git a/src/include/extern.h b/src/include/extern.h
index 07b9e149a7d..9687516ffd3 100644
--- a/src/include/extern.h
+++ b/src/include/extern.h
@@ -24,6 +24,8 @@ __wt_config_init(WT_CONFIG *conf, const char *str, size_t len);
int
__wt_config_next(WT_CONFIG *conf, WT_CONFIG_ITEM *key, WT_CONFIG_ITEM *value);
int
+__wt_session_add_btree(SESSION *session, BTREE *btree);
+int
__wt_cursor_open(SESSION *session,
const char *uri, const char *config, WT_CURSOR **cursorp);
int