From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: From: Kirill Shcherbatov Subject: [PATCH v2 4/5] box: move the function hash to the tuple library Date: Mon, 24 Jun 2019 17:27:03 +0300 Message-Id: <9c50db9c5e92d58e2b3e6dc145879a0746302667.1561384554.git.kshcherbatov@tarantool.org> In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit To: tarantool-patches@freelists.org, vdavydov.dev@gmail.com Cc: Kirill Shcherbatov List-ID: The functions hashtable moved to the tuple library. It is required in scope of functional indexes to perform a lookup function by it's identifier in key_def module that is a part of tuple library. Needed for #1260 --- src/box/CMakeLists.txt | 1 + src/box/func_cache.c | 124 +++++++++++++++++++++++++++++++++++++++++ src/box/func_cache.h | 78 ++++++++++++++++++++++++++ src/box/schema.cc | 69 ----------------------- src/box/schema.h | 19 +------ src/box/tuple.c | 6 ++ 6 files changed, 210 insertions(+), 87 deletions(-) create mode 100644 src/box/func_cache.c create mode 100644 src/box/func_cache.h diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index 481842a39..7da2d6cff 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -45,6 +45,7 @@ add_library(tuple STATIC tuple_hash.cc tuple_bloom.c tuple_dictionary.c + func_cache.c key_def.c coll_id_def.c coll_id.c diff --git a/src/box/func_cache.c b/src/box/func_cache.c new file mode 100644 index 000000000..05545eb6b --- /dev/null +++ b/src/box/func_cache.c @@ -0,0 +1,124 @@ +/* + * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "func_cache.h" +#include "assoc.h" +#include "diag.h" +#include "errcode.h" +#include "error.h" +#include "func.h" +#include "schema_def.h" + +/** mhash table (name, len -> collation) */ +static struct mh_i32ptr_t *func_id_cache; +/** mhash table (id -> collation) */ +static struct mh_strnptr_t *func_name_cache; + +int +func_cache_init(void) +{ + func_id_cache = mh_i32ptr_new(); + if (func_id_cache == NULL) { + diag_set(OutOfMemory, sizeof(*func_id_cache), "malloc", + "func_id_cache"); + return -1; + } + func_name_cache = mh_strnptr_new(); + if (func_name_cache == NULL) { + diag_set(OutOfMemory, sizeof(*func_name_cache), "malloc", + "func_name_cache"); + mh_i32ptr_delete(func_id_cache); + return -1; + } + return 0; +} + +void +func_cache_destroy(void) +{ + mh_strnptr_delete(func_name_cache); + mh_i32ptr_delete(func_id_cache); +} + +void +func_cache_insert(struct func *func) +{ + assert(func_by_id(func->def->fid) == NULL); + assert(func_by_name(func->def->name, strlen(func->def->name)) == NULL); + const struct mh_i32ptr_node_t node = { func->def->fid, func }; + mh_int_t k1 = mh_i32ptr_put(func_id_cache, &node, NULL, NULL); + if (k1 == mh_end(func_id_cache)) { +error: + panic_syserror("Out of memory for the data " + "dictionary cache (stored function)."); + } + size_t def_name_len = strlen(func->def->name); + uint32_t name_hash = mh_strn_hash(func->def->name, def_name_len); + const struct mh_strnptr_node_t strnode = { + func->def->name, def_name_len, name_hash, func }; + mh_int_t k2 = mh_strnptr_put(func_name_cache, &strnode, NULL, NULL); + if (k2 == mh_end(func_name_cache)) { + mh_i32ptr_del(func_id_cache, k1, NULL); + goto error; + } +} + +void +func_cache_delete(uint32_t fid) +{ + mh_int_t k = mh_i32ptr_find(func_id_cache, fid, NULL); + if (k == mh_end(func_id_cache)) + return; + struct func *func = (struct func *) + mh_i32ptr_node(func_id_cache, k)->val; + mh_i32ptr_del(func_id_cache, k, NULL); + k = mh_strnptr_find_inp(func_name_cache, func->def->name, + strlen(func->def->name)); + if (k != mh_end(func_id_cache)) + mh_strnptr_del(func_name_cache, k, NULL); +} + +struct func * +func_by_id(uint32_t fid) +{ + mh_int_t func = mh_i32ptr_find(func_id_cache, fid, NULL); + if (func == mh_end(func_id_cache)) + return NULL; + return (struct func *) mh_i32ptr_node(func_id_cache, func)->val; +} + +struct func * +func_by_name(const char *name, uint32_t name_len) +{ + mh_int_t func = mh_strnptr_find_inp(func_name_cache, name, name_len); + if (func == mh_end(func_name_cache)) + return NULL; + return (struct func *) mh_strnptr_node(func_name_cache, func)->val; +} diff --git a/src/box/func_cache.h b/src/box/func_cache.h new file mode 100644 index 000000000..9a8bba76d --- /dev/null +++ b/src/box/func_cache.h @@ -0,0 +1,78 @@ +#ifndef TARANTOOL_BOX_FUNC_CACHE_H_INCLUDED +#define TARANTOOL_BOX_FUNC_CACHE_H_INCLUDED +/* + * Copyright 2010-2019, Tarantool AUTHORS, please see AUTHORS file. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +struct func; + +/** + * Create global function hash tables. + * @return - 0 on success, -1 on memory error. + */ +int +func_cache_init(void); + +/** Delete global function hash tables. */ +void +func_cache_destroy(void); + +/** + * Insert a new function object in the function cache. + * @param func Function object to insert. + */ +void +func_cache_insert(struct func *func); + +/** + * Delete a function object from function cache. + * @param fid Function to delete identifier. + */ +void +func_cache_delete(uint32_t fid); + +/** Find a function object by its id. */ +struct func * +func_by_id(uint32_t fid); + +/** Find a function object by its name. */ +struct func * +func_by_name(const char *name, uint32_t name_len); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif /* defined(__cplusplus) */ + +#endif /* TARANTOOL_BOX_FUNC_CACHE_H_INCLUDED */ diff --git a/src/box/schema.cc b/src/box/schema.cc index 64412fac6..4427668a1 100644 --- a/src/box/schema.cc +++ b/src/box/schema.cc @@ -56,8 +56,6 @@ /** 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; /** Public change counter. On its update clients need to fetch * new space data from the instance. */ @@ -377,8 +375,6 @@ 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(); /* * Create surrogate space objects for the mandatory system @@ -523,15 +519,6 @@ schema_free(void) } mh_i32ptr_delete(spaces); mh_strnptr_delete(spaces_by_name); - while (mh_size(funcs) > 0) { - mh_int_t i = mh_first(funcs); - - struct func *func = ((struct func *) - mh_i32ptr_node(funcs, i)->val); - func_cache_delete(func->def->fid); - func_delete(func); - } - mh_i32ptr_delete(funcs); while (mh_size(sequences) > 0) { mh_int_t i = mh_first(sequences); @@ -542,62 +529,6 @@ schema_free(void) mh_i32ptr_delete(sequences); } -void -func_cache_insert(struct func *func) -{ - assert(func_by_id(func->def->fid) == NULL); - assert(func_by_name(func->def->name, strlen(func->def->name)) == NULL); - const struct mh_i32ptr_node_t node = { func->def->fid, func }; - mh_int_t k1 = mh_i32ptr_put(funcs, &node, NULL, NULL); - if (k1 == mh_end(funcs)) { -error: - panic_syserror("Out of memory for the data " - "dictionary cache (stored function)."); - } - size_t def_name_len = strlen(func->def->name); - uint32_t name_hash = mh_strn_hash(func->def->name, def_name_len); - const struct mh_strnptr_node_t strnode = { - func->def->name, def_name_len, name_hash, func }; - mh_int_t k2 = mh_strnptr_put(funcs_by_name, &strnode, NULL, NULL); - if (k2 == mh_end(funcs_by_name)) { - mh_i32ptr_del(funcs, k1, NULL); - goto error; - } -} - -void -func_cache_delete(uint32_t fid) -{ - mh_int_t k = mh_i32ptr_find(funcs, fid, NULL); - if (k == mh_end(funcs)) - return; - struct func *func = (struct func *) - mh_i32ptr_node(funcs, k)->val; - mh_i32ptr_del(funcs, k, NULL); - k = mh_strnptr_find_inp(funcs_by_name, func->def->name, - strlen(func->def->name)); - if (k != mh_end(funcs)) - mh_strnptr_del(funcs_by_name, k, NULL); -} - -struct func * -func_by_id(uint32_t fid) -{ - mh_int_t func = mh_i32ptr_find(funcs, fid, NULL); - if (func == mh_end(funcs)) - return NULL; - return (struct func *) mh_i32ptr_node(funcs, func)->val; -} - -struct func * -func_by_name(const char *name, uint32_t name_len) -{ - mh_int_t func = mh_strnptr_find_inp(funcs_by_name, name, name_len); - if (func == mh_end(funcs_by_name)) - return NULL; - return (struct func *) mh_strnptr_node(funcs_by_name, func)->val; -} - bool schema_find_grants(const char *type, uint32_t id) { diff --git a/src/box/schema.h b/src/box/schema.h index f0039b29d..181a0d2db 100644 --- a/src/box/schema.h +++ b/src/box/schema.h @@ -36,6 +36,7 @@ #include "error.h" #include "space.h" #include "latch.h" +#include "func_cache.h" #if defined(__cplusplus) extern "C" { @@ -89,9 +90,6 @@ space_cache_find(uint32_t id) return NULL; } -struct func * -func_by_name(const char *name, uint32_t name_len); - /** Call a visitor function on every space in the space cache. */ int space_foreach(int (*func)(struct space *sp, void *udata), void *udata); @@ -162,21 +160,6 @@ schema_free(); struct space *schema_space(uint32_t id); -/** - * Insert a new function object in the function cache. - * @param func Function object to insert. - */ -void -func_cache_insert(struct func *func); - -void -func_cache_delete(uint32_t fid); - -struct func; - -struct func * -func_by_id(uint32_t fid); - static inline struct func * func_cache_find(uint32_t fid) { diff --git a/src/box/tuple.c b/src/box/tuple.c index 5fff868ac..e98cdb829 100644 --- a/src/box/tuple.c +++ b/src/box/tuple.c @@ -38,6 +38,7 @@ #include "tuple_update.h" #include "coll_id_cache.h" +#include "func_cache.h" static struct mempool tuple_iterator_pool; static struct small_alloc runtime_alloc; @@ -339,6 +340,9 @@ tuple_init(field_name_hash_f hash) if (coll_id_cache_init() != 0) return -1; + if (func_cache_init() != 0) + return -1; + return 0; } @@ -403,6 +407,8 @@ tuple_free(void) coll_id_cache_destroy(); + func_cache_destroy(); + bigref_list_destroy(); } -- 2.21.0