[patches] [PATCH v2 1/5] tuple: move tuple_extract_key functions to a separate .cc file
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Sun Feb 18 23:59:35 MSK 2018
Needed for #2048
Signed-off-by: Vladislav Shpilevoy <v.shpilevoy at tarantool.org>
---
src/CMakeLists.txt | 1 +
src/box/CMakeLists.txt | 1 +
src/box/index.h | 14 +++
src/box/key_def.cc | 1 +
src/box/key_def.h | 39 +++++++++
src/box/tuple.c | 194 ------------------------------------------
src/box/tuple.h | 59 -------------
src/box/tuple_extract_key.cc | 197 +++++++++++++++++++++++++++++++++++++++++++
src/box/tuple_extract_key.h | 50 +++++++++++
9 files changed, 303 insertions(+), 253 deletions(-)
create mode 100644 src/box/tuple_extract_key.cc
create mode 100644 src/box/tuple_extract_key.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e5acef738..b947a67c0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -185,6 +185,7 @@ set(api_headers
${CMAKE_SOURCE_DIR}/src/box/tuple.h
${CMAKE_SOURCE_DIR}/src/box/tuple_format.h
${CMAKE_SOURCE_DIR}/src/box/tuple_compare.h
+ ${CMAKE_SOURCE_DIR}/src/box/tuple_extract_key.h
${CMAKE_SOURCE_DIR}/src/box/schema_def.h
${CMAKE_SOURCE_DIR}/src/box/box.h
${CMAKE_SOURCE_DIR}/src/box/index.h
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index bdbbbb075..c7ca34b89 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -35,6 +35,7 @@ add_library(tuple STATIC
tuple_format.c
tuple_update.c
tuple_compare.cc
+ tuple_extract_key.cc
tuple_hash.cc
tuple_dictionary.c
key_def.cc
diff --git a/src/box/index.h b/src/box/index.h
index 74b1c9ae9..3c478c6d6 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -195,6 +195,20 @@ ssize_t
box_index_count(uint32_t space_id, uint32_t index_id, int type,
const char *key, const char *key_end);
+/**
+ * Extract key from tuple according to key definition of given
+ * index. Returned buffer is allocated on box_txn_alloc() with
+ * this key.
+ * @param tuple Tuple from which need to extract key.
+ * @param space_id Space identifier.
+ * @param index_id Index identifier.
+ * @retval not NULL Success
+ * @retval NULL Memory Allocation error
+ */
+char *
+box_tuple_extract_key(const box_tuple_t *tuple, uint32_t space_id,
+ uint32_t index_id, uint32_t *key_size);
+
/** \endcond public */
/**
diff --git a/src/box/key_def.cc b/src/box/key_def.cc
index f7f6c753a..7f00b82df 100644
--- a/src/box/key_def.cc
+++ b/src/box/key_def.cc
@@ -30,6 +30,7 @@
*/
#include "key_def.h"
#include "tuple_compare.h"
+#include "tuple_extract_key.h"
#include "tuple_hash.h"
#include "column_mask.h"
#include "schema_def.h"
diff --git a/src/box/key_def.h b/src/box/key_def.h
index 201863f5a..d90859196 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -374,6 +374,45 @@ key_part_check_compatibility(const struct key_part *old_parts,
const struct key_part *new_parts,
uint32_t new_part_count);
+/**
+ * Extract key from tuple by given key definition and return
+ * buffer allocated on box_txn_alloc with this key. This function
+ * has O(n) complexity, where n is the number of key parts.
+ * @param tuple - tuple from which need to extract key
+ * @param key_def - definition of key that need to extract
+ * @param key_size - here will be size of extracted key
+ *
+ * @retval not NULL Success
+ * @retval NULL Memory allocation error
+ */
+static inline char *
+tuple_extract_key(const struct tuple *tuple, const struct key_def *key_def,
+ uint32_t *key_size)
+{
+ return key_def->tuple_extract_key(tuple, key_def, key_size);
+}
+
+/**
+ * Extract key from raw msgpuck by given key definition and return
+ * buffer allocated on box_txn_alloc with this key.
+ * This function has O(n*m) complexity, where n is the number of key parts
+ * and m is the tuple size.
+ * @param data - msgpuck data from which need to extract key
+ * @param data_end - pointer at the end of data
+ * @param key_def - definition of key that need to extract
+ * @param key_size - here will be size of extracted key
+ *
+ * @retval not NULL Success
+ * @retval NULL Memory allocation error
+ */
+static inline char *
+tuple_extract_key_raw(const char *data, const char *data_end,
+ const struct key_def *key_def, uint32_t *key_size)
+{
+ return key_def->tuple_extract_key_raw(data, data_end, key_def,
+ key_size);
+}
+
#if defined(__cplusplus)
} /* extern "C" */
#endif /* defined(__cplusplus) */
diff --git a/src/box/tuple.c b/src/box/tuple.c
index 40a091c13..d4760f3b1 100644
--- a/src/box/tuple.c
+++ b/src/box/tuple.c
@@ -184,200 +184,6 @@ tuple_next(struct tuple_iterator *it)
return NULL;
}
-/**
- * Optimized version of tuple_extract_key_raw() for sequential key defs
- * @copydoc tuple_extract_key_raw()
- */
-static char *
-tuple_extract_key_sequential_raw(const char *data, const char *data_end,
- const struct key_def *key_def,
- uint32_t *key_size)
-{
- assert(key_def_is_sequential(key_def));
- const char *field_start = data;
- uint32_t bsize = mp_sizeof_array(key_def->part_count);
-
- mp_decode_array(&field_start);
- const char *field_end = field_start;
-
- for (uint32_t i = 0; i < key_def->part_count; i++)
- mp_next(&field_end);
- bsize += field_end - field_start;
-
- assert(!data_end || (field_end - field_start <= data_end - data));
- (void) data_end;
-
- char *key = (char *) region_alloc(&fiber()->gc, bsize);
- if (key == NULL) {
- diag_set(OutOfMemory, bsize, "region",
- "tuple_extract_key_raw_sequential");
- return NULL;
- }
- char *key_buf = mp_encode_array(key, key_def->part_count);
- memcpy(key_buf, field_start, field_end - field_start);
-
- if (key_size != NULL)
- *key_size = bsize;
- return key;
-}
-
-/**
- * Optimized version of tuple_extract_key() for sequential key defs
- * @copydoc tuple_extract_key()
- */
-static inline char *
-tuple_extract_key_sequential(const struct tuple *tuple,
- const struct key_def *key_def,
- uint32_t *key_size)
-{
- assert(key_def_is_sequential(key_def));
- const char *data = tuple_data(tuple);
- return tuple_extract_key_sequential_raw(data, NULL, key_def, key_size);
-}
-
-/**
- * General-purpose implementation of tuple_extract_key()
- * @copydoc tuple_extract_key()
- */
-static char *
-tuple_extract_key_slowpath(const struct tuple *tuple,
- const struct key_def *key_def, uint32_t *key_size)
-{
- const char *data = tuple_data(tuple);
- uint32_t part_count = key_def->part_count;
- uint32_t bsize = mp_sizeof_array(part_count);
- const struct tuple_format *format = tuple_format(tuple);
- const uint32_t *field_map = tuple_field_map(tuple);
-
- /* Calculate the key size. */
- for (uint32_t i = 0; i < part_count; ++i) {
- const char *field =
- tuple_field_raw(format, data, field_map,
- key_def->parts[i].fieldno);
- const char *end = field;
- /*
- * Skip sequential part in order to minimize
- * tuple_field_raw() calls.
- */
- for (; i < key_def->part_count - 1; i++) {
- if (key_def->parts[i].fieldno + 1 !=
- key_def->parts[i + 1].fieldno) {
- /* End of sequential part */
- break;
- }
- mp_next(&end);
- }
- mp_next(&end);
- bsize += end - field;
- }
-
- char *key = (char *) region_alloc(&fiber()->gc, bsize);
- if (key == NULL) {
- diag_set(OutOfMemory, bsize, "region", "tuple_extract_key");
- return NULL;
- }
- char *key_buf = mp_encode_array(key, part_count);
- for (uint32_t i = 0; i < part_count; ++i) {
- const char *field =
- tuple_field_raw(format, data, field_map,
- key_def->parts[i].fieldno);
- const char *end = field;
- /*
- * Skip sequential part in order to minimize
- * tuple_field_raw() calls
- */
- for (; i < key_def->part_count - 1; i++) {
- if (key_def->parts[i].fieldno + 1 !=
- key_def->parts[i + 1].fieldno) {
- /* End of sequential part */
- break;
- }
- mp_next(&end);
- }
- mp_next(&end);
- bsize = end - field;
- memcpy(key_buf, field, bsize);
- key_buf += bsize;
- }
- if (key_size != NULL)
- *key_size = key_buf - key;
- return key;
-}
-
-/**
- * General-purpose version of tuple_extract_key_raw()
- * @copydoc tuple_extract_key_raw()
- */
-static char *
-tuple_extract_key_slowpath_raw(const char *data, const char *data_end,
- const struct key_def *key_def,
- uint32_t *key_size)
-{
- /* allocate buffer with maximal possible size */
- char *key = (char *) region_alloc(&fiber()->gc, data_end - data);
- if (key == NULL) {
- diag_set(OutOfMemory, data_end - data, "region",
- "tuple_extract_key_raw");
- return NULL;
- }
- char *key_buf = mp_encode_array(key, key_def->part_count);
- const char *field0 = data;
- mp_decode_array(&field0);
- const char *field0_end = field0;
- mp_next(&field0_end);
- const char *field = field0;
- const char *field_end = field0_end;
- uint32_t current_fieldno = 0;
- for (uint32_t i = 0; i < key_def->part_count; i++) {
- uint32_t fieldno = key_def->parts[i].fieldno;
- for (; i < key_def->part_count - 1; i++) {
- if (key_def->parts[i].fieldno + 1 !=
- key_def->parts[i + 1].fieldno)
- break;
- }
- if (fieldno < current_fieldno) {
- /* Rewind. */
- field = field0;
- field_end = field0_end;
- current_fieldno = 0;
- }
-
- while (current_fieldno < fieldno) {
- /* search first field of key in tuple raw data */
- field = field_end;
- mp_next(&field_end);
- current_fieldno++;
- }
-
- while (current_fieldno < key_def->parts[i].fieldno) {
- /* search the last field in subsequence */
- mp_next(&field_end);
- current_fieldno++;
- }
- memcpy(key_buf, field, field_end - field);
- key_buf += field_end - field;
- assert(key_buf - key <= data_end - data);
- }
- if (key_size != NULL)
- *key_size = (uint32_t)(key_buf - key);
- return key;
-}
-
-/**
- * Initialize tuple_extract_key() and tuple_extract_key_raw()
- */
-void
-tuple_extract_key_set(struct key_def *key_def)
-{
- if (key_def_is_sequential(key_def)) {
- key_def->tuple_extract_key = tuple_extract_key_sequential;
- key_def->tuple_extract_key_raw = tuple_extract_key_sequential_raw;
- } else {
- key_def->tuple_extract_key = tuple_extract_key_slowpath;
- key_def->tuple_extract_key_raw = tuple_extract_key_slowpath_raw;
- }
-}
-
int
tuple_init(field_name_hash_f hash)
{
diff --git a/src/box/tuple.h b/src/box/tuple.h
index 27c475056..6ebedf5f2 100644
--- a/src/box/tuple.h
+++ b/src/box/tuple.h
@@ -285,20 +285,6 @@ box_tuple_t *
box_tuple_upsert(const box_tuple_t *tuple, const char *expr, const
char *expr_end);
-/**
- * Extract key from tuple according to key definition of given index.
- * Returned buffer is allocated on box_txn_alloc() with this key.
- * This function has O(n) complexity, where n is the number of key parts.
- * @param tuple tuple from which need to extract key
- * @param space_id space identifier
- * @param index_id index identifier
- * @retval not NULL Success
- * @retval NULL Memory allocation error
- */
-char *
-box_tuple_extract_key(const box_tuple_t *tuple, uint32_t space_id,
- uint32_t index_id, uint32_t *key_size);
-
/** \endcond public */
/**
@@ -409,51 +395,6 @@ tuple_snprint(char *buf, int size, const struct tuple *tuple);
const char *
tuple_str(const struct tuple *tuple);
-/**
- * Initialize key extraction functions in the key_def
- * @param key_def key definition
- */
-void
-tuple_extract_key_set(struct key_def *key_def);
-
-/* Extract key from tuple by given key definition and return
- * buffer allocated on box_txn_alloc with this key. This function
- * has O(n) complexity, where n is the number of key parts.
- * @param tuple - tuple from which need to extract key
- * @param key_def - definition of key that need to extract
- * @param key_size - here will be size of extracted key
- *
- * @retval not NULL Success
- * @retval NULL Memory allocation error
- */
-static inline char *
-tuple_extract_key(const struct tuple *tuple, const struct key_def *key_def,
- uint32_t *key_size)
-{
- return key_def->tuple_extract_key(tuple, key_def, key_size);
-}
-
-/**
- * Extract key from raw msgpuck by given key definition and return
- * buffer allocated on box_txn_alloc with this key.
- * This function has O(n*m) complexity, where n is the number of key parts
- * and m is the tuple size.
- * @param data - msgpuck data from which need to extract key
- * @param data_end - pointer at the end of data
- * @param key_def - definition of key that need to extract
- * @param key_size - here will be size of extracted key
- *
- * @retval not NULL Success
- * @retval NULL Memory allocation error
- */
-static inline char *
-tuple_extract_key_raw(const char *data, const char *data_end,
- const struct key_def *key_def, uint32_t *key_size)
-{
- return key_def->tuple_extract_key_raw(data, data_end, key_def,
- key_size);
-}
-
/**
* Get the format of the tuple.
* @param tuple Tuple.
diff --git a/src/box/tuple_extract_key.cc b/src/box/tuple_extract_key.cc
new file mode 100644
index 000000000..a83e9dfc4
--- /dev/null
+++ b/src/box/tuple_extract_key.cc
@@ -0,0 +1,197 @@
+#include "tuple_extract_key.h"
+#include "tuple.h"
+#include "fiber.h"
+
+/**
+ * Optimized version of tuple_extract_key_raw() for sequential key defs
+ * @copydoc tuple_extract_key_raw()
+ */
+static char *
+tuple_extract_key_sequential_raw(const char *data, const char *data_end,
+ const struct key_def *key_def,
+ uint32_t *key_size)
+{
+ assert(key_def_is_sequential(key_def));
+ const char *field_start = data;
+ uint32_t bsize = mp_sizeof_array(key_def->part_count);
+
+ mp_decode_array(&field_start);
+ const char *field_end = field_start;
+
+ for (uint32_t i = 0; i < key_def->part_count; i++)
+ mp_next(&field_end);
+ bsize += field_end - field_start;
+
+ assert(!data_end || (field_end - field_start <= data_end - data));
+ (void) data_end;
+
+ char *key = (char *) region_alloc(&fiber()->gc, bsize);
+ if (key == NULL) {
+ diag_set(OutOfMemory, bsize, "region",
+ "tuple_extract_key_raw_sequential");
+ return NULL;
+ }
+ char *key_buf = mp_encode_array(key, key_def->part_count);
+ memcpy(key_buf, field_start, field_end - field_start);
+
+ if (key_size != NULL)
+ *key_size = bsize;
+ return key;
+}
+
+/**
+ * Optimized version of tuple_extract_key() for sequential key defs
+ * @copydoc tuple_extract_key()
+ */
+static inline char *
+tuple_extract_key_sequential(const struct tuple *tuple,
+ const struct key_def *key_def,
+ uint32_t *key_size)
+{
+ assert(key_def_is_sequential(key_def));
+ const char *data = tuple_data(tuple);
+ return tuple_extract_key_sequential_raw(data, NULL, key_def, key_size);
+}
+
+/**
+ * General-purpose implementation of tuple_extract_key()
+ * @copydoc tuple_extract_key()
+ */
+static char *
+tuple_extract_key_slowpath(const struct tuple *tuple,
+ const struct key_def *key_def, uint32_t *key_size)
+{
+ const char *data = tuple_data(tuple);
+ uint32_t part_count = key_def->part_count;
+ uint32_t bsize = mp_sizeof_array(part_count);
+ const struct tuple_format *format = tuple_format(tuple);
+ const uint32_t *field_map = tuple_field_map(tuple);
+
+ /* Calculate the key size. */
+ for (uint32_t i = 0; i < part_count; ++i) {
+ const char *field =
+ tuple_field_raw(format, data, field_map,
+ key_def->parts[i].fieldno);
+ const char *end = field;
+ /*
+ * Skip sequential part in order to minimize
+ * tuple_field_raw() calls.
+ */
+ for (; i < key_def->part_count - 1; i++) {
+ if (key_def->parts[i].fieldno + 1 !=
+ key_def->parts[i + 1].fieldno) {
+ /* End of sequential part */
+ break;
+ }
+ mp_next(&end);
+ }
+ mp_next(&end);
+ bsize += end - field;
+ }
+
+ char *key = (char *) region_alloc(&fiber()->gc, bsize);
+ if (key == NULL) {
+ diag_set(OutOfMemory, bsize, "region", "tuple_extract_key");
+ return NULL;
+ }
+ char *key_buf = mp_encode_array(key, part_count);
+ for (uint32_t i = 0; i < part_count; ++i) {
+ const char *field =
+ tuple_field_raw(format, data, field_map,
+ key_def->parts[i].fieldno);
+ const char *end = field;
+ /*
+ * Skip sequential part in order to minimize
+ * tuple_field_raw() calls
+ */
+ for (; i < key_def->part_count - 1; i++) {
+ if (key_def->parts[i].fieldno + 1 !=
+ key_def->parts[i + 1].fieldno) {
+ /* End of sequential part */
+ break;
+ }
+ mp_next(&end);
+ }
+ mp_next(&end);
+ bsize = end - field;
+ memcpy(key_buf, field, bsize);
+ key_buf += bsize;
+ }
+ if (key_size != NULL)
+ *key_size = key_buf - key;
+ return key;
+}
+
+/**
+ * General-purpose version of tuple_extract_key_raw()
+ * @copydoc tuple_extract_key_raw()
+ */
+static char *
+tuple_extract_key_slowpath_raw(const char *data, const char *data_end,
+ const struct key_def *key_def,
+ uint32_t *key_size)
+{
+ /* allocate buffer with maximal possible size */
+ char *key = (char *) region_alloc(&fiber()->gc, data_end - data);
+ if (key == NULL) {
+ diag_set(OutOfMemory, data_end - data, "region",
+ "tuple_extract_key_raw");
+ return NULL;
+ }
+ char *key_buf = mp_encode_array(key, key_def->part_count);
+ const char *field0 = data;
+ mp_decode_array(&field0);
+ const char *field0_end = field0;
+ mp_next(&field0_end);
+ const char *field = field0;
+ const char *field_end = field0_end;
+ uint32_t current_fieldno = 0;
+ for (uint32_t i = 0; i < key_def->part_count; i++) {
+ uint32_t fieldno = key_def->parts[i].fieldno;
+ for (; i < key_def->part_count - 1; i++) {
+ if (key_def->parts[i].fieldno + 1 !=
+ key_def->parts[i + 1].fieldno)
+ break;
+ }
+ if (fieldno < current_fieldno) {
+ /* Rewind. */
+ field = field0;
+ field_end = field0_end;
+ current_fieldno = 0;
+ }
+
+ while (current_fieldno < fieldno) {
+ /* search first field of key in tuple raw data */
+ field = field_end;
+ mp_next(&field_end);
+ current_fieldno++;
+ }
+
+ while (current_fieldno < key_def->parts[i].fieldno) {
+ /* search the last field in subsequence */
+ mp_next(&field_end);
+ current_fieldno++;
+ }
+ memcpy(key_buf, field, field_end - field);
+ key_buf += field_end - field;
+ assert(key_buf - key <= data_end - data);
+ }
+ if (key_size != NULL)
+ *key_size = (uint32_t)(key_buf - key);
+ return key;
+}
+
+/**
+ * Initialize tuple_extract_key() and tuple_extract_key_raw()
+ */
+void
+tuple_extract_key_set(struct key_def *key_def)
+{
+ if (key_def_is_sequential(key_def)) {
+ key_def->tuple_extract_key = tuple_extract_key_sequential;
+ key_def->tuple_extract_key_raw = tuple_extract_key_sequential_raw;
+ } else {
+ key_def->tuple_extract_key = tuple_extract_key_slowpath;
+ key_def->tuple_extract_key_raw = tuple_extract_key_slowpath_raw;
+ }
+}
diff --git a/src/box/tuple_extract_key.h b/src/box/tuple_extract_key.h
new file mode 100644
index 000000000..8a3465957
--- /dev/null
+++ b/src/box/tuple_extract_key.h
@@ -0,0 +1,50 @@
+#ifndef TARANTOOL_BOX_TUPLE_EXTRACT_KEY_H_INCLUDED
+#define TARANTOOL_BOX_TUPLE_EXTRACT_KEY_H_INCLUDED
+/*
+ * Copyright 2010-2016, 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.
+ */
+#if defined(__cplusplus)
+extern "C" {
+#endif /* defined(__cplusplus) */
+
+struct key_def;
+
+/**
+ * Initialize key extraction functions in the key_def
+ * @param key_def key definition
+ */
+void
+tuple_extract_key_set(struct key_def *key_def);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* TARANTOOL_BOX_TUPLE_EXTRACT_KEY_H_INCLUDED */
--
2.14.3 (Apple Git-98)
More information about the Tarantool-patches
mailing list