[tarantool-patches] [PATCH 3/3] vinyl: implement support of replica local spaces

  • From: Vladimir Davydov <vdavydov.dev@xxxxxxxxx>
  • To: kostja@xxxxxxxxxxxxx
  • Date: Tue, 10 Jul 2018 16:43:27 +0300

Store replication group id in vylog and ignore spaces whose group_id
equals GROUP_LOCAL when relaying initial join rows.

Folow-up #3443
---
 src/box/vinyl.c                        | 13 ++++++------
 src/box/vy_log.c                       | 38 +++++++++++++++++++++++++++-------
 src/box/vy_log.h                       | 14 +++++++++----
 src/box/vy_lsm.c                       |  8 ++++---
 src/box/vy_lsm.h                       |  6 ++++--
 test/replication/local_spaces.result   |  9 +++++---
 test/replication/local_spaces.test.lua |  7 ++++---
 test/replication/suite.cfg             |  1 -
 test/unit/vy_point_lookup.c            |  2 +-
 test/vinyl/ddl.result                  |  5 -----
 test/vinyl/ddl.test.lua                |  3 ---
 11 files changed, 68 insertions(+), 38 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index b3c97196..1c5192ff 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -71,6 +71,7 @@
 #include "trigger.h"
 #include "checkpoint.h"
 #include "session.h"
+#include "replication.h" /* GROUP_LOCAL */
 #include "wal.h" /* wal_mode() */
 
 /**
@@ -595,11 +596,6 @@ vinyl_engine_check_space_def(struct space_def *def)
                         def->name, "engine does not support temporary flag");
                return -1;
        }
-       if (def->opts.group_id != 0) {
-               diag_set(ClientError, ER_ALTER_SPACE, def->name,
-                        "engine does not support replication groups");
-               return -1;
-       }
        return 0;
 }
 
@@ -724,7 +720,8 @@ vinyl_space_create_index(struct space *space, struct 
index_def *index_def)
        }
        struct vy_lsm *lsm = vy_lsm_new(&env->lsm_env, &env->cache_env,
                                        &env->mem_env, index_def,
-                                       space->format, pk);
+                                       space->format, pk,
+                                       space_group_id(space));
        if (lsm == NULL) {
                free(index);
                return NULL;
@@ -3135,6 +3132,10 @@ vy_send_lsm(struct vy_join_ctx *ctx, struct 
vy_lsm_recovery_info *lsm_info)
                /* Dropped or not yet built LSM tree. */
                return 0;
        }
+       if (lsm_info->group_id == GROUP_LOCAL) {
+               /* Replica local space. */
+               return 0;
+       }
 
        /*
         * We are only interested in the primary index LSM tree.
diff --git a/src/box/vy_log.c b/src/box/vy_log.c
index 760a253d..fbbc7a7f 100644
--- a/src/box/vy_log.c
+++ b/src/box/vy_log.c
@@ -83,6 +83,7 @@ enum vy_log_key {
        VY_LOG_KEY_CREATE_LSN           = 12,
        VY_LOG_KEY_MODIFY_LSN           = 13,
        VY_LOG_KEY_DROP_LSN             = 14,
+       VY_LOG_KEY_GROUP_ID             = 15,
 };
 
 /** vy_log_key -> human readable name. */
@@ -102,6 +103,7 @@ static const char *vy_log_key_name[] = {
        [VY_LOG_KEY_CREATE_LSN]         = "create_lsn",
        [VY_LOG_KEY_MODIFY_LSN]         = "modify_lsn",
        [VY_LOG_KEY_DROP_LSN]           = "drop_lsn",
+       [VY_LOG_KEY_GROUP_ID]           = "group_id",
 };
 
 /** vy_log_type -> human readable name. */
@@ -247,6 +249,9 @@ vy_log_record_snprint(char *buf, int size, const struct 
vy_log_record *record)
        if (record->space_id > 0)
                SNPRINT(total, snprintf, buf, size, "%s=%"PRIu32", ",
                        vy_log_key_name[VY_LOG_KEY_SPACE_ID], record->space_id);
+       if (record->group_id > 0)
+               SNPRINT(total, snprintf, buf, size, "%s=%"PRIu32", ",
+                       vy_log_key_name[VY_LOG_KEY_GROUP_ID], record->group_id);
        if (record->key_parts != NULL) {
                SNPRINT(total, snprintf, buf, size, "%s=",
                        vy_log_key_name[VY_LOG_KEY_DEF]);
@@ -362,6 +367,11 @@ vy_log_record_encode(const struct vy_log_record *record,
                size += mp_sizeof_uint(record->space_id);
                n_keys++;
        }
+       if (record->group_id > 0) {
+               size += mp_sizeof_uint(VY_LOG_KEY_GROUP_ID);
+               size += mp_sizeof_uint(record->group_id);
+               n_keys++;
+       }
        if (record->key_parts != NULL) {
                size += mp_sizeof_uint(VY_LOG_KEY_DEF);
                size += mp_sizeof_array(record->key_part_count);
@@ -447,6 +457,10 @@ vy_log_record_encode(const struct vy_log_record *record,
                pos = mp_encode_uint(pos, VY_LOG_KEY_SPACE_ID);
                pos = mp_encode_uint(pos, record->space_id);
        }
+       if (record->group_id > 0) {
+               pos = mp_encode_uint(pos, VY_LOG_KEY_GROUP_ID);
+               pos = mp_encode_uint(pos, record->group_id);
+       }
        if (record->key_parts != NULL) {
                pos = mp_encode_uint(pos, VY_LOG_KEY_DEF);
                pos = mp_encode_array(pos, record->key_part_count);
@@ -561,6 +575,9 @@ vy_log_record_decode(struct vy_log_record *record,
                case VY_LOG_KEY_SPACE_ID:
                        record->space_id = mp_decode_uint(&pos);
                        break;
+               case VY_LOG_KEY_GROUP_ID:
+                       record->group_id = mp_decode_uint(&pos);
+                       break;
                case VY_LOG_KEY_DEF: {
                        uint32_t part_count = mp_decode_array(&pos);
                        struct key_part_def *parts = region_alloc(&fiber()->gc,
@@ -1238,6 +1255,7 @@ vy_recovery_lookup_slice(struct vy_recovery *recovery, 
int64_t slice_id)
 static struct vy_lsm_recovery_info *
 vy_recovery_do_create_lsm(struct vy_recovery *recovery, int64_t id,
                          uint32_t space_id, uint32_t index_id,
+                         uint32_t group_id,
                          const struct key_part_def *key_parts,
                          uint32_t key_part_count)
 {
@@ -1273,6 +1291,7 @@ vy_recovery_do_create_lsm(struct vy_recovery *recovery, 
int64_t id,
        lsm->id = id;
        lsm->space_id = space_id;
        lsm->index_id = index_id;
+       lsm->group_id = group_id;
        memcpy(lsm->key_parts, key_parts, sizeof(*key_parts) * key_part_count);
        lsm->key_part_count = key_part_count;
        lsm->create_lsn = -1;
@@ -1313,6 +1332,7 @@ vy_recovery_do_create_lsm(struct vy_recovery *recovery, 
int64_t id,
 static int
 vy_recovery_prepare_lsm(struct vy_recovery *recovery, int64_t id,
                        uint32_t space_id, uint32_t index_id,
+                       uint32_t group_id,
                        const struct key_part_def *key_parts,
                        uint32_t key_part_count)
 {
@@ -1323,7 +1343,8 @@ vy_recovery_prepare_lsm(struct vy_recovery *recovery, 
int64_t id,
                return -1;
        }
        if (vy_recovery_do_create_lsm(recovery, id, space_id, index_id,
-                                     key_parts, key_part_count) == NULL)
+                                     group_id, key_parts,
+                                     key_part_count) == NULL)
                return -1;
        return 0;
 }
@@ -1339,7 +1360,7 @@ vy_recovery_prepare_lsm(struct vy_recovery *recovery, 
int64_t id,
  */
 static int
 vy_recovery_create_lsm(struct vy_recovery *recovery, int64_t id,
-                      uint32_t space_id, uint32_t index_id,
+                      uint32_t space_id, uint32_t index_id, uint32_t group_id,
                       const struct key_part_def *key_parts,
                       uint32_t key_part_count, int64_t create_lsn,
                       int64_t modify_lsn, int64_t dump_lsn)
@@ -1358,7 +1379,8 @@ vy_recovery_create_lsm(struct vy_recovery *recovery, 
int64_t id,
                        return -1;
                }
        } else {
-               lsm = vy_recovery_do_create_lsm(recovery, id, space_id, 
index_id,
+               lsm = vy_recovery_do_create_lsm(recovery, id, space_id,
+                                               index_id, group_id,
                                                key_parts, key_part_count);
                if (lsm == NULL)
                        return -1;
@@ -1883,14 +1905,15 @@ vy_recovery_process_record(struct vy_recovery *recovery,
        case VY_LOG_PREPARE_LSM:
                rc = vy_recovery_prepare_lsm(recovery, record->lsm_id,
                                record->space_id, record->index_id,
-                               record->key_parts, record->key_part_count);
+                               record->group_id, record->key_parts,
+                               record->key_part_count);
                break;
        case VY_LOG_CREATE_LSM:
                rc = vy_recovery_create_lsm(recovery, record->lsm_id,
                                record->space_id, record->index_id,
-                               record->key_parts, record->key_part_count,
-                               record->create_lsn, record->modify_lsn,
-                               record->dump_lsn);
+                               record->group_id, record->key_parts,
+                               record->key_part_count, record->create_lsn,
+                               record->modify_lsn, record->dump_lsn);
                break;
        case VY_LOG_MODIFY_LSM:
                rc = vy_recovery_modify_lsm(recovery, record->lsm_id,
@@ -2218,6 +2241,7 @@ vy_log_append_lsm(struct xlog *xlog, struct 
vy_lsm_recovery_info *lsm)
        record.lsm_id = lsm->id;
        record.index_id = lsm->index_id;
        record.space_id = lsm->space_id;
+       record.group_id = lsm->group_id;
        record.key_parts = lsm->key_parts;
        record.key_part_count = lsm->key_part_count;
        record.create_lsn = lsm->create_lsn;
diff --git a/src/box/vy_log.h b/src/box/vy_log.h
index 0a216de8..da0745b2 100644
--- a/src/box/vy_log.h
+++ b/src/box/vy_log.h
@@ -66,8 +66,8 @@ enum vy_log_record_type {
        /**
         * Create a new LSM tree.
         * Requires vy_log_record::lsm_id, create_lsn.
-        * After rotation, it also stores space_id, index_id, key_def,
-        * create_lsn, modify_lsn, dump_lsn.
+        * After rotation, it also stores space_id, index_id, group_id,
+        * key_def, create_lsn, modify_lsn, dump_lsn.
         */
        VY_LOG_CREATE_LSM               = 0,
        /**
@@ -182,7 +182,8 @@ enum vy_log_record_type {
        VY_LOG_FORGET_LSM               = 14,
        /**
         * Prepare a new LSM tree for building.
-        * Requires vy_log_record::lsm_id, index_id, space_id.
+        * Requires vy_log_record::lsm_id, index_id, space_id, group_id,
+        * key_def.
         *
         * Index ALTER operation consists of two stages. First, we
         * build a new LSM tree, checking constraints if necessary.
@@ -225,6 +226,8 @@ struct vy_log_record {
        uint32_t index_id;
        /** Space ID. */
        uint32_t space_id;
+       /** Replication group ID. */
+       uint32_t group_id;
        /** Index key definition, as defined by the user. */
        const struct key_def *key_def;
        /** Array of key part definitions. */
@@ -285,6 +288,8 @@ struct vy_lsm_recovery_info {
        uint32_t index_id;
        /** Space ID. */
        uint32_t space_id;
+       /** Replication group ID. */
+       uint32_t group_id;
        /** Array of key part definitions. */
        struct key_part_def *key_parts;
        /** Number of key parts. */
@@ -562,7 +567,7 @@ vy_log_record_init(struct vy_log_record *record)
 /** Helper to log a vinyl LSM tree preparation. */
 static inline void
 vy_log_prepare_lsm(int64_t id, uint32_t space_id, uint32_t index_id,
-                  const struct key_def *key_def)
+                  uint32_t group_id, const struct key_def *key_def)
 {
        struct vy_log_record record;
        vy_log_record_init(&record);
@@ -570,6 +575,7 @@ vy_log_prepare_lsm(int64_t id, uint32_t space_id, uint32_t 
index_id,
        record.lsm_id = id;
        record.space_id = space_id;
        record.index_id = index_id;
+       record.group_id = group_id;
        record.key_def = key_def;
        vy_log_write(&record);
 }
diff --git a/src/box/vy_lsm.c b/src/box/vy_lsm.c
index f2400657..cb3c436f 100644
--- a/src/box/vy_lsm.c
+++ b/src/box/vy_lsm.c
@@ -110,8 +110,8 @@ vy_lsm_mem_tree_size(struct vy_lsm *lsm)
 
 struct vy_lsm *
 vy_lsm_new(struct vy_lsm_env *lsm_env, struct vy_cache_env *cache_env,
-            struct vy_mem_env *mem_env, struct index_def *index_def,
-            struct tuple_format *format, struct vy_lsm *pk)
+          struct vy_mem_env *mem_env, struct index_def *index_def,
+          struct tuple_format *format, struct vy_lsm *pk, uint32_t group_id)
 {
        static int64_t run_buckets[] = {
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 50, 100,
@@ -202,6 +202,7 @@ vy_lsm_new(struct vy_lsm_env *lsm_env, struct vy_cache_env 
*cache_env,
        lsm->in_compact.pos = UINT32_MAX;
        lsm->space_id = index_def->space_id;
        lsm->index_id = index_def->iid;
+       lsm->group_id = group_id;
        lsm->opts = index_def->opts;
        lsm->check_is_unique = lsm->opts.is_unique;
        vy_lsm_read_set_new(&lsm->read_set);
@@ -331,7 +332,8 @@ vy_lsm_create(struct vy_lsm *lsm)
 
        /* Write the new LSM tree record to vylog. */
        vy_log_tx_begin();
-       vy_log_prepare_lsm(id, lsm->space_id, lsm->index_id, lsm->key_def);
+       vy_log_prepare_lsm(id, lsm->space_id, lsm->index_id,
+                          lsm->group_id, lsm->key_def);
        vy_log_insert_range(id, range->id, NULL, NULL);
        if (vy_log_tx_commit() < 0)
                return -1;
diff --git a/src/box/vy_lsm.h b/src/box/vy_lsm.h
index 90ccb534..f0b7ec9c 100644
--- a/src/box/vy_lsm.h
+++ b/src/box/vy_lsm.h
@@ -158,6 +158,8 @@ struct vy_lsm {
        uint32_t index_id;
        /** ID of the space this LSM tree is for. */
        uint32_t space_id;
+       /** Replication group ID. */
+       uint32_t group_id;
        /** Index options. */
        struct index_opts opts;
        /** Key definition used to compare tuples. */
@@ -301,8 +303,8 @@ vy_lsm_mem_tree_size(struct vy_lsm *lsm);
 /** Allocate a new LSM tree object. */
 struct vy_lsm *
 vy_lsm_new(struct vy_lsm_env *lsm_env, struct vy_cache_env *cache_env,
-            struct vy_mem_env *mem_env, struct index_def *index_def,
-            struct tuple_format *format, struct vy_lsm *pk);
+          struct vy_mem_env *mem_env, struct index_def *index_def,
+          struct tuple_format *format, struct vy_lsm *pk, uint32_t group_id);
 
 /** Free an LSM tree object. */
 void
diff --git a/test/replication/local_spaces.result 
b/test/replication/local_spaces.result
index 06782788..15173553 100644
--- a/test/replication/local_spaces.result
+++ b/test/replication/local_spaces.result
@@ -4,17 +4,20 @@ env = require('test_run')
 test_run = env.new()
 ---
 ...
+engine = test_run:get_cfg('engine')
+---
+...
 --
 -- gh-3443: Check that changes done to spaces marked as local
 -- are not replicated, but vclock is still promoted.
 --
-s1 = box.schema.space.create('test1')
+s1 = box.schema.space.create('test1', {engine = engine})
 ---
 ...
 _ = s1:create_index('pk')
 ---
 ...
-s2 = box.schema.space.create('test2', {is_local = true})
+s2 = box.schema.space.create('test2', {engine = engine, is_local = true})
 ---
 ...
 _ = s2:create_index('pk')
@@ -48,7 +51,7 @@ box.space._space:update(s2.id, {{'=', 6, {group_id = 0}}}) -- 
error
 ...
 -- Currently, there are only two replication groups:
 -- 0 (global) and 1 (local)
-box.space._space:insert{9000, 1, 'test', 'memtx', 0, {group_id = 2}, {}} -- 
error
+box.space._space:insert{9000, 1, 'test', engine, 0, {group_id = 2}, {}} -- 
error
 ---
 - error: Replication group '2' does not exist
 ...
diff --git a/test/replication/local_spaces.test.lua 
b/test/replication/local_spaces.test.lua
index ec676a18..06e2b0bd 100644
--- a/test/replication/local_spaces.test.lua
+++ b/test/replication/local_spaces.test.lua
@@ -1,14 +1,15 @@
 env = require('test_run')
 test_run = env.new()
+engine = test_run:get_cfg('engine')
 
 --
 -- gh-3443: Check that changes done to spaces marked as local
 -- are not replicated, but vclock is still promoted.
 --
 
-s1 = box.schema.space.create('test1')
+s1 = box.schema.space.create('test1', {engine = engine})
 _ = s1:create_index('pk')
-s2 = box.schema.space.create('test2', {is_local = true})
+s2 = box.schema.space.create('test2', {engine = engine, is_local = true})
 _ = s2:create_index('pk')
 s1.is_local
 s2.is_local
@@ -23,7 +24,7 @@ box.space._space:update(s2.id, {{'=', 6, {group_id = 0}}}) -- 
error
 
 -- Currently, there are only two replication groups:
 -- 0 (global) and 1 (local)
-box.space._space:insert{9000, 1, 'test', 'memtx', 0, {group_id = 2}, {}} -- 
error
+box.space._space:insert{9000, 1, 'test', engine, 0, {group_id = 2}, {}} -- 
error
 
 -- Temporary local spaces should behave in the same fashion as
 -- plain temporary spaces, i.e. neither replicated nor persisted.
diff --git a/test/replication/suite.cfg b/test/replication/suite.cfg
index 283edcad..95e94e5a 100644
--- a/test/replication/suite.cfg
+++ b/test/replication/suite.cfg
@@ -6,7 +6,6 @@
     "wal_off.test.lua": {},
     "hot_standby.test.lua": {},
     "rebootstrap.test.lua": {},
-    "local_spaces.test.lua": {},
     "*": {
         "memtx": {"engine": "memtx"},
         "vinyl": {"engine": "vinyl"}
diff --git a/test/unit/vy_point_lookup.c b/test/unit/vy_point_lookup.c
index ebbb87d5..b9b7d6ff 100644
--- a/test/unit/vy_point_lookup.c
+++ b/test/unit/vy_point_lookup.c
@@ -93,7 +93,7 @@ test_basic()
                              &index_opts, key_def, NULL);
 
        struct vy_lsm *pk = vy_lsm_new(&lsm_env, &cache_env, &mem_env,
-                                      index_def, format, NULL);
+                                      index_def, format, NULL, 0);
        isnt(pk, NULL, "lsm is not NULL")
 
        struct vy_range *range = vy_range_new(1, NULL, NULL, pk->cmp_def);
diff --git a/test/vinyl/ddl.result b/test/vinyl/ddl.result
index 5b49f51f..3e65e232 100644
--- a/test/vinyl/ddl.result
+++ b/test/vinyl/ddl.result
@@ -44,11 +44,6 @@ space:create_index('pk', {bloom_fpr = 1.1})
 space:drop()
 ---
 ...
--- vinyl does not support replica local spaces
-space = box.schema.space.create('test', {engine = 'vinyl', is_local = true})
----
-- error: 'Can''t modify space ''test'': engine does not support replication 
groups'
-...
 -- space secondary index create
 space = box.schema.space.create('test', { engine = 'vinyl' })
 ---
diff --git a/test/vinyl/ddl.test.lua b/test/vinyl/ddl.test.lua
index 44cfa2ac..45c5cf8e 100644
--- a/test/vinyl/ddl.test.lua
+++ b/test/vinyl/ddl.test.lua
@@ -12,9 +12,6 @@ space:create_index('pk', {bloom_fpr = 0})
 space:create_index('pk', {bloom_fpr = 1.1})
 space:drop()
 
--- vinyl does not support replica local spaces
-space = box.schema.space.create('test', {engine = 'vinyl', is_local = true})
-
 -- space secondary index create
 space = box.schema.space.create('test', { engine = 'vinyl' })
 index1 = space:create_index('primary')
-- 
2.11.0


Other related posts:

  • » [tarantool-patches] [PATCH 3/3] vinyl: implement support of replica local spaces - Vladimir Davydov