diff --git a/src/box/wal.cc b/src/box/wal.cc index 000cd520aa0f5d3d717799f15c51ecc04e7014fd..960c9d048ef816229045439bb5208d499651ec49 100644 --- a/src/box/wal.cc +++ b/src/box/wal.cc @@ -570,14 +570,14 @@ wal_assign_lsn(struct wal_writer *writer, struct xrow_header **row, struct xrow_header **end) { /** Assign LSN to all local rows. */ - if ((*row)->replica_id == 0) { - for ( ; row < end; row++) { + for ( ; row < end; row++) { + if ((*row)->replica_id == 0) { (*row)->lsn = vclock_inc(&writer->vclock, instance_id); (*row)->replica_id = instance_id; + } else { + vclock_follow(&writer->vclock, (*row)->replica_id, + (*row)->lsn); } - } else { - struct xrow_header *last = end[-1]; - vclock_follow(&writer->vclock, last->replica_id, last->lsn); } } diff --git a/test/replication/on_replace.lua b/test/replication/on_replace.lua new file mode 100644 index 0000000000000000000000000000000000000000..7e49efe1f7427c2f1dd7d8995a96828e21b9072a --- /dev/null +++ b/test/replication/on_replace.lua @@ -0,0 +1,34 @@ +#!/usr/bin/env tarantool + +-- get instance name from filename (on_replace1.lua => on_replace1) +local INSTANCE_ID = string.match(arg[0], "%d") +local USER = 'cluster' +local PASSWORD = 'somepassword' +local SOCKET_DIR = require('fio').cwd() +local function instance_uri(instance_id) + --return 'localhost:'..(3310 + instance_id) + return SOCKET_DIR..'/on_replace'..instance_id..'.sock'; +end + +-- start console first +require('console').listen(os.getenv('ADMIN')) + +box.cfg({ + listen = instance_uri(INSTANCE_ID); +-- log_level = 7; + replication = { + USER..':'..PASSWORD..'@'..instance_uri(1); + USER..':'..PASSWORD..'@'..instance_uri(2); + }; +}) + +env = require('test_run') +test_run = env.new() +engine = test_run:get_cfg('engine') + +box.once("bootstrap", function() + box.schema.user.create(USER, { password = PASSWORD }) + box.schema.user.grant(USER, 'replication') + box.schema.space.create('test', {engine = engine}) + box.space.test:create_index('primary') +end) diff --git a/test/replication/on_replace.result b/test/replication/on_replace.result index 15338ff051df4803dbbc4b5d55074f93f360c835..1736c53b746dcaeaefb2654bcce86c71e00a7690 100644 --- a/test/replication/on_replace.result +++ b/test/replication/on_replace.result @@ -94,3 +94,86 @@ box.space.test:drop() box.schema.user.revoke('guest', 'replication') --- ... +-- gh-2682 on_replace on slave server with data change +SERVERS = { 'on_replace1', 'on_replace2' } +--- +... +test_run:create_cluster(SERVERS) +--- +... +test_run:wait_fullmesh(SERVERS) +--- +... +test_run:cmd('switch on_replace1') +--- +- true +... +fiber = require'fiber' +--- +... +s1 = box.schema.space.create('s1') +--- +... +_ = s1:create_index('pk') +--- +... +s2 = box.schema.space.create('s2') +--- +... +_ = s2:create_index('pk') +--- +... +test_run:cmd('switch on_replace2') +--- +- true +... +fiber = require'fiber' +--- +... +while box.space.s2 == nil do fiber.sleep(0.00001) end +--- +... +_ = box.space.s1:on_replace(function (old, new) box.space.s2:replace(new) end) +--- +... +test_run:cmd('switch on_replace1') +--- +- true +... +box.space.s1:replace({1, 2, 3, 4}) +--- +- [1, 2, 3, 4] +... +while #(box.space.s2:select()) == 0 do fiber.sleep(0.00001) end +--- +... +test_run:cmd('switch on_replace2') +--- +- true +... +box.space.s1:select() +--- +- - [1, 2, 3, 4] +... +box.space.s2:select() +--- +- - [1, 2, 3, 4] +... +test_run:cmd('switch on_replace1') +--- +- true +... +box.space.s1:select() +--- +- - [1, 2, 3, 4] +... +box.space.s2:select() +--- +- - [1, 2, 3, 4] +... +_ = test_run:cmd('switch default') +--- +... +test_run:drop_cluster(SERVERS) +--- +... diff --git a/test/replication/on_replace.test.lua b/test/replication/on_replace.test.lua index 12869031e72a7b60cd28f92e6d8478613227e52f..10bba2ddf06187d8389a3d8fa3c1dfb583bd19f3 100644 --- a/test/replication/on_replace.test.lua +++ b/test/replication/on_replace.test.lua @@ -39,3 +39,37 @@ test_run:cmd("stop server replica") test_run:cmd("cleanup server replica") box.space.test:drop() box.schema.user.revoke('guest', 'replication') + + +-- gh-2682 on_replace on slave server with data change + +SERVERS = { 'on_replace1', 'on_replace2' } +test_run:create_cluster(SERVERS) +test_run:wait_fullmesh(SERVERS) + +test_run:cmd('switch on_replace1') +fiber = require'fiber' +s1 = box.schema.space.create('s1') +_ = s1:create_index('pk') +s2 = box.schema.space.create('s2') +_ = s2:create_index('pk') + +test_run:cmd('switch on_replace2') +fiber = require'fiber' +while box.space.s2 == nil do fiber.sleep(0.00001) end +_ = box.space.s1:on_replace(function (old, new) box.space.s2:replace(new) end) + +test_run:cmd('switch on_replace1') +box.space.s1:replace({1, 2, 3, 4}) +while #(box.space.s2:select()) == 0 do fiber.sleep(0.00001) end + +test_run:cmd('switch on_replace2') +box.space.s1:select() +box.space.s2:select() + +test_run:cmd('switch on_replace1') +box.space.s1:select() +box.space.s2:select() + +_ = test_run:cmd('switch default') +test_run:drop_cluster(SERVERS) diff --git a/test/replication/on_replace1.lua b/test/replication/on_replace1.lua new file mode 120000 index 0000000000000000000000000000000000000000..4fb461aac2a1d6e18bd3a770f8990274e98c4d78 --- /dev/null +++ b/test/replication/on_replace1.lua @@ -0,0 +1 @@ +on_replace.lua \ No newline at end of file diff --git a/test/replication/on_replace2.lua b/test/replication/on_replace2.lua new file mode 120000 index 0000000000000000000000000000000000000000..4fb461aac2a1d6e18bd3a770f8990274e98c4d78 --- /dev/null +++ b/test/replication/on_replace2.lua @@ -0,0 +1 @@ +on_replace.lua \ No newline at end of file