[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