Skip to content

Commit

Permalink
config: move snapshot related code into configdata
Browse files Browse the repository at this point in the history
Config's box.cfg applier scans snapshot_dir in order to find out,
whether recovery is going to be done. It's needed in order to determine,
whether the instance should be started into ro mode firstly.

Let's move info about snapshot into configdata, as it accumulates
configuration data and this part should be there. The commit also
introduces snapshot_path, which will be used in the following commits
in order to validate names.

Needed for tarantool#8978

NO_DOC=refactoring
NO_TEST=refactoring
NO_CHANGELOG=refactoring
  • Loading branch information
Serpentian committed Oct 12, 2023
1 parent fb64a24 commit 00bdb13
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 52 deletions.
54 changes: 2 additions & 52 deletions src/box/lua/config/applier/box_cfg.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local fio = require('fio')
local fiber = require('fiber')
local log = require('internal.config.utils.log')
local instance_config = require('internal.config.instance_config')
Expand Down Expand Up @@ -69,55 +68,6 @@ local function log_destination(log)
end
end

-- Determine where snapshot should reside based on the given
-- configuration.
--
-- To be called before first box.cfg().
local function effective_snapshot_dir(configdata)
-- The snapshot directory has a default value in the schema
-- (it is a string). So, it can't be nil or box.NULL.
local snap_dir = configdata:get('snapshot.dir', {use_default = true})
assert(snap_dir ~= nil)

-- If the path is absolute, just return it.
--
-- This check is necessary due to fio.pathjoin() peculiars,
-- see gh-8816.
if snap_dir:startswith('/') then
return snap_dir
end

-- We assume that the startup working directory is the current
-- working directory. IOW, that this function is called before
-- first box.cfg() call. Let's verify it.
assert(type(box.cfg) == 'function')

-- If the snapshot directory is not absolute, it is relative
-- to the working directory.
--
-- Determine an absolute path to the configured working
-- directory considering that it may be relative to the
-- working directory at the startup moment.
local work_dir = configdata:get('process.work_dir', {use_default = true})
if work_dir == nil then
work_dir = '.'
end
work_dir = fio.abspath(work_dir)

-- Now we know the absolute path to the configured working
-- directory. Let's determine the snapshot directory path.
return fio.abspath(fio.pathjoin(work_dir, snap_dir))
end

-- Determine whether the instance will be started from an existing
-- snapshot.
--
-- To be called before first box.cfg().
local function has_snapshot(configdata)
local pattern = fio.pathjoin(effective_snapshot_dir(configdata), '*.snap')
return #fio.glob(pattern) > 0
end

-- Returns nothing or {needs_retry = true}.
local function apply(config)
local configdata = config._configdata
Expand Down Expand Up @@ -266,7 +216,7 @@ local function apply(config)
local am_i_bootstrap_leader = false
if is_startup then
local instance_name = configdata:names().instance_name
am_i_bootstrap_leader = not has_snapshot(configdata) and
am_i_bootstrap_leader = not configdata:has_snapshot() and
instance_name == configdata:bootstrap_leader_name()
box_cfg.read_only = not am_i_bootstrap_leader
end
Expand Down Expand Up @@ -382,7 +332,7 @@ local function apply(config)
if is_startup and failover ~= 'election' and failover ~= 'supervised' then
local configured_as_rw = not box_cfg.read_only
local in_replicaset = #configdata:peers() > 1
local has_snap = has_snapshot(configdata)
local has_snap = configdata:has_snapshot()

-- Require at least one writable instance in the
-- replicaset if the instance is to be bootstrapped (has
Expand Down
59 changes: 59 additions & 0 deletions src/box/lua/config/configdata.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
--
-- Intended to be used as an immutable object.

local fio = require('fio')
local fun = require('fun')
local urilib = require('uri')
local digest = require('digest')
Expand Down Expand Up @@ -197,10 +198,54 @@ function methods.bootstrap_leader_name(self)
return self._bootstrap_leader_name
end

-- Determine whether the instance will be started from an existing
-- snapshot.
function methods.has_snapshot(self)
return self._snapshot_path ~= nil
end

local mt = {
__index = methods,
}

-- Determine where snapshot should reside based on the given
-- configuration.
local function effective_snapshot_dir(iconfig)
-- The snapshot directory has a default value in the schema
-- (it is a string). So, it can't be nil or box.NULL.
local snap_dir = instance_config:get(iconfig, 'snapshot.dir')
assert(snap_dir ~= nil)

-- If the path is absolute, just return it.
--
-- This check is necessary due to fio.pathjoin() peculiars,
-- see gh-8816.
if snap_dir:startswith('/') then
return snap_dir
end

-- We assume that the startup working directory is the current
-- working directory. IOW, that this function is called before
-- first box.cfg() call. Let's verify it.
assert(type(box.cfg) == 'function')

-- If the snapshot directory is not absolute, it is relative
-- to the working directory.
--
-- Determine an absolute path to the configured working
-- directory considering that it may be relative to the
-- working directory at the startup moment.
local work_dir = instance_config:get(iconfig, 'process.work_dir')
if work_dir == nil then
work_dir = '.'
end
work_dir = fio.abspath(work_dir)

-- Now we know the absolute path to the configured working
-- directory. Let's determine the snapshot directory path.
return fio.abspath(fio.pathjoin(work_dir, snap_dir))
end

local function new(iconfig, cconfig, instance_name)
-- Precalculate configuration with applied defaults.
local iconfig_def = instance_config:apply_default(iconfig)
Expand Down Expand Up @@ -352,6 +397,19 @@ local function new(iconfig, cconfig, instance_name)
bootstrap_leader_name = peer_names[1]
end

-- Snapshot, used for recovery.
local snapshot_path = nil
-- Recovery can be done only during startup. Don't set snapshot_path,
-- when config reload is done. It's not needed anymore.
if type(box.cfg) == 'function' then
local snap_dir = effective_snapshot_dir(iconfig_def)
local glob = fio.glob(fio.pathjoin(snap_dir, '*.snap'))
if #glob > 0 then
table.sort(glob)
snapshot_path = glob[#glob]
end
end

return setmetatable({
_iconfig = iconfig,
_iconfig_def = iconfig_def,
Expand All @@ -367,6 +425,7 @@ local function new(iconfig, cconfig, instance_name)
_leader = leader,
_bootstrap_leader = bootstrap_leader,
_bootstrap_leader_name = bootstrap_leader_name,
_snapshot_path = snapshot_path,
}, mt)
end

Expand Down

0 comments on commit 00bdb13

Please sign in to comment.