diff --git a/doc/examples/config/etcd/remote.yaml b/doc/examples/config/etcd/remote.yaml index d3824f8e8ebb9f69593a02af0f5f2f32ba3d2f2e..13dddfaf6650258315f8f1077692e8bc498c2de3 100644 --- a/doc/examples/config/etcd/remote.yaml +++ b/doc/examples/config/etcd/remote.yaml @@ -16,6 +16,6 @@ groups: instances: instance-001: database: - rw: true + mode: 'rw' instance-002: {} instance-003: {} diff --git a/doc/examples/config/replicaset.yaml b/doc/examples/config/replicaset.yaml index 869bca08157a048fa3981d32a92b0f180156d17c..6af36fddf6a46ca4c4075db29d1e0963b775917e 100644 --- a/doc/examples/config/replicaset.yaml +++ b/doc/examples/config/replicaset.yaml @@ -25,6 +25,6 @@ groups: instances: instance-001: database: - rw: true + mode: rw instance-002: {} instance-003: {} diff --git a/doc/examples/config/single.yaml b/doc/examples/config/single.yaml index 80af10ca6893ee89fe7dbf9c5291ae0222c0233e..9723b70b297c5dcc159e5e087b072b5058f90f72 100644 --- a/doc/examples/config/single.yaml +++ b/doc/examples/config/single.yaml @@ -11,6 +11,4 @@ groups: replicasets: replicaset-001: instances: - instance-001: - database: - rw: true + instance-001: {} diff --git a/src/box/lua/config/applier/box_cfg.lua b/src/box/lua/config/applier/box_cfg.lua index 0ee254ac81348d5cf043ec7c697ea002d014235b..cf9d0769e8d32afb76fd0bc1ffb30d4ded244682 100644 --- a/src/box/lua/config/applier/box_cfg.lua +++ b/src/box/lua/config/applier/box_cfg.lua @@ -191,7 +191,29 @@ local function apply(config) -- they're already added to `box_cfg`. box_cfg.log = log_destination(configdata) - box_cfg.read_only = not configdata:get('database.rw', {use_default = true}) + -- Read-only or read-write? + -- + -- 'rw' and 'ro' mean itself. + -- + -- The default is determined depending of amount of instances + -- in the given replicaset. + -- + -- * 1 instance: read-write. + -- * >1 instances: read-only. + local mode = configdata:get('database.mode', {use_default = true}) + if mode == 'ro' then + box_cfg.read_only = true + elseif mode == 'rw' then + box_cfg.read_only = false + elseif #configdata:peers() == 1 then + assert(mode == nil) + box_cfg.read_only = false + elseif #configdata:peers() > 1 then + assert(mode == nil) + box_cfg.read_only = true + else + assert(false) + end assert(type(box.cfg) == 'function' or type(box.cfg) == 'table') if type(box.cfg) == 'table' then diff --git a/src/box/lua/config/instance_config.lua b/src/box/lua/config/instance_config.lua index 36f278a800dcf676b6f6d563eddfea6ff07a42d3..b940314f0df6f95118db9bceb0a1d30d72f43044 100644 --- a/src/box/lua/config/instance_config.lua +++ b/src/box/lua/config/instance_config.lua @@ -569,10 +569,21 @@ return schema.new('instance_config', schema.record({ box_cfg_nondynamic = true, default = false, }), - -- Reversed and applied to box_cfg.read_only. - rw = schema.scalar({ - type = 'boolean', - default = false, + -- Applied to box_cfg.read_only. + -- + -- The effective default depends on amount of instances in + -- a replicaset. + -- + -- A singleton instance (the only instance in the + -- replicaset) is in the 'rw' mode by default. + -- + -- If the replicaset contains several (more than one) + -- instances, the default is 'ro'. + mode = schema.enum({ + 'ro', + 'rw', + }, { + default = box.NULL, }), txn_timeout = schema.scalar({ type = 'number', diff --git a/test/config-luatest/appliers_test.lua b/test/config-luatest/appliers_test.lua index ee34a09d12086a770131925d24dec73f7e5ae2fb..354ddf4faabc269a976ee7db9376e705897c1694 100644 --- a/test/config-luatest/appliers_test.lua +++ b/test/config-luatest/appliers_test.lua @@ -32,11 +32,7 @@ local appliers_script = [[ replicasets = { ['replicaset-001'] = { instances = { - ['instance-001'] = { - database = { - rw = true, - }, - }, + ['instance-001'] = {}, }, }, }, diff --git a/test/config-luatest/basic_test.lua b/test/config-luatest/basic_test.lua index ecad6a1b7efbd4baacc62346e94e6c1414c7bcf7..e97934cde00b940d67897cc503546d235868b986 100644 --- a/test/config-luatest/basic_test.lua +++ b/test/config-luatest/basic_test.lua @@ -43,11 +43,7 @@ g.test_basic = function(g) replicasets = { ['replicaset-001'] = { instances = { - ['instance-001'] = { - database = { - rw = true, - }, - }, + ['instance-001'] = {}, }, }, }, @@ -60,6 +56,10 @@ g.test_basic = function(g) g.server = server:new(fun.chain(opts, {alias = 'instance-001'}):tomap()) g.server:start() t.assert_equals(g.server:eval('return box.info.name'), g.server.alias) + + -- Verify that the default database mode for a singleton + -- instance (the only one in its replicaset) is read-write. + t.assert_equals(g.server:eval('return box.info.ro'), false) end g.test_example_single = function(g) @@ -75,6 +75,12 @@ g.test_example_replicaset = function(g) local dir = treegen.prepare_directory(g, {}, {}) local config_file = fio.abspath('doc/examples/config/replicaset.yaml') helpers.start_example_replicaset(g, dir, config_file) + + -- Verify that the default database mode for a replicaset with + -- several instances (more than one) is read-only. + t.assert_equals(g.server_1:eval('return box.info.ro'), false) + t.assert_equals(g.server_2:eval('return box.info.ro'), true) + t.assert_equals(g.server_3:eval('return box.info.ro'), true) end local err_msg_cannot_find_user = 'box_cfg.apply: cannot find user unknown ' .. @@ -152,7 +158,7 @@ for case_name, case in pairs({ instances = { ['instance-001'] = { database = { - rw = true, + mode = 'rw', }, iproto = { listen = good_listen, @@ -268,7 +274,7 @@ for case_name, case in pairs({ instances = { ['instance-001'] = { database = { - rw = true, + mode = 'rw', }, }, ['instance-002'] = {}, diff --git a/test/config-luatest/cluster_config_schema_test.lua b/test/config-luatest/cluster_config_schema_test.lua index c83ff3ec7b7ab4b412cc4cc995f57902abc3d899..f171d90ea2487acc4a0eda4e842311555bba812b 100644 --- a/test/config-luatest/cluster_config_schema_test.lua +++ b/test/config-luatest/cluster_config_schema_test.lua @@ -30,7 +30,7 @@ g.test_cluster_config = function() instances = { ['instance-001'] = { database = { - rw = true, + mode = 'rw', }, }, }, @@ -58,7 +58,7 @@ g.test_cluster_config = function() cache_size = 2000, }, database = { - rw = true, + mode = 'rw', }, iproto = { listen = 'unix/:./{{ instance_name }}.iproto', @@ -71,7 +71,7 @@ g.test_cluster_config = function() local result = cluster_config:find_instance(config, 'instance-001') local expected_instance = { database = { - rw = true, + mode = 'rw', }, } local expected_replicaset = { @@ -167,7 +167,7 @@ g.test_defaults = function() instance_uuid = box.NULL, replicaset_uuid = box.NULL, hot_standby = false, - rw = false, + mode = box.NULL, txn_timeout = 3153600000, txn_isolation = 'best-effort', use_mvcc_engine = false, diff --git a/test/config-luatest/config_test.lua b/test/config-luatest/config_test.lua index 25287defb43e81183e432c8538f8455b89900b57..500b40f1ba6a1c0b9e6c980018a05c42a07422c3 100644 --- a/test/config-luatest/config_test.lua +++ b/test/config-luatest/config_test.lua @@ -40,12 +40,12 @@ g.test_configdata = function() instances = { ['instance-001'] = { database = { - rw = true, + mode = 'rw', }, }, ['instance-002'] = { database = { - rw = false, + mode = 'ro', }, }, }, @@ -72,7 +72,7 @@ g.test_configdata = function() cache_size = 2000, }, database = { - rw = true, + mode = 'rw', }, memtx = { memory = 1000000, @@ -140,9 +140,7 @@ g.test_config_general = function() replicasets:\ replicaset-001:\ instances:\ - instance-001:\ - database:\ - rw: true\ + instance-001: {}\ " file = io.open('config.yaml', 'w') file:write(file_config) @@ -166,9 +164,7 @@ g.test_config_general = function() replicasets:\ replicaset-001:\ instances:\ - instance-001:\ - database:\ - rw: true\ + instance-001: {}\ " file = io.open('config.yaml', 'w') file:write(file_config) @@ -207,9 +203,7 @@ g.test_config_broadcast = function() replicasets: replicaset-001: instances: - instance-001: - database: - rw: true + instance-001: {} ]] treegen.write_script(dir, 'config.yaml', file_config) @@ -267,9 +261,7 @@ g.test_config_option = function() replicasets: replicaset-001: instances: - instance-001: - database: - rw: true + instance-001: {} ]] treegen.write_script(dir, 'config.yaml', file_config) diff --git a/test/config-luatest/instance_config_schema_test.lua b/test/config-luatest/instance_config_schema_test.lua index 06fa1f4a5c287017c719a16548ed85054bbc7e2b..25d865aeafbbe01af03477d1a8b50c01d3f08e76 100644 --- a/test/config-luatest/instance_config_schema_test.lua +++ b/test/config-luatest/instance_config_schema_test.lua @@ -556,7 +556,7 @@ g.test_database = function() instance_uuid = '11111111-1111-1111-1111-111111111111', replicaset_uuid = '11111111-1111-1111-1111-111111111111', hot_standby = true, - rw = true, + mode = 'ro', txn_timeout = 1, txn_isolation = 'best-effort', use_mvcc_engine = true, @@ -587,11 +587,22 @@ g.test_database = function() instance_config:validate(iconfig) end) + iconfig = { + database = { + mode = 'none', + }, + } + err = '[instance_config] database.mode: Got none, but only the ' .. + 'following values are allowed: ro, rw' + t.assert_error_msg_content_equals(err, function() + instance_config:validate(iconfig) + end) + local exp = { instance_uuid = box.NULL, replicaset_uuid = box.NULL, hot_standby = false, - rw = false, + mode = box.NULL, txn_timeout = 3153600000, txn_isolation = 'best-effort', use_mvcc_engine = false, diff --git a/test/config-luatest/sources_test.lua b/test/config-luatest/sources_test.lua index 740158e69cb15a59e7e25b361951485b098dfeb7..cd494ec69f7421f14f6b2ddf46a9ea99595a7295 100644 --- a/test/config-luatest/sources_test.lua +++ b/test/config-luatest/sources_test.lua @@ -34,11 +34,7 @@ g.test_source_file = function() replicasets = { ['replicaset-001'] = { instances = { - ['instance-001'] = { - database = { - rw = true, - }, - }, + ['instance-001'] = {}, }, }, },