I think it is out of scope of the task. On Sunday, March 24, 2019 12:07:22 AM MSK Vladimir Davydov wrote: > Local spaces can be modified even in read-only mode hence we don't need > to abort transactions that modify only local spaces when switching to > read-only mode. > > Follow-up #4016 > --- > src/box/vy_tx.c | 19 +++++++++++++++++-- > test/vinyl/misc.result | 38 ++++++++++++++++++++++++++++++++++++++ > test/vinyl/misc.test.lua | 16 ++++++++++++++++ > 3 files changed, 71 insertions(+), 2 deletions(-) > > diff --git a/src/box/vy_tx.c b/src/box/vy_tx.c > index 56d594e5..67a9b384 100644 > --- a/src/box/vy_tx.c > +++ b/src/box/vy_tx.c > @@ -52,6 +52,7 @@ > #include "trivia/util.h" > #include "tuple.h" > #include "column_mask.h" > +#include "vclock.h" > #include "vy_cache.h" > #include "vy_lsm.h" > #include "vy_mem.h" > @@ -1121,8 +1122,22 @@ tx_manager_abort_writers_for_ro(struct tx_manager > *xm) struct vy_tx *tx; > rlist_foreach_entry(tx, &xm->writers, in_writers) { > /* Applier ignores ro flag. */ > - if (tx->state == VINYL_TX_READY && !tx->is_applier_session) > - vy_tx_abort(tx); > + if (tx->state == VINYL_TX_READY && !tx->is_applier_session) { > + /* > + * Don't abort transactions that modify only > + * local spaces as they can be modified even > + * in ro mode. > + */ > + struct vy_tx_space_hash_entry *entry; > + struct vy_tx_space_hash_iterator it; > + vy_tx_space_hash_ifirst(&tx->space_hash, &it); > + while ((entry = vy_tx_space_hash_inext(&it)) != NULL) { > + if (space_group_id(entry->space) != GROUP_LOCAL) { > + vy_tx_abort(tx); > + break; > + } > + } > + } > } > } > > diff --git a/test/vinyl/misc.result b/test/vinyl/misc.result > index 4f613cb0..751f8795 100644 > --- a/test/vinyl/misc.result > +++ b/test/vinyl/misc.result > @@ -298,6 +298,16 @@ s:replace({1, 1}) > --- > - [1, 1] > ... > +s_local = box.schema.space.create('test_local', {engine = 'vinyl', is_local > = true}) +--- > +... > +_ = s_local:create_index('pk') > +--- > +... > +s_local:replace({1, 1}) > +--- > +- [1, 1] > +... > test_run:cmd("setopt delimiter ';'") > --- > - true > @@ -334,6 +344,19 @@ _ = fiber.create(function() > end); > --- > ... > +-- Start rw transaction modifying only local spaces. > +ch3 = fiber.channel(1); > +--- > +... > +_ = fiber.create(function() > + box.begin() > + s_local:replace{1, 2} > + ch3:get() > + local status, err = pcall(box.commit) > + ch3:put(status or err) > +end); > +--- > +... > test_run:cmd("setopt delimiter ''"); > --- > - true > @@ -351,6 +374,10 @@ ch2:put(true) > --- > - true > ... > +ch3:put(true) > +--- > +- true > +... > ch1:get() > --- > - Can't modify data because this instance is in read-only mode. > @@ -371,6 +398,10 @@ ch2:get() > --- > - true > ... > +ch3:get() > +--- > +- true > +... > -- Cleanup. > box.cfg{read_only = false} > --- > @@ -382,3 +413,10 @@ s:select() > s:drop() > --- > ... > +s_local:select() > +--- > +- - [1, 2] > +... > +s_local:drop() > +--- > +... > diff --git a/test/vinyl/misc.test.lua b/test/vinyl/misc.test.lua > index bffaaf16..0616722f 100644 > --- a/test/vinyl/misc.test.lua > +++ b/test/vinyl/misc.test.lua > @@ -124,6 +124,9 @@ test_run:cmd('cleanup server test') > s = box.schema.space.create('test', {engine = 'vinyl'}) > _ = s:create_index('pk') > s:replace({1, 1}) > +s_local = box.schema.space.create('test_local', {engine = 'vinyl', is_local > = true}) +_ = s_local:create_index('pk') > +s_local:replace({1, 1}) > test_run:cmd("setopt delimiter ';'") > -- Start rw transaction. > ch1 = fiber.channel(1); > @@ -149,18 +152,31 @@ _ = fiber.create(function() > local status, err = pcall(box.commit) > ch2:put(status or err) > end); > +-- Start rw transaction modifying only local spaces. > +ch3 = fiber.channel(1); > +_ = fiber.create(function() > + box.begin() > + s_local:replace{1, 2} > + ch3:get() > + local status, err = pcall(box.commit) > + ch3:put(status or err) > +end); > test_run:cmd("setopt delimiter ''"); > -- Switch to ro mode. > box.cfg{read_only = true} > -- Resume the transactions. > ch1:put(true) > ch2:put(true) > +ch3:put(true) > ch1:get() > ch1:get() > ch1:get() > ch2:get() > ch2:get() > +ch3:get() > -- Cleanup. > box.cfg{read_only = false} > s:select() > s:drop() > +s_local:select() > +s_local:drop()