diff options
author | Michael Cahill <michael.cahill@wiredtiger.com> | 2011-03-16 13:34:56 +1100 |
---|---|---|
committer | Michael Cahill <michael.cahill@wiredtiger.com> | 2011-03-16 13:34:56 +1100 |
commit | efa1687336ab8d5ba9df65c6f13839f4348af98d (patch) | |
tree | 2877827228654c151116a2741d65b1a4f50edb52 | |
parent | fb97386f2af9b3b7c1bb1e84e33afaf44652f659 (diff) | |
download | mongo-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.c | 4 | ||||
-rw-r--r-- | src/api/api.c | 42 | ||||
-rw-r--r-- | src/api/cur_btree.c | 23 | ||||
-rw-r--r-- | src/btree/bt_close.c | 4 | ||||
-rw-r--r-- | src/btree/bt_evict.c | 29 | ||||
-rw-r--r-- | src/btree/bt_walk.c | 18 | ||||
-rw-r--r-- | src/env/env_session.c | 31 | ||||
-rw-r--r-- | src/include/api.h | 9 | ||||
-rw-r--r-- | src/include/config.h | 2 | ||||
-rw-r--r-- | src/include/extern.h | 2 |
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 |