From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Kirill Yukhin Subject: [PATCH v2 2/4] schema: add space names cache Date: Thu, 25 Oct 2018 11:17:10 +0300 Message-Id: <66ba0680f60b962be5b810474761e660c248d9b7.1540388902.git.kyukhin@tarantool.org> In-Reply-To: References: In-Reply-To: References: To: vdavydov.dev@gmail.com Cc: tarantool-patches@freelists.org, Kirill Yukhin List-ID: Since SQL is heavily using name -> space mapping, introduce (instead of scanning _space space) dedicated cache, which maps space name to space pointer. --- src/box/schema.cc | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/box/schema.h | 8 ++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/box/schema.cc b/src/box/schema.cc index 08457a46..b931fdf 100644 --- a/src/box/schema.cc +++ b/src/box/schema.cc @@ -55,6 +55,7 @@ /** All existing spaces. */ static struct mh_i32ptr_t *spaces; +static struct mh_strnptr_t *spaces_by_name; static struct mh_i32ptr_t *funcs; static struct mh_strnptr_t *funcs_by_name; static struct mh_i32ptr_t *sequences; @@ -95,6 +96,17 @@ space_by_id(uint32_t id) return (struct space *) mh_i32ptr_node(spaces, space)->val; } +/** Return space by its name */ +struct space * +space_by_name(const char *name) +{ + mh_int_t space = mh_strnptr_find_inp(spaces_by_name, name, + strlen(name)); + if (space == mh_end(spaces_by_name)) + return NULL; + return (struct space *) mh_strnptr_node(spaces_by_name, space)->val; +} + /** Return current schema version */ uint32_t box_schema_version() @@ -165,7 +177,25 @@ void space_cache_replace(struct space *old_space, struct space *new_space) { assert(new_space != NULL || old_space != NULL); + struct space *old_space_by_n = NULL; if (new_space != NULL) { + /* + * If replacing is performed and space name was + * changed, then need to explicitly remove old + * entry from spaces cache. + * NB: Since space_id never changed - no need + * to do so for space_id cache. + */ + if (old_space != NULL && strcmp(space_name(old_space), + new_space->def->name) != 0) { + const char *name = space_name(old_space); + mh_int_t k = mh_strnptr_find_inp(spaces_by_name, name, + strlen(name)); + assert(k != mh_end(spaces_by_name)); + mh_strnptr_del(spaces_by_name, k, NULL); + old_space_by_n = (struct space *)mh_strnptr_node(spaces_by_name, + k)->val; + } const struct mh_i32ptr_node_t node_p = { space_id(new_space), new_space }; struct mh_i32ptr_node_t old, *p_old = &old; @@ -174,7 +204,23 @@ space_cache_replace(struct space *old_space, struct space *new_space) panic_syserror("Out of memory for the data " "dictionary cache."); } - assert((struct space *)p_old->val == old_space); + const char *name = space_name(new_space); + uint32_t name_len = strlen(name); + uint32_t hash = mh_strn_hash(name, name_len); + const struct mh_strnptr_node_t node_s = { name, name_len, hash, + new_space }; + struct mh_strnptr_node_t old_s, *p_old_s = &old_s; + k = mh_strnptr_put(spaces_by_name, &node_s, &p_old_s, NULL); + if (k == mh_end(spaces_by_name)) { + panic_syserror("Out of memory for the data " + "dictionary cache."); + } + assert(old_space_by_n == NULL || p_old_s == NULL); + if(old_space_by_n == NULL && p_old != NULL) { + assert(p_old->val == p_old_s->val); + old_space_by_n = (struct space *)p_old->val; + } + assert((struct space*)old_space_by_n == old_space); } else { mh_int_t k = mh_i32ptr_find(spaces, space_id(old_space), NULL); assert(k != mh_end(spaces)); @@ -183,6 +229,14 @@ space_cache_replace(struct space *old_space, struct space *new_space) (void)old_space_by_id; assert(old_space_by_id == old_space); mh_i32ptr_del(spaces, k, NULL); + const char *name = space_name(old_space); + k = mh_strnptr_find_inp(spaces_by_name, name, strlen(name)); + assert(k != mh_end(spaces_by_name)); + old_space_by_n = (struct space *)mh_strnptr_node(spaces_by_name, + k)->val; + assert(old_space_by_n == old_space_by_id); + (void)old_space_by_id; + mh_strnptr_del(spaces_by_name, k, NULL); } space_cache_version++; } @@ -302,6 +356,7 @@ schema_init() /* Initialize the space cache. */ spaces = mh_i32ptr_new(); + spaces_by_name = mh_strnptr_new(); funcs = mh_i32ptr_new(); funcs_by_name = mh_strnptr_new(); sequences = mh_i32ptr_new(); @@ -449,6 +504,7 @@ schema_free(void) space_cache_replace(space, NULL); } mh_i32ptr_delete(spaces); + mh_strnptr_delete(spaces_by_name); while (mh_size(funcs) > 0) { mh_int_t i = mh_first(funcs); diff --git a/src/box/schema.h b/src/box/schema.h index 05f32de..89866a8 100644 --- a/src/box/schema.h +++ b/src/box/schema.h @@ -58,6 +58,14 @@ extern struct latch schema_lock; struct space * space_by_id(uint32_t id); +/** + * Try to look up a space by space name in the space name cache. + * + * @return NULL if space not found, otherwise space object. + */ +struct space * +space_by_name(const char *name); + uint32_t box_schema_version(); -- 2.11.0