[PATCH v2 4/5] box: move the function hash to the tuple library
Kirill Shcherbatov
kshcherbatov at tarantool.org
Mon Jun 24 17:27:03 MSK 2019
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 <COPYRIGHT HOLDER> ``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
+ * <COPYRIGHT HOLDER> 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 <COPYRIGHT HOLDER> ``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
+ * <COPYRIGHT HOLDER> 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 <stdint.h>
+
+#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
More information about the Tarantool-patches
mailing list