[server 2/4] Move helpers for updating request from space.c to request.c
Vladimir Davydov
vdavydov.dev at gmail.com
Tue Jan 23 19:28:56 MSK 2018
This patch moves helpers used to fix requests after certain DML
operations to a separate source file. Currently, there are only
two of them, but there are going to be more so it seems to be a
good idea to isolate them. No functional changes.
Suggested by @kostja
---
src/box/CMakeLists.txt | 1 +
src/box/request.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++
src/box/request.h | 69 ++++++++++++++++++++++
src/box/space.c | 124 +--------------------------------------
4 files changed, 225 insertions(+), 122 deletions(-)
create mode 100644 src/box/request.c
create mode 100644 src/box/request.h
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 19d3dbbc..f31ce178 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -81,6 +81,7 @@ add_library(box STATIC
vy_upsert.c
vy_read_set.c
vy_scheduler.c
+ request.c
space.c
space_def.c
sequence.c
diff --git a/src/box/request.c b/src/box/request.c
new file mode 100644
index 00000000..9118dcc7
--- /dev/null
+++ b/src/box/request.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2010-2018, 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 "request.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <msgpuck.h>
+#include <small/region.h>
+
+#include "fiber.h"
+#include "space.h"
+#include "index.h"
+#include "sequence.h"
+#include "key_def.h"
+#include "tuple.h"
+#include "xrow.h"
+#include "iproto_constants.h"
+
+void
+request_rebind_to_primary_key(struct request *request, struct space *space,
+ struct tuple *found_tuple)
+{
+ struct index *pk = space_index(space, 0);
+ assert(pk != NULL);
+ uint32_t key_len;
+ char *key = tuple_extract_key(found_tuple, pk->def->key_def, &key_len);
+ assert(key != NULL);
+ request->key = key;
+ request->key_end = key + key_len;
+ request->index_id = 0;
+ /* Clear the *body* to ensure it's rebuilt at commit. */
+ request->header = NULL;
+}
+
+int
+request_handle_sequence(struct request *request, struct space *space)
+{
+ struct sequence *seq = space->sequence;
+
+ assert(seq != NULL);
+ assert(request->type == IPROTO_INSERT ||
+ request->type == IPROTO_REPLACE);
+
+ /*
+ * An automatically generated sequence inherits
+ * privileges of the space it is used with.
+ */
+ if (!seq->is_generated &&
+ access_check_sequence(seq) != 0)
+ return -1;
+
+ struct index *pk = space_index(space, 0);
+ if (unlikely(pk == NULL))
+ return 0;
+
+ /*
+ * Look up the first field of the primary key.
+ */
+ const char *data = request->tuple;
+ const char *data_end = request->tuple_end;
+ int len = mp_decode_array(&data);
+ int fieldno = pk->def->key_def->parts[0].fieldno;
+ if (unlikely(len < fieldno + 1))
+ return 0;
+
+ const char *key = data;
+ if (unlikely(fieldno > 0)) {
+ do {
+ mp_next(&key);
+ } while (--fieldno > 0);
+ }
+
+ int64_t value;
+ if (mp_typeof(*key) == MP_NIL) {
+ /*
+ * If the first field of the primary key is nil,
+ * this is an auto increment request and we need
+ * to replace the nil with the next value generated
+ * by the space sequence.
+ */
+ if (unlikely(sequence_next(seq, &value) != 0))
+ return -1;
+
+ const char *key_end = key;
+ mp_decode_nil(&key_end);
+
+ size_t buf_size = (request->tuple_end - request->tuple) +
+ mp_sizeof_uint(UINT64_MAX);
+ char *tuple = region_alloc(&fiber()->gc, buf_size);
+ if (tuple == NULL)
+ return -1;
+ char *tuple_end = mp_encode_array(tuple, len);
+
+ if (unlikely(key != data)) {
+ memcpy(tuple_end, data, key - data);
+ tuple_end += key - data;
+ }
+
+ if (value >= 0)
+ tuple_end = mp_encode_uint(tuple_end, value);
+ else
+ tuple_end = mp_encode_int(tuple_end, value);
+
+ memcpy(tuple_end, key_end, data_end - key_end);
+ tuple_end += data_end - key_end;
+
+ assert(tuple_end <= tuple + buf_size);
+
+ request->tuple = tuple;
+ request->tuple_end = tuple_end;
+ } else {
+ /*
+ * If the first field is not nil, update the space
+ * sequence with its value, to make sure that an
+ * auto increment request never tries to insert a
+ * value that is already in the space. Note, this
+ * code is also invoked on final recovery to restore
+ * the sequence value from WAL.
+ */
+ if (likely(mp_read_int64(&key, &value) == 0))
+ return sequence_update(seq, value);
+ }
+ return 0;
+}
diff --git a/src/box/request.h b/src/box/request.h
new file mode 100644
index 00000000..ff1d97e0
--- /dev/null
+++ b/src/box/request.h
@@ -0,0 +1,69 @@
+#ifndef TARANTOOL_BOX_REQUEST_H_INCLUDED
+#define TARANTOOL_BOX_REQUEST_H_INCLUDED
+/*
+ * Copyright 2010-2018, 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 request;
+struct space;
+struct tuple;
+
+/**
+ * Convert a request accessing a secondary key to a primary
+ * key undo record, given it found a tuple.
+ * Flush iproto header of the request to be reconstructed in
+ * txn_add_redo().
+ *
+ * @param request - request to fix
+ * @param space - space corresponding to request
+ * @param found_tuple - tuple found by secondary key
+ */
+void
+request_rebind_to_primary_key(struct request *request, struct space *space,
+ struct tuple *found_tuple);
+
+/**
+ * Handle INSERT/REPLACE in a space with a sequence attached.
+ *
+ * @param request - request to fix
+ * @param space - space corresponding to request
+ */
+int
+request_handle_sequence(struct request *request, struct space *space);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif /* defined(__cplusplus) */
+
+#endif /* TARANTOOL_BOX_REQUEST_H_INCLUDED */
diff --git a/src/box/space.c b/src/box/space.c
index aeebf10a..d3692094 100644
--- a/src/box/space.c
+++ b/src/box/space.c
@@ -31,14 +31,13 @@
#include "space.h"
#include <stdlib.h>
#include <string.h>
-#include "tuple.h"
-#include "tuple_compare.h"
+#include "tuple_format.h"
#include "trigger.h"
#include "user.h"
#include "session.h"
+#include "request.h"
#include "xrow.h"
#include "iproto_constants.h"
-#include "sequence.h"
int
access_check_space(struct space *space, user_access_t access)
@@ -309,125 +308,6 @@ space_def_check_compatibility(const struct space_def *old_def,
return 0;
}
-/**
- * Convert a request accessing a secondary key to a primary key undo
- * record, given it found a tuple.
- * Flush iproto header of the request to be reconstructed in txn_add_redo().
- *
- * @param request - request to fix
- * @param space - space corresponding to request
- * @param found_tuple - tuple found by secondary key
- */
-static void
-request_rebind_to_primary_key(struct request *request, struct space *space,
- struct tuple *found_tuple)
-{
- struct index *pk = space_index(space, 0);
- assert(pk != NULL);
- uint32_t key_len;
- char *key = tuple_extract_key(found_tuple, pk->def->key_def, &key_len);
- assert(key != NULL);
- request->key = key;
- request->key_end = key + key_len;
- request->index_id = 0;
- /* Clear the *body* to ensure it's rebuilt at commit. */
- request->header = NULL;
-}
-
-/**
- * Handle INSERT/REPLACE in a space with a sequence attached.
- */
-static int
-request_handle_sequence(struct request *request, struct space *space)
-{
- struct sequence *seq = space->sequence;
-
- assert(seq != NULL);
- assert(request->type == IPROTO_INSERT ||
- request->type == IPROTO_REPLACE);
-
- /*
- * An automatically generated sequence inherits
- * privileges of the space it is used with.
- */
- if (!seq->is_generated &&
- access_check_sequence(seq) != 0)
- return -1;
-
- struct index *pk = space_index(space, 0);
- if (unlikely(pk == NULL))
- return 0;
-
- /*
- * Look up the first field of the primary key.
- */
- const char *data = request->tuple;
- const char *data_end = request->tuple_end;
- int len = mp_decode_array(&data);
- int fieldno = pk->def->key_def->parts[0].fieldno;
- if (unlikely(len < fieldno + 1))
- return 0;
-
- const char *key = data;
- if (unlikely(fieldno > 0)) {
- do {
- mp_next(&key);
- } while (--fieldno > 0);
- }
-
- int64_t value;
- if (mp_typeof(*key) == MP_NIL) {
- /*
- * If the first field of the primary key is nil,
- * this is an auto increment request and we need
- * to replace the nil with the next value generated
- * by the space sequence.
- */
- if (unlikely(sequence_next(seq, &value) != 0))
- return -1;
-
- const char *key_end = key;
- mp_decode_nil(&key_end);
-
- size_t buf_size = (request->tuple_end - request->tuple) +
- mp_sizeof_uint(UINT64_MAX);
- char *tuple = region_alloc(&fiber()->gc, buf_size);
- if (tuple == NULL)
- return -1;
- char *tuple_end = mp_encode_array(tuple, len);
-
- if (unlikely(key != data)) {
- memcpy(tuple_end, data, key - data);
- tuple_end += key - data;
- }
-
- if (value >= 0)
- tuple_end = mp_encode_uint(tuple_end, value);
- else
- tuple_end = mp_encode_int(tuple_end, value);
-
- memcpy(tuple_end, key_end, data_end - key_end);
- tuple_end += data_end - key_end;
-
- assert(tuple_end <= tuple + buf_size);
-
- request->tuple = tuple;
- request->tuple_end = tuple_end;
- } else {
- /*
- * If the first field is not nil, update the space
- * sequence with its value, to make sure that an
- * auto increment request never tries to insert a
- * value that is already in the space. Note, this
- * code is also invoked on final recovery to restore
- * the sequence value from WAL.
- */
- if (likely(mp_read_int64(&key, &value) == 0))
- return sequence_update(seq, value);
- }
- return 0;
-}
-
int
space_execute_dml(struct space *space, struct txn *txn,
struct request *request, struct tuple **result)
--
2.11.0
More information about the Tarantool-patches
mailing list