From 5a454e84dec99b94c717847092b0b9c8aff6d9e3 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Sun, 27 Apr 2014 12:20:59 +0400 Subject: [PATCH] async-master-master review fixes * Remove a bogus message at the start of FindLibUUID.cmake. * Move cluster_add_node to cluster. * Extract UUID API into a (potentially) platform-independnent header tt_uuid. * Add error codes for error messages used in UUID generation, triggers and consistency checks. * Cleanup. --- cmake/FindLibUUID.cmake | 2 - src/CMakeLists.txt | 1 + src/admin.cc | 2 +- src/box/CMakeLists.txt | 1 + src/box/alter.cc | 79 +++++++++++++++++++---------- src/box/box.cc | 23 ++++----- src/box/cluster.cc | 75 +++++++++++++++++++++++++++ src/box/cluster.h | 107 +++++++++++++++++++++++++++++++++++++++ src/box/txn.cc | 3 +- src/errcode.h | 5 +- src/iobuf.cc | 4 +- src/iobuf.h | 2 +- src/iproto.cc | 2 +- src/log_io.cc | 26 +++++----- src/log_io.h | 12 +++-- src/lua/info.cc | 4 +- src/recovery.cc | 72 +++++++------------------- src/recovery.h | 12 ++--- src/replica.cc | 15 +++--- src/replication.cc | 41 +++++++-------- src/trivia/util.h | 8 --- src/tt_uuid.c | 40 +++++++++++++++ src/tt_uuid.h | 90 ++++++++++++++++++++++++++++++++ src/util.cc | 8 --- test/box/misc.result | 89 ++++++++++++++++---------------- test/unit/CMakeLists.txt | 2 +- test/unit/log_dir.cc | 6 +-- 27 files changed, 508 insertions(+), 223 deletions(-) create mode 100644 src/box/cluster.cc create mode 100644 src/box/cluster.h create mode 100644 src/tt_uuid.c create mode 100644 src/tt_uuid.h diff --git a/cmake/FindLibUUID.cmake b/cmake/FindLibUUID.cmake index aece9f4cb8..d6c4163e96 100644 --- a/cmake/FindLibUUID.cmake +++ b/cmake/FindLibUUID.cmake @@ -1,6 +1,4 @@ if(NOT LIBUUID_FOUND) - message(STATUS "NOT FOUND") - find_path(LIBUUID_INCLUDE_DIR NAMES uuid.h PATH_SUFFIXES uuid diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ec72df1a1..cc437eb7cd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,6 +70,7 @@ set (common_sources cfg.cc cpu_feature.c fiob.c + tt_uuid.c ffisyms.cc lua/init.cc lua/fiber.cc diff --git a/src/admin.cc b/src/admin.cc index 130e053821..7def35ec83 100644 --- a/src/admin.cc +++ b/src/admin.cc @@ -97,7 +97,7 @@ admin_handler(va_list ap) for (;;) { if (admin_dispatch(&coio, iobuf, L) < 0) return; - iobuf_gc(iobuf); + iobuf_reset(iobuf); fiber_gc(); } } diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt index 600f848a2b..70d1f31bd6 100644 --- a/src/box/CMakeLists.txt +++ b/src/box/CMakeLists.txt @@ -40,6 +40,7 @@ add_library(box box.cc access.cc authentication.cc + cluster.cc ${lua_sources} lua/call.cc lua/tuple.cc diff --git a/src/box/alter.cc b/src/box/alter.cc index e866787032..d1d86885c8 100644 --- a/src/box/alter.cc +++ b/src/box/alter.cc @@ -38,7 +38,7 @@ #include <new> /* for placement new */ #include <stdio.h> /* snprintf() */ #include <ctype.h> -#include "recovery.h" /* for on_replace_dd_schema trigger */ +#include "cluster.h" /* for cluster_set_uuid() */ /** _space columns */ #define ID 0 @@ -1498,25 +1498,38 @@ on_replace_dd_priv(struct trigger * /* trigger */, void *event) /* {{{ cluster configuration */ +/** + * Parse a tuple field which is expected to contain a string + * representation of UUID, and return a 16-byte representation. + */ +tt_uuid +tuple_field_uuid(struct tuple *tuple, int fieldno) +{ + const char *value = tuple_field_cstr(tuple, fieldno); + tt_uuid uuid; + if (tt_uuid_from_string(value, &uuid) != 0) + tnt_raise(ClientError, ER_INVALID_UUID, value); + return uuid; +} + +/** + * This trigger is normally invoked only upon initial recovery. + * + * Before a cluster is assigned a cluster id it's read only. + */ static void on_replace_dd_schema(struct trigger * /* trigger */, void *event) { struct txn *txn = (struct txn *) event; struct tuple *old_tuple = txn->old_tuple; struct tuple *new_tuple = txn->new_tuple; - const char *key = tuple_field_cstr(new_tuple ? new_tuple : old_tuple,0); + const char *key = tuple_field_cstr(new_tuple ? + new_tuple : old_tuple, 0); if (strcmp(key, "cluster") == 0) { if (old_tuple != NULL || new_tuple == NULL) - tnt_raise(IllegalParams, "'cluster' value is read-only"); - - const char *value = tuple_field_cstr(new_tuple, 1); - uuid_t cluster_uuid; - if (uuid_parse(value, cluster_uuid) != 0) - tnt_raise(IllegalParams, "invalid 'cluster' value"); - - /* Set Cluster-UUID (can only be done from snapshot) */ - assert(uuid_is_null(recovery_state->cluster_uuid)); - uuid_copy(recovery_state->cluster_uuid, cluster_uuid); + tnt_raise(ClientError, ER_CLUSTER_ID_IS_RO); + tt_uuid uu = tuple_field_uuid(new_tuple, 1); + cluster_set_id(&uu); } } @@ -1527,35 +1540,49 @@ on_commit_dd_cluster(struct trigger *trigger, void *event) (void) trigger; struct txn *txn = (struct txn *) event; uint32_t node_id = tuple_field_u32(txn->new_tuple, 0); - uuid_t node_uuid; - uuid_parse(tuple_field_cstr(txn->new_tuple, 1), node_uuid); + tt_uuid node_uuid = tuple_field_uuid(txn->new_tuple, 1); - recovery_confirm_node(recovery_state, node_uuid, node_id); + cluster_add_node(&node_uuid, node_id); } static struct trigger commit_cluster_trigger = { rlist_nil, on_commit_dd_cluster, NULL, NULL }; /** - * A trigger invoked on replace in the space containing cluster configration. + * A trigger invoked on replace in the space _cluster, + * which contains cluster configuration. + * + * The space is modified by JOIN command in IPROTO + * protocol. + * + * The trigger updates the cluster configuration cache + * with uuid of the newly joined node. + * + * During recovery, it acts the same way, loading identifiers + * of all nodes into the node cache. Node globally unique + * identifiers are used to keep track of cluster configuration, + * so that a node that previously joined the cluster can + * follow updates, and a node that belongs to a different + * cluster can not by mistake join/follow another cluster + * without first being reset (emptied). */ static void on_replace_dd_cluster(struct trigger *trigger, void *event) { (void) trigger; struct txn *txn = (struct txn *) event; - if (txn->old_tuple != NULL || txn->new_tuple == NULL) - tnt_raise(IllegalParams, "can't change Node-UUID!"); + struct tuple *old_tuple = txn->old_tuple; + struct tuple *new_tuple = txn->new_tuple; + if (old_tuple != NULL || new_tuple == NULL) + tnt_raise(ClientError, ER_NODE_ID_IS_RO); /* Check fields */ - uint32_t node_id = tuple_field_u32(txn->new_tuple, 0); - if (node_id == 0) - tnt_raise(IllegalParams, "invalid Node-ID!"); - - uuid_t node_uuid; - if (uuid_parse(tuple_field_cstr(txn->new_tuple, 1), node_uuid) != 0 || - uuid_is_null(node_uuid)) - tnt_raise(IllegalParams, "invalid Node-UUID!"); + uint32_t node_id = tuple_field_u32(new_tuple, 0); + if (cnode_id_is_reserved(node_id)) + tnt_raise(IllegalParams, "Invalid Node-Id"); + tt_uuid node_uuid = tuple_field_uuid(new_tuple, 1); + if (tt_uuid_is_nil(&node_uuid)) + tnt_raise(ClientError, ER_INVALID_UUID, tt_uuid_str(&node_uuid)); trigger_set(&txn->on_commit, &commit_cluster_trigger); } diff --git a/src/box/box.cc b/src/box/box.cc index e99e10b1ce..5b9c895d36 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -277,12 +277,14 @@ box_leave_local_standby_mode(void *data __attribute__((unused))) } /** - * @brief Called when recovery/replication wants to add a new node to cluster. - * recovery_confirm_node() must be called after insert. + * @brief Called when recovery/replication wants to add a new node + * to cluster. + * cluster_add_node() is called as a commit trigger on _cluster + * space and actually adds the node to the cluster. * @param node_uuid */ static void -box_on_cluster_join(uuid_t node_uuid) +box_on_cluster_join(const tt_uuid *node_uuid) { struct space *space = space_cache_find(SC_CLUSTER_ID); class Index *index = index_find(space, 0); @@ -298,7 +300,7 @@ box_on_cluster_join(uuid_t node_uuid) char *data = buf; data = mp_encode_array(data, 2); data = mp_encode_uint(data, node_id); - data = mp_encode_str(data, uuid_str(node_uuid), UUID_STR_LEN); + data = mp_encode_str(data, tt_uuid_str(node_uuid), UUID_STR_LEN); assert(data <= buf + sizeof(buf)); req.tuple = buf; req.tuple_end = data; @@ -309,8 +311,8 @@ static void box_set_cluster_uuid(struct recovery_state *r) { /* Save Cluster-UUID to _schema space */ - uuid_t cluster_uuid; - uuid_generate(cluster_uuid); + tt_uuid cluster_uuid; + tt_uuid_create(&cluster_uuid); const char *key = "cluster"; struct request req; @@ -320,7 +322,7 @@ box_set_cluster_uuid(struct recovery_state *r) char *data = buf; data = mp_encode_array(data, 2); data = mp_encode_str(data, key, strlen(key)); - data = mp_encode_str(data, uuid_str(cluster_uuid), UUID_STR_LEN); + data = mp_encode_str(data, tt_uuid_str(&cluster_uuid), UUID_STR_LEN); assert(data <= buf + sizeof(buf)); req.tuple = buf; req.tuple_end = data; @@ -328,7 +330,7 @@ box_set_cluster_uuid(struct recovery_state *r) process_rw(&null_port, &req); /* Cluster-UUID was be updated by a _schema trigger */ - assert(uuid_compare(r->cluster_uuid, cluster_uuid) == 0); + assert(tt_uuid_cmp(&r->cluster_uuid, &cluster_uuid) == 0); } void @@ -402,15 +404,12 @@ box_init() snapshot_save(recovery_state); } - if (uuid_is_null(recovery_state->cluster_uuid)) + if (tt_uuid_is_nil(&recovery_state->cluster_uuid)) tnt_raise(ClientError, ER_INVALID_CLUSTER); space_end_recover_snapshot(); space_end_recover(); - say_debug("node: %s", uuid_str(recovery_state->node_uuid)); - say_debug("cluster: %s", uuid_str(recovery_state->cluster_uuid)); - stat_cleanup(stat_base, IPROTO_DML_REQUEST_MAX); title("orphan", NULL); recovery_follow_local(recovery_state, diff --git a/src/box/cluster.cc b/src/box/cluster.cc new file mode 100644 index 0000000000..b4be84de8e --- /dev/null +++ b/src/box/cluster.cc @@ -0,0 +1,75 @@ +/* + * 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 "cluster.h" +#include "recovery.h" +#include "exception.h" + +void +cluster_set_id(const tt_uuid *uu) +{ + /* Set cluster UUID. */ + assert(tt_uuid_is_nil(&recovery_state->cluster_uuid)); + recovery_state->cluster_uuid = *uu; +} + +void +cluster_add_node(const tt_uuid *node_uuid, cnode_id_t node_id) +{ + struct recovery_state *r = recovery_state; + + assert(!tt_uuid_is_nil(node_uuid)); + assert(!cnode_id_is_reserved(node_id)); + + /* Add node */ + struct node *node = (struct node *) calloc(1, sizeof(*node)); + if (node == NULL) { + tnt_raise(ClientError, ER_MEMORY_ISSUE, sizeof(*node), + "recovery", "r->cluster"); + } + node->id = node_id; + node->uuid = *node_uuid; + uint32_t k = mh_cluster_put(recovery_state->cluster, + (const struct node **) &node, NULL, NULL); + if (k == mh_end(recovery_state->cluster)) { + free(node); + tnt_raise(ClientError, ER_MEMORY_ISSUE, sizeof(*node), + "recovery", "r->cluster"); + } + + say_debug("confirm node: {uuid = %s, id = %u}", + tt_uuid_str(node_uuid), node_id); + + /* Confirm Local node */ + if (tt_uuid_cmp(&r->node_uuid, node_uuid) == 0) { + /* Confirm Local Node */ + say_info("synchronized with cluster"); + assert(r->local_node == NULL || r->local_node->id == 0); + r->local_node = node; + } +} diff --git a/src/box/cluster.h b/src/box/cluster.h new file mode 100644 index 0000000000..40d6314104 --- /dev/null +++ b/src/box/cluster.h @@ -0,0 +1,107 @@ +#ifndef INCLUDES_BOX_CLUSTER_H +#define INCLUDES_BOX_CLUSTER_H +/* + * 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 "tt_uuid.h" +#include <stdint.h> +/** + * @module cluster - global state of multi-master + * replicated database. + * + * Right now the cluster can only consist of instances + * connected with asynchronous master-master replication. + * + * Each cluster has a globally unique identifier. Each + * node in the cluster is identified as well. A node + * which is part of one cluster can not join another + * cluster. + * + * Cluster and node identifiers are stored in a system + * space _cluster on all nodes. The node identifier + * is also stored in each snapshot header, this is how + * the node knows which node id in the cluster belongs + * to it. + * + * Cluster and node identifiers are globally unique + * (UUID, universally unique identifiers). In addition + * to a long UUID, which is stored in _cluster system + * space for each node, a short integer id is used for + * pervasive node identification in a replication stream, + * a snapshot, or internal data structures. + * The mapping between 16-byte node globally unique id and + * 4 byte cluster local id is stored in _cluster table. When + * a node joins the cluster, it sends its globally unique + * identifier to one of the masters, and gets its cluster + * local identifier as part of the reply to the JOIN request + * (in fact, it gets it as a REPLACE request in _cluster + * system space along with the rest of the replication + * stream). + * + * Cluster state on each node is represented by a table + * like below: + * + * ---------------------------------- + * | node id | confirmed lsn | + * ---------------------------------- + * | 1 | 1258 | <-- changes of the local node + * ---------------------------------- + * | 2 | 1292 | <-- changes received from + * ---------------------------------- a remote node + */ + +/** Cluster-local node identifier. */ +typedef uint32_t cnode_id_t; + +static inline bool +cnode_id_is_reserved(cnode_id_t id) +{ + return id == 0; +} + +/** + * Bootstrap a new cluster consisting of this node by + * assigning it a new globally unique cluster id. Used + * during bootstrapping in an empty data directory when no + * existing cluster for joining has been provided in the + * database configuration. + */ +void +cluster_set_id(const tt_uuid *uu); + +/** + * Register the universally unique identifier of a remote node and + * a matching cluster-local identifier in the cluster registry. + * Called when a remote master joins the cluster. + * + * The node is added to the cluster lsn table with LSN 0. + */ +void +cluster_add_node(const tt_uuid *node_uu, cnode_id_t id); + +#endif diff --git a/src/box/txn.cc b/src/box/txn.cc index a99dea7a1a..91f43ab93b 100644 --- a/src/box/txn.cc +++ b/src/box/txn.cc @@ -30,7 +30,8 @@ #include "tuple.h" #include "space.h" #include <tarantool.h> -#include <recovery.h> +#include "cluster.h" +#include "recovery.h" #include <fiber.h> #include "request.h" /* for request_name */ diff --git a/src/errcode.h b/src/errcode.h index 74ff5c1e62..1130318193 100644 --- a/src/errcode.h +++ b/src/errcode.h @@ -113,8 +113,9 @@ enum { TNT_ERRMSG_MAX = 512 }; /* 61 */_(ER_LOCAL_NODE_IS_NOT_ACTIVE, 2, "Local node is not active") \ /* 62 */_(ER_UNKNOWN_NODE, 2, "Unknown node %u") \ /* 63 */_(ER_INVALID_CLUSTER, 2, "Invalid cluster id") \ - - + /* 64 */_(ER_INVALID_UUID, 2, "Invalid UUID: %s") \ + /* 65 */_(ER_CLUSTER_ID_IS_RO, 2, "Can't reset cluster id: it is already assigned") \ + /* 66 */_(ER_NODE_ID_IS_RO, 2, "Can't reset node id") \ /* * !IMPORTANT! Please follow instructions at start of the file diff --git a/src/iobuf.cc b/src/iobuf.cc index f47e33dc5e..d4837d673a 100644 --- a/src/iobuf.cc +++ b/src/iobuf.cc @@ -320,7 +320,7 @@ iobuf_flush(struct iobuf *iobuf, struct ev_io *coio) ssize_t total = coio_writev(coio, iobuf->out.iov, obuf_iovcnt(&iobuf->out), obuf_size(&iobuf->out)); - iobuf_gc(iobuf); + iobuf_reset(iobuf); /* * If there is some residue in the input buffer, move it * but only in case if we don't have iobuf_readahead @@ -335,7 +335,7 @@ iobuf_flush(struct iobuf *iobuf, struct ev_io *coio) } void -iobuf_gc(struct iobuf *iobuf) +iobuf_reset(struct iobuf *iobuf) { /* * If we happen to have fully processed the input, diff --git a/src/iobuf.h b/src/iobuf.h index 0bd43b3cd2..25d97babc8 100644 --- a/src/iobuf.h +++ b/src/iobuf.h @@ -226,7 +226,7 @@ iobuf_flush(struct iobuf *iobuf, struct ev_io *coio); * Is automatically called by iobuf_flush(). */ void -iobuf_gc(struct iobuf *iobuf); +iobuf_reset(struct iobuf *iobuf); /** Return true if there is no input and no output. */ static inline bool diff --git a/src/iproto.cc b/src/iproto.cc index 158ca4e32a..7f1be78104 100644 --- a/src/iproto.cc +++ b/src/iproto.cc @@ -615,7 +615,7 @@ iproto_flush(struct iobuf *iobuf, int fd, struct obuf_svp *svp) if (nwr > 0) { if (svp->size + nwr == obuf_size(&iobuf->out)) { - iobuf_gc(iobuf); + iobuf_reset(iobuf); *svp = obuf_create_svp(&iobuf->out); return 0; } diff --git a/src/log_io.cc b/src/log_io.cc index e48408d8d7..eb291c7b49 100644 --- a/src/log_io.cc +++ b/src/log_io.cc @@ -143,8 +143,9 @@ log_dir_add_to_index(struct log_dir *dir, int64_t lsnsum) /* * Open xlog to find SETLSN */ - uuid_t uuid; - struct log_io *wal = log_io_open_for_read(dir, lsnsum, uuid, INPROGRESS); + tt_uuid uuid; + struct log_io *wal = log_io_open_for_read(dir, lsnsum, &uuid, + INPROGRESS); if (wal == NULL) return -1; auto log_guard = make_scoped_guard([&]{ @@ -870,13 +871,11 @@ log_io_sync(struct log_io *l) #define NODE_UUID_KEY "Node" static int -log_io_write_meta(struct log_io *l, const uuid_t node_uuid) +log_io_write_meta(struct log_io *l, const tt_uuid *node_uuid) { - char uuid_str[UUID_STR_LEN + 1]; - uuid_unparse(node_uuid, uuid_str); - if (fprintf(l->f, "%s%s", l->dir->filetype, v12) < 0 || - fprintf(l->f, NODE_UUID_KEY ": %s\n\n", uuid_str) < 0) { + fprintf(l->f, NODE_UUID_KEY ": %s\n\n", + tt_uuid_str(node_uuid)) < 0) { return -1; } @@ -892,7 +891,8 @@ log_io_write_meta(struct log_io *l, const uuid_t node_uuid) * @return 0 if success, -1 on error. */ static int -log_io_verify_meta(struct log_io *l, uuid_t node_uuid, const char **errmsg) +log_io_verify_meta(struct log_io *l, tt_uuid *node_uuid, + const char **errmsg) { char filetype[32], version[32], buf[256]; struct log_dir *dir = l->dir; @@ -934,7 +934,7 @@ log_io_verify_meta(struct log_io *l, uuid_t node_uuid, const char **errmsg) if (strcmp(key, NODE_UUID_KEY) == 0) { if ((end - val) != UUID_STR_LEN || - uuid_parse(val, node_uuid) != 0) { + tt_uuid_from_string(val, node_uuid) != 0) { *errmsg = "can't parse node uuid"; goto error; } @@ -949,7 +949,7 @@ log_io_verify_meta(struct log_io *l, uuid_t node_uuid, const char **errmsg) struct log_io * log_io_open(struct log_dir *dir, enum log_mode mode, const char *filename, - uuid_t node_uuid, enum log_suffix suffix, FILE *file) + tt_uuid *node_uuid, enum log_suffix suffix, FILE *file) { struct log_io *l = NULL; int save_errno; @@ -995,8 +995,8 @@ log_io_open(struct log_dir *dir, enum log_mode mode, const char *filename, } struct log_io * -log_io_open_for_read(struct log_dir *dir, int64_t lsnsum, uuid_t node_uuid, - enum log_suffix suffix) +log_io_open_for_read(struct log_dir *dir, int64_t lsnsum, + tt_uuid *node_uuid, enum log_suffix suffix) { const char *filename = format_filename(dir, lsnsum, suffix); FILE *f = fopen(filename, "r"); @@ -1012,7 +1012,7 @@ log_io_open_for_read(struct log_dir *dir, int64_t lsnsum, uuid_t node_uuid, * and sets errno. */ struct log_io * -log_io_open_for_write(struct log_dir *dir, int64_t lsn, uuid_t node_uuid, +log_io_open_for_write(struct log_dir *dir, int64_t lsn, tt_uuid *node_uuid, enum log_suffix suffix) { char *filename; diff --git a/src/log_io.h b/src/log_io.h index b5196b1230..adc783c725 100644 --- a/src/log_io.h +++ b/src/log_io.h @@ -35,7 +35,9 @@ #include "trivia/util.h" #include "third_party/tarantool_ev.h" #include "iproto_constants.h" -#include "uuid/uuid.h" +#include "tt_uuid.h" + +extern const uint32_t xlog_format; enum log_mode { LOG_READ, @@ -151,14 +153,14 @@ struct log_io { }; struct log_io * -log_io_open_for_read(struct log_dir *dir, int64_t lsn, uuid_t node_uuid, +log_io_open_for_read(struct log_dir *dir, int64_t lsn, tt_uuid *node_uuid, enum log_suffix suffix); struct log_io * -log_io_open_for_write(struct log_dir *dir, int64_t lsn, uuid_t node_uuid, - enum log_suffix suffix); +log_io_open_for_write(struct log_dir *dir, int64_t lsn, + tt_uuid *node_uuid, enum log_suffix suffix); struct log_io * log_io_open(struct log_dir *dir, enum log_mode mode, const char *filename, - uuid_t node_uuid, enum log_suffix suffix, FILE *file); + tt_uuid *node_uuid, enum log_suffix suffix, FILE *file); int log_io_sync(struct log_io *l); int diff --git a/src/lua/info.cc b/src/lua/info.cc index 0b8e4d0464..4c523db4ad 100644 --- a/src/lua/info.cc +++ b/src/lua/info.cc @@ -65,7 +65,7 @@ lbox_info_recovery_last_update_tstamp(struct lua_State *L) static int lbox_info_node(struct lua_State *L) { - lua_pushlstring(L, uuid_str(recovery_state->node_uuid), UUID_STR_LEN); + lua_pushlstring(L, tt_uuid_str(&recovery_state->node_uuid), UUID_STR_LEN); return 1; } @@ -77,7 +77,7 @@ lbox_info_cluster(struct lua_State *L) uint32_t k; mh_foreach(recovery_state->cluster, k) { struct node *node = *mh_cluster_node(recovery_state->cluster,k); - lua_pushlstring(L, uuid_str(node->uuid), UUID_STR_LEN); + lua_pushlstring(L, tt_uuid_str(&node->uuid), UUID_STR_LEN); luaL_pushnumber64(L, node->confirmed_lsn); lua_settable(L, -3); } diff --git a/src/recovery.cc b/src/recovery.cc index 6752ab12d1..4a06d01cc7 100644 --- a/src/recovery.cc +++ b/src/recovery.cc @@ -45,6 +45,7 @@ #include "iproto_constants.h" #include "crc32.h" #include "scoped_guard.h" +#include "box/cluster.h" /* * Recovery subsystem @@ -195,11 +196,10 @@ confirm_lsn(struct node *node, int64_t lsn, bool is_commit) if (node->confirmed_lsn < lsn) { if (is_commit) { if (node->confirmed_lsn + 1 != lsn) { - char uuid_str[UUID_STR_LEN + 1]; - uuid_unparse(node->uuid, uuid_str); - say_warn("non consecutive LSN for %s " + say_warn("non consecutive LSN for node %u (%s) " "confirmed: %jd, new: %jd, diff: %jd", - uuid_str, + (unsigned) node->id, + tt_uuid_str(&node->uuid), (intmax_t) node->confirmed_lsn, (intmax_t) lsn, (intmax_t) (lsn - node->confirmed_lsn)); @@ -207,15 +207,13 @@ confirm_lsn(struct node *node, int64_t lsn, bool is_commit) node->confirmed_lsn = lsn; } } else { - /* + /* * There can be holes in * confirmed_lsn, in case of disk write failure, but * wal_writer never confirms LSNs out order. */ - char uuid_str[UUID_STR_LEN + 1]; - uuid_unparse(node->uuid, uuid_str); panic("LSN for %s is used twice or COMMIT order is broken: " - "confirmed: %jd, new: %jd", uuid_str, + "confirmed: %jd, new: %jd", tt_uuid_str(&node->uuid), (intmax_t) node->confirmed_lsn, (intmax_t) lsn); } } @@ -284,7 +282,7 @@ recovery_init(const char *snap_dirname, const char *wal_dirname, if (node == NULL) panic("cannot allocate struct node"); node->id = 0; - assert(uuid_is_null(node->uuid)); + assert(tt_uuid_is_nil(&node->uuid)); uint32_t k = mh_cluster_put(r->cluster, (const struct node **) &node, NULL, NULL); if (k == mh_end(r->cluster)) @@ -426,55 +424,19 @@ recovery_process(struct recovery_state *r, struct iproto_packet *packet) return r->row_handler(r->row_handler_param, packet); } -void -recovery_confirm_node(struct recovery_state *r, uuid_t node_uuid, - uint32_t node_id) -{ - /* Node-Id must be unique */ - assert(mh_cluster_find(r->cluster, node_id, NULL) == mh_end(r->cluster)); - assert(!uuid_is_null(node_uuid)); - assert(node_id != 0); - - /* Add node */ - struct node *node = (struct node *) calloc(1, sizeof(*node)); - if (node == NULL) { - tnt_raise(ClientError, ER_MEMORY_ISSUE, sizeof(*node), - "recovery", "r->cluster"); - } - node->id = node_id; - memcpy(node->uuid, node_uuid, sizeof(uuid_t)); - uint32_t k = mh_cluster_put(recovery_state->cluster, - (const struct node **) &node, NULL, NULL); - if (k == mh_end(recovery_state->cluster)) { - free(node); - tnt_raise(ClientError, ER_MEMORY_ISSUE, sizeof(*node), - "recovery", "r->cluster"); - } - - say_debug("confirm node: {uuid = %s, id = %u}", - uuid_str(node_uuid), node_id); - - if (uuid_compare(r->node_uuid, node_uuid) == 0) { - /* Confirm Local Node */ - say_info("synchronized with cluster"); - assert(r->local_node == NULL || r->local_node->id == 0); - r->local_node = node; - } -} - void cluster_bootstrap(struct recovery_state *r) { /* Generate Node-UUID */ - uuid_generate(r->node_uuid); + tt_uuid_create(&r->node_uuid); /* Recover from bootstrap.snap */ say_info("initializing cluster"); FILE *f = fmemopen((void *) &bootstrap_bin, sizeof(bootstrap_bin), "r"); - uuid_t bootstrap_uuid; /* ignored */ + tt_uuid bootstrap_uuid; /* ignored */ struct log_io *snap = log_io_open(&r->snap_dir, LOG_READ, - "bootstrap.snap", bootstrap_uuid, NONE, f); + "bootstrap.snap", &bootstrap_uuid, NONE, f); assert(snap != NULL); auto snap_guard = make_scoped_guard([&]{ log_io_close(&snap); @@ -486,10 +448,10 @@ cluster_bootstrap(struct recovery_state *r) panic("failed to bootstrap data directory"); /* Initialize local node */ - r->join_handler(r->node_uuid); + r->join_handler(&r->node_uuid); assert(r->local_node != NULL); assert(r->local_node->id == 1); - assert(uuid_compare(r->local_node->uuid, r->node_uuid) == 0); + assert(tt_uuid_cmp(&r->local_node->uuid, &r->node_uuid) == 0); say_info("done"); } @@ -517,13 +479,13 @@ recover_snap(struct recovery_state *r) say_error("can't find snapshot"); goto error; } - snap = log_io_open_for_read(&r->snap_dir, lsn, r->node_uuid, NONE); + snap = log_io_open_for_read(&r->snap_dir, lsn, &r->node_uuid, NONE); if (snap == NULL) { say_error("can't find/open snapshot"); goto error; } - if (uuid_is_null(r->node_uuid)) { + if (tt_uuid_is_nil(&r->node_uuid)) { say_error("can't find node uuid in snapshot"); goto error; } @@ -646,7 +608,7 @@ recover_remaining_wals(struct recovery_state *r) goto find_next_wal; } next_wal = log_io_open(&r->wal_dir, LOG_READ, filename, - r->node_uuid, suffix, f); + &r->node_uuid, suffix, f); /* * When doing final recovery, and dealing with the * last file, try opening .<ext>.inprogress. @@ -1227,7 +1189,7 @@ wal_opt_rotate(struct log_io **wal, struct fio_batch *batch, if (l == NULL) { /* Open WAL with '.inprogress' suffix. */ int64_t lsnsum = mh_cluster_current_sum(cluster); - l = log_io_open_for_write(&r->wal_dir, lsnsum, r->node_uuid, + l = log_io_open_for_write(&r->wal_dir, lsnsum, &r->node_uuid, INPROGRESS); if (l != NULL) { if (wal_write_setlsn(l, batch, cluster) != 0) @@ -1516,7 +1478,7 @@ snapshot_save(struct recovery_state *r) assert(r->snapshot_handler != NULL); struct log_io *snap; int64_t lsnsum = mh_cluster_current_sum(r->cluster); - snap = log_io_open_for_write(&r->snap_dir, lsnsum, r->node_uuid, + snap = log_io_open_for_write(&r->snap_dir, lsnsum, &r->node_uuid, INPROGRESS); if (snap == NULL) panic_status(errno, "Failed to save snapshot: failed to open file in write mode."); diff --git a/src/recovery.h b/src/recovery.h index 996a84331d..2b8a7e9884 100644 --- a/src/recovery.h +++ b/src/recovery.h @@ -33,7 +33,7 @@ #include "trivia/util.h" #include "third_party/tarantool_ev.h" #include "log_io.h" -#include <uuid/uuid.h> +#include "tt_uuid.h" #if defined(__cplusplus) extern "C" { @@ -44,7 +44,7 @@ struct tbuf; typedef void (row_handler)(void *, struct iproto_packet *packet); typedef void (snapshot_handler)(struct log_io *); -typedef void (join_handler)(uuid_t node_uuid); +typedef void (join_handler)(const tt_uuid *node_uuid); /** A "condition variable" that allows fibers to wait when a given * LSN makes it to disk. @@ -64,7 +64,7 @@ extern const char *wal_mode_STRS[]; */ struct node { uint32_t id; - uuid_t uuid; + tt_uuid uuid; int64_t current_lsn; int64_t confirmed_lsn; }; @@ -112,8 +112,8 @@ struct recovery_state { int rows_per_wal; double wal_fsync_delay; enum wal_mode wal_mode; - uuid_t node_uuid; - uuid_t cluster_uuid; + tt_uuid node_uuid; + tt_uuid cluster_uuid; bool finalize; }; @@ -146,8 +146,6 @@ int wal_write(struct recovery_state *r, struct iproto_packet *packet); void recovery_setup_panic(struct recovery_state *r, bool on_snap_error, bool on_wal_error); void recovery_process(struct recovery_state *r, struct iproto_packet *packet); -void recovery_confirm_node(struct recovery_state *r, uuid_t node_uuid, - uint32_t node_id); void recovery_fix_lsn(struct recovery_state *r, bool master_bootstrap); struct fio_batch; diff --git a/src/replica.cc b/src/replica.cc index 94f25f7978..7ae0355eec 100644 --- a/src/replica.cc +++ b/src/replica.cc @@ -28,7 +28,6 @@ */ #include "recovery.h" #include "tarantool.h" - #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -120,7 +119,7 @@ replica_bootstrap(struct recovery_state *r, const char *replication_source) say_info("bootstrapping replica"); /* Generate Node-UUID */ - uuid_generate(r->node_uuid); + tt_uuid_create(&r->node_uuid); char ip_addr[32]; char greeting[IPROTO_GREETING_SIZE]; @@ -155,8 +154,8 @@ replica_bootstrap(struct recovery_state *r, const char *replication_source) char *data = buf; data = mp_encode_map(data, 1); data = mp_encode_uint(data, IPROTO_NODE_UUID); - data = mp_encode_str(data, (const char *) recovery_state->node_uuid, - sizeof(uuid_t)); + data = mp_encode_str(data, (const char *) &recovery_state->node_uuid, + sizeof(tt_uuid)); assert(data <= buf + sizeof(buf)); packet.body[0].iov_base = buf; @@ -213,9 +212,11 @@ remote_connect(struct recovery_state *r, struct ev_io *coio,const char **err) char *data = buf; data = mp_encode_map(data, 3); data = mp_encode_uint(data, IPROTO_CLUSTER_UUID); - data = mp_encode_str(data, (const char *) r->cluster_uuid, sizeof(uuid_t)); + data = mp_encode_str(data, (const char *) &r->cluster_uuid, + sizeof(tt_uuid)); data = mp_encode_uint(data, IPROTO_NODE_UUID); - data = mp_encode_str(data, (const char *) r->node_uuid, sizeof(uuid_t)); + data = mp_encode_str(data, (const char *) &r->node_uuid, + sizeof(tt_uuid)); data = mp_encode_uint(data, IPROTO_LSNMAP); data = mp_encode_map(data, cluster_size); uint32_t k; @@ -274,7 +275,7 @@ pull_from_remote(va_list ap) recovery_process(r, &packet); - iobuf_gc(iobuf); + iobuf_reset(iobuf); fiber_gc(); } catch (FiberCancelException *e) { title("replica", "%s/%s", r->remote->source, "failed"); diff --git a/src/replication.cc b/src/replication.cc index 3149a1269a..5f72b453a4 100644 --- a/src/replication.cc +++ b/src/replication.cc @@ -227,8 +227,7 @@ replication_join(int fd, struct iproto_packet *packet) if (mp_check(&d, end) != 0 || mp_typeof(*data) != MP_MAP) tnt_raise(ClientError, ER_INVALID_MSGPACK, "JOIN body"); - uuid_t node_uuid; - memset(node_uuid, 0, sizeof(node_uuid)); + tt_uuid node_uuid = uuid_nil; d = data; uint32_t map_size = mp_decode_map(&d); for (uint32_t i = 0; i < map_size; i++) { @@ -240,26 +239,24 @@ replication_join(int fd, struct iproto_packet *packet) uint8_t key = mp_decode_uint(&d); if (key == IPROTO_NODE_UUID) { if (mp_typeof(*d) != MP_STR || - mp_decode_strl(&d) != sizeof(uuid_t)) { + mp_decode_strl(&d) != sizeof(tt_uuid)) { tnt_raise(ClientError, ER_INVALID_MSGPACK, "invalid Node-UUID"); } - memcpy(node_uuid, d, sizeof(uuid_t)); - d += sizeof(uuid_t); + tt_uuid_set(&node_uuid, d); + d += sizeof(node_uuid); } else { mp_next(&d); /* value */ } } - if (uuid_is_null(node_uuid)) { + if (tt_uuid_is_nil(&node_uuid)) { tnt_raise(ClientError, ER_INVALID_MSGPACK, "Can't find Node-UUID in JOIN request"); } /* Notify box about new cluster node */ - char uuid_str[UUID_STR_LEN + 1]; - uuid_unparse(node_uuid, uuid_str); - recovery_state->join_handler(node_uuid); + recovery_state->join_handler(&node_uuid); struct replication_request *request = (struct replication_request *) malloc(sizeof(*request)); @@ -283,17 +280,14 @@ replication_subscribe(int fd, struct iproto_packet *packet) { assert(packet->code == IPROTO_SUBSCRIBE); if (packet->bodycnt == 0) - tnt_raise(ClientError, ER_INVALID_MSGPACK, "SUBSCRIBE body"); + tnt_raise(ClientError, ER_INVALID_MSGPACK, "subscribe body"); assert(packet->bodycnt == 1); const char *data = (const char *) packet->body[0].iov_base; const char *end = data + packet->body[0].iov_len; const char *d = data; if (mp_check(&d, end) != 0 || mp_typeof(*data) != MP_MAP) - tnt_raise(ClientError, ER_INVALID_MSGPACK, "SUBSCRIBE body"); - uuid_t cluster_uuid; - memset(cluster_uuid, 0, sizeof(cluster_uuid)); - uuid_t node_uuid; - memset(node_uuid, 0, sizeof(node_uuid)); + tnt_raise(ClientError, ER_INVALID_MSGPACK, "subscribe body"); + tt_uuid cluster_uuid = uuid_nil, node_uuid = uuid_nil; const char *lsnmap = NULL; d = data; @@ -308,20 +302,20 @@ replication_subscribe(int fd, struct iproto_packet *packet) switch (key) { case IPROTO_CLUSTER_UUID: if (mp_typeof(*d) != MP_STR || - mp_decode_strl(&d) != sizeof(uuid_t)) { + mp_decode_strl(&d) != sizeof(cluster_uuid)) { tnt_raise(ClientError, ER_INVALID_MSGPACK, "invalid Cluster-UUID"); } - memcpy(cluster_uuid, d, sizeof(cluster_uuid)); + tt_uuid_set(&cluster_uuid, d); d += sizeof(cluster_uuid); break; case IPROTO_NODE_UUID: if (mp_typeof(*d) != MP_STR || - mp_decode_strl(&d) != sizeof(uuid_t)) { + mp_decode_strl(&d) != sizeof(node_uuid)) { tnt_raise(ClientError, ER_INVALID_MSGPACK, "invalid Node-UUID"); } - memcpy(node_uuid, d, sizeof(node_uuid)); + tt_uuid_set(&node_uuid, d); d += sizeof(node_uuid); break; case IPROTO_LSNMAP: @@ -338,15 +332,16 @@ replication_subscribe(int fd, struct iproto_packet *packet) } /* Check Cluster-UUID */ - if (uuid_compare(cluster_uuid, recovery_state->cluster_uuid) != 0) - tnt_raise(ClientError, ER_INVALID_CLUSTER); - + if (tt_uuid_cmp(&cluster_uuid, &recovery_state->cluster_uuid) != 0) { + tnt_raise(ClientError, ER_INVALID_MSGPACK, + "Unknown Cluster-UUID"); + } /* Check Node-UUID */ struct node *node = NULL; uint32_t k; mh_foreach(recovery_state->cluster, k) { struct node *n = *mh_cluster_node(recovery_state->cluster, k); - if (uuid_compare(n->uuid, node_uuid) == 0) { + if (tt_uuid_cmp(&n->uuid, &node_uuid) == 0) { node = n; break; } diff --git a/src/trivia/util.h b/src/trivia/util.h index 6584b8b295..cb071e612a 100644 --- a/src/trivia/util.h +++ b/src/trivia/util.h @@ -34,7 +34,6 @@ #include <unistd.h> #include <inttypes.h> #include <assert.h> -#include "uuid/uuid.h" #if defined(__cplusplus) extern "C" { @@ -201,13 +200,6 @@ FILE * fmemopen(void *buf, size_t size, const char *mode); #endif /* HAVE_FMEMOPEN */ -enum { - UUID_STR_LEN = 36 /** Length of encoded UUID */ -}; - -char * -uuid_str(uuid_t uuid); - #if defined(__cplusplus) } /* extern "C" */ #endif /* defined(__cplusplus) */ diff --git a/src/tt_uuid.c b/src/tt_uuid.c new file mode 100644 index 0000000000..502809c672 --- /dev/null +++ b/src/tt_uuid.c @@ -0,0 +1,40 @@ +/* + * 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 "tt_uuid.h" +/* Zeroed by the linker. */ +tt_uuid uuid_nil; + +char * +tt_uuid_str(const struct tt_uuid *uu) +{ + static __thread char buf[UUID_STR_LEN + 1]; + tt_uuid_to_string(uu, buf); + return buf; +} + diff --git a/src/tt_uuid.h b/src/tt_uuid.h new file mode 100644 index 0000000000..2e934ebf25 --- /dev/null +++ b/src/tt_uuid.h @@ -0,0 +1,90 @@ +#ifndef TARANTOOL_UUID_H_INCLUDED +#define TARANTOOL_UUID_H_INCLUDED +/* + * 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 <uuid/uuid.h> +#include <string.h> +#include <stdbool.h> + +#if defined(__cplusplus) +extern "C" { +#endif + +enum { UUID_STR_LEN = 36 }; + +typedef struct tt_uuid { + uuid_t id; +} tt_uuid; + +extern tt_uuid uuid_nil; + +static inline void +tt_uuid_create(tt_uuid *uu) +{ + uuid_generate(uu->id); +} + +static inline int +tt_uuid_from_string(const char *in, tt_uuid *uu) +{ + return uuid_parse((char *) in, uu->id); +} + +static inline void +tt_uuid_to_string(const tt_uuid *uu, char *out) +{ + uuid_unparse(uu->id, out); +} + +static inline void +tt_uuid_set(tt_uuid *uu, const void *data) +{ + memcpy(uu->id, data, sizeof(uu->id)); +} + +char * +tt_uuid_str(const struct tt_uuid *uu); + +static inline bool +tt_uuid_cmp(const tt_uuid *lhs, const tt_uuid *rhs) +{ + return uuid_compare(lhs->id, rhs->id); +} + +static inline bool +tt_uuid_is_nil(const tt_uuid *uu) +{ + return uuid_is_null(uu->id); +} + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /* TARANTOOL_UUID_H_INCLUDED */ diff --git a/src/util.cc b/src/util.cc index 2651be13a9..1cf563abf2 100644 --- a/src/util.cc +++ b/src/util.cc @@ -525,11 +525,3 @@ addr2symbol(void *addr) } #endif /* HAVE_BFD */ - -char * -uuid_str(uuid_t uuid) -{ - static char buf[UUID_STR_LEN + 1]; - uuid_unparse(uuid, buf); - return buf; -} diff --git a/test/box/misc.result b/test/box/misc.result index a75da65f3d..eb279fe24f 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -193,70 +193,73 @@ end; ... t; --- -- - 'box.error.ER_FUNCTION_ACCESS_DENIED : 53' - - 'box.error.ER_CREATE_FUNCTION : 50' - - 'box.error.ER_NO_SUCH_INDEX : 35' - - 'box.error.ER_TUPLE_FOUND : 3' - - 'box.error.ER_UNKNOWN_NODE : 62' - - 'box.error.ER_CREATE_SPACE : 9' - - 'box.error.ER_LOCAL_NODE_IS_NOT_ACTIVE : 61' +- - 'box.error.ER_CREATE_FUNCTION : 50' - 'box.error.ER_PROC_RET : 21' - 'box.error.ER_TUPLE_FORMAT_LIMIT : 16' - - 'box.error.ER_FIELD_TYPE : 23' - - 'box.error.ER_CFG : 59' - - 'box.error.ER_UNKNOWN_SCHEMA_OBJECT : 49' - - 'box.error.ER_OK : 0' - - 'box.error.ER_NO_SUCH_ENGINE : 57' + - 'box.error.ER_FUNCTION_MAX : 54' - 'box.error.ER_TUPLE_NOT_FOUND : 4' - - 'box.error.ER_INDEX_ARITY : 39' - - 'box.error.ER_WAL_IO : 40' - - 'box.error.ER_USER_MAX : 56' - - 'box.error.ER_NO_SUCH_FUNCTION : 51' - - 'box.error.ER_INJECTION : 8' - - 'box.error.ER_DROP_PRIMARY_KEY : 17' - - 'box.error.ER_INDEX_TYPE : 13' + - 'box.error.ER_PASSWORD_MISMATCH : 47' + - 'box.error.ER_LAST_DROP : 15' - 'box.error.ER_ARG_TYPE : 26' - - 'box.error.ER_FUNCTION_MAX : 54' - 'box.error.ER_INVALID_CLUSTER : 63' - - 'box.error.ER_SPACE_ARITY : 38' - 'box.error.ER_INVALID_MSGPACK : 20' - - 'box.error.ER_SPACE_ACCESS_DENIED : 55' - - 'box.error.ER_KEY_PART_COUNT : 31' - 'box.error.ER_RELOAD_CFG : 58' - 'box.error.ER_USER_EXISTS : 46' - 'box.error.ER_MEMORY_ISSUE : 2' - 'box.error.ER_ILLEGAL_PARAMS : 1' - 'box.error.ER_KEY_FIELD_TYPE : 18' - 'box.error.ER_NONMASTER : 6' - - 'box.error.ER_UNKNOWN_REQUEST_TYPE : 48' - - 'box.error.ER_FIELD_TYPE_MISMATCH : 24' - - 'box.error.ER_MODIFY_INDEX : 14' - - 'box.error.ER_PASSWORD_MISMATCH : 47' - - 'box.error.ER_EXACT_MATCH : 19' - 'box.error.ER_NO_SUCH_USER : 45' - - 'box.error.ER_SECONDARY : 7' - - 'box.error.ER_FUNCTION_EXISTS : 52' + - 'box.error.ER_EXACT_MATCH : 19' - 'box.error.ER_CREATE_USER : 43' - - 'box.error.ER_ACCESS_DENIED : 42' - - 'box.error.ER_LAST_DROP : 15' - - 'box.error.ER_UPDATE_FIELD : 29' + - 'box.error.ER_FUNCTION_EXISTS : 52' + - 'box.error.ER_NO_SUCH_FUNCTION : 51' - 'box.error.ER_FIBER_STACK : 30' - - 'box.error.ER_UNKNOWN_UPDATE_OP : 28' - - 'box.error.ER_DROP_USER : 44' - - 'box.error.ER_UNSUPPORTED : 5' - - 'box.error.ER_NO_SUCH_FIELD : 37' + - 'box.error.ER_FUNCTION_ACCESS_DENIED : 53' + - 'box.error.ER_CFG : 59' - 'box.error.ER_TUPLE_NOT_ARRAY : 22' - - 'box.error.ER_NO_SUCH_SPACE : 36' + - 'box.error.ER_CLUSTER_ID_IS_RO : 65' - 'box.error.ER_MORE_THAN_ONE_TUPLE : 41' - - 'box.error.ER_ALTER_SPACE : 12' - - 'box.error.ER_NO_SUCH_PROC : 33' + - 'box.error.ER_NO_SUCH_SPACE : 36' + - 'box.error.ER_NO_SUCH_INDEX : 35' + - 'box.error.ER_TUPLE_FOUND : 3' + - 'box.error.ER_CREATE_SPACE : 9' + - 'box.error.ER_FIELD_TYPE : 23' + - 'box.error.ER_OK : 0' + - 'box.error.ER_INDEX_ARITY : 39' + - 'box.error.ER_WAL_IO : 40' + - 'box.error.ER_INJECTION : 8' + - 'box.error.ER_NO_SUCH_ENGINE : 57' + - 'box.error.ER_INDEX_TYPE : 13' + - 'box.error.ER_UNKNOWN_SCHEMA_OBJECT : 49' + - 'box.error.ER_SPACE_ACCESS_DENIED : 55' + - 'box.error.ER_KEY_PART_COUNT : 31' - 'box.error.ER_SPACE_EXISTS : 10' + - 'box.error.ER_UNKNOWN_NODE : 62' + - 'box.error.ER_MODIFY_INDEX : 14' + - 'box.error.ER_SECONDARY : 7' + - 'box.error.ER_NODE_ID_IS_RO : 66' + - 'box.error.ER_INVALID_UUID : 64' + - 'box.error.ER_FIELD_TYPE_MISMATCH : 24' + - 'box.error.ER_SPLICE : 25' + - 'box.error.ER_TUPLE_IS_TOO_LONG : 27' + - 'box.error.ER_DROP_SPACE : 11' + - 'box.error.ER_SPACE_ARITY : 38' + - 'box.error.ER_LOCAL_NODE_IS_NOT_ACTIVE : 61' + - 'box.error.ER_UNSUPPORTED : 5' + - 'box.error.ER_ACCESS_DENIED : 42' - 'box.error.ER_PROC_LUA : 32' + - 'box.error.ER_UPDATE_FIELD : 29' + - 'box.error.ER_NO_SUCH_FIELD : 37' + - 'box.error.ER_ALTER_SPACE : 12' + - 'box.error.ER_DROP_USER : 44' + - 'box.error.ER_UNKNOWN_UPDATE_OP : 28' + - 'box.error.ER_NO_SUCH_PROC : 33' - 'box.error.ER_SOPHIA : 60' - 'box.error.ER_NO_SUCH_TRIGGER : 34' - - 'box.error.ER_TUPLE_IS_TOO_LONG : 27' - - 'box.error.ER_SPLICE : 25' - - 'box.error.ER_DROP_SPACE : 11' + - 'box.error.ER_UNKNOWN_REQUEST_TYPE : 48' + - 'box.error.ER_DROP_PRIMARY_KEY : 17' + - 'box.error.ER_USER_MAX : 56' ... --# setopt delimiter '' -- A test case for Bug#901674 diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 072fe852d2..41ac98c10e 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -38,7 +38,7 @@ target_link_libraries(arena_mt.test small pthread) add_executable(pt_alloc.test pt_alloc.cc) target_link_libraries(pt_alloc.test small) add_executable(log_dir.test log_dir.cc test.c) -target_link_libraries(log_dir.test core small salad misc bitset msgpuck uuid +target_link_libraries(log_dir.test uuid core small salad misc bitset msgpuck ${LIBEV_LIBRARIES} ${LIBEIO_LIBRARIES} ${LIBCORO_LIBRARIES}) diff --git a/test/unit/log_dir.cc b/test/unit/log_dir.cc index ef1f6d0fa7..0dcf422585 100644 --- a/test/unit/log_dir.cc +++ b/test/unit/log_dir.cc @@ -14,7 +14,7 @@ extern "C" { #define header() note("*** %s ***", __func__) #define footer() note("*** %s: done ***", __func__) -uuid_t node_uuid; +tt_uuid node_uuid; static void testset_create(struct log_dir *dir, int64_t *files, int files_n, int node_n) @@ -53,7 +53,7 @@ testset_create(struct log_dir *dir, int64_t *files, int files_n, int node_n) } /* Write XLOG */ - struct log_io *l = log_io_open_for_write(dir, lsnsum, node_uuid, + struct log_io *l = log_io_open_for_write(dir, lsnsum, &node_uuid, INPROGRESS); int rc = wal_write_setlsn(l, batch, cluster); assert(rc == 0); @@ -234,7 +234,7 @@ main(int argc, char *argv[]) memory_init(); fiber_init(); crc32_init(); - uuid_generate(node_uuid); + tt_uuid_create(&node_uuid); plan(1); test1(); -- GitLab