diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua index da1e0476f0f35c7f602b56852e80bd24e069f66f..60b00980a5c96794a9854cf92107f4bf5be4abbe 100644 --- a/src/box/lua/load_cfg.lua +++ b/src/box/lua/load_cfg.lua @@ -240,8 +240,9 @@ local function load_cfg(cfg) __call = reload_cfg, }) ffi.C.load_cfg() - - box.internal.snapshot_daemon.start() + for _, k in pairs({'snapshot_count', 'snapshot_period' }) do + dynamic_cfg[k](cfg[k]) + end end box.cfg = load_cfg jit.off(load_cfg) diff --git a/src/box/lua/snapshot_daemon.lua b/src/box/lua/snapshot_daemon.lua index 8b7d50c782d6049d700ae98d44f8a452670c91f7..f1738b77b07eb872460b091d0cb3e841435bc810 100644 --- a/src/box/lua/snapshot_daemon.lua +++ b/src/box/lua/snapshot_daemon.lua @@ -9,7 +9,10 @@ do local PREFIX = 'snapshot_daemon' - local daemon = { status = 'stopped' } + local daemon = { + snapshot_period = 0; + snapshot_count = 0; + } local function sprintf(fmt, ...) return string.format(fmt, ...) end @@ -31,11 +34,11 @@ do -- create snapshot by several options local function make_snapshot(last_snap) - if box.cfg.snapshot_period == nil then + if daemon.snapshot_period == nil then return false end - if not(box.cfg.snapshot_period > 0) then + if not(daemon.snapshot_period > 0) then return false end @@ -61,13 +64,13 @@ do log.error("can't stat %s: %s", snaps[#snaps], errno.strerror()) return false end - if snstat.mtime <= fiber.time() + box.cfg.snapshot_period then + if snstat.mtime <= fiber.time() + daemon.snapshot_period then return snapshot(snaps) end end -- check filesystem and current time - local function process() + local function process(self) local snaps = fio.glob(fio.pathjoin(box.cfg.snap_dir, '*.snap')) if snaps == nil then @@ -81,11 +84,11 @@ do end -- cleanup code - if box.cfg.snapshot_count == nil then + if daemon.snapshot_count == nil then return end - if not (box.cfg.snapshot_count > 0) then + if not (self.snapshot_count > 0) then return end @@ -99,7 +102,7 @@ do return end - while #snaps > box.cfg.snapshot_count do + while #snaps > self.snapshot_count do local rm = snaps[1] table.remove(snaps, 1) @@ -141,16 +144,16 @@ do end - local function next_snap_interval() + local function next_snap_interval(self) -- don't do anything in hot_standby mode if box.info.status ~= 'running' or - box.cfg.snapshot_period == nil or - box.cfg.snapshot_period <= 0 then + self.snapshot_period == nil or + self.snapshot_period <= 0 then return nil end - local interval = box.cfg.snapshot_period / 10 + local interval = self.snapshot_period / 10 local time = fiber.time() local snaps = fio.glob(fio.pathjoin(box.cfg.snap_dir, '*.snap')) @@ -167,11 +170,11 @@ do -- there is no activity in xlogs - if box.cfg.snapshot_period * 2 + stat.mtime < time then + if self.snapshot_period * 2 + stat.mtime < time then return interval end - local time_left = box.cfg.snapshot_period + stat.mtime - time + local time_left = self.snapshot_period + stat.mtime - time if time_left > 0 then return time_left end @@ -182,89 +185,64 @@ do local function daemon_fiber(self) fiber.name(PREFIX) - log.info("%s", self.status) + log.info("started") while true do - local interval = next_snap_interval() - - if interval ~= nil then - fiber.sleep(interval) - if self.status ~= 'started' then - break - end - - local s, e = pcall(process) + local interval = next_snap_interval(self) + if interval == nil then + break + end + if self.control:get(interval) == nil then + local s, e = pcall(process, self) if not s then log.error(e) end else - -- daemon is disabled - -- do nothing, waiting for change event wakes us up - fiber.sleep(3600 * 24 * 365 * 100) + log.info("reloaded") end end - log.info("%s", self.status) - log.info("finished daemon fiber") + log.info("stopped") + self.control:close() + self.control = nil + self.fiber = nil + end + + local function reload(self) + if self.snapshot_period > 0 and self.fiber == nil then + self.control = fiber.channel(5) + self.fiber = fiber.create(daemon_fiber, self) + elseif self.fiber ~= nil then + -- wake up daemon + self.control:put(true) + end end setmetatable(daemon, { __index = { - start = function() - local daemon = box.internal[PREFIX] or daemon - if daemon.status == 'started' then - error("snapshot daemon has already been started") - end - daemon.status = 'started' - if box.cfg.snapshot_period > 0 then - daemon.fiber = fiber.create(daemon_fiber, daemon) - end - end, - - stop = function() - local daemon = box.internal[PREFIX] or daemon - if daemon.status == 'stopped' then - error("snapshot daemon has already been stopped") - end - daemon.status = 'stopped' - if daemon.fiber ~= nil then - daemon.fiber:wakeup() - end - daemon.fiber = nil - end, - set_snapshot_period = function(snapshot_period) - local daemon = box.internal[PREFIX] or daemon - log.info("%s: new snapshot period is %s", PREFIX, - tostring(snapshot_period)) - - if daemon.status ~= 'started' then + if daemon.snapshot_period == snapshot_period then return end - - if daemon.fiber == nil then - daemon.fiber = fiber.create(daemon_fiber, daemon) - end - daemon.fiber:wakeup() - return snapshot_period + log.info("%s: new snapshot period is %s", PREFIX, + tostring(snapshot_period)) + daemon.snapshot_period = snapshot_period + reload(daemon) + return end, set_snapshot_count = function(snapshot_count) if math.floor(snapshot_count) ~= snapshot_count then - box.error(box.error.PROC_LUA, + box.error(box.error.CFG, "snapshot_count must be integer") end - local daemon = box.internal[PREFIX] or daemon - log.info("%s: new snapshot count is %s", PREFIX, - tostring(snapshot_count)) - if daemon.status ~= 'started' then + if daemon.snapshot_count == snapshot_count then return end - - if daemon.fiber ~= nil then - daemon.fiber:wakeup() - end - return snapshot_period - end + daemon.snapshot_count = snapshot_count + log.info("%s: new snapshot count is %s", PREFIX, + tostring(snapshot_count)) + reload(daemon) + end } }) diff --git a/test/box/snapshot_daemon.result b/test/box/snapshot_daemon.result index 95aa45ff93a1b86a481d0933c154bb0ba9ad6216..8959177f47a4ddd4c543b30ebdcdfc4c3e4c22bf 100644 --- a/test/box/snapshot_daemon.result +++ b/test/box/snapshot_daemon.result @@ -114,5 +114,43 @@ PERIOD ... box.cfg{ snapshot_count = .2 } --- -- error: snapshot_count must be integer +- error: 'Incorrect option value: snapshot_count must be integer' +... +daemon = box.internal.snapshot_daemon +--- +... +-- stop daemon +box.cfg{ snapshot_period = 0 } +--- +... +-- wait daemon to stop +while daemon.fiber ~= nil do fiber.sleep(0) end +--- +... +daemon.fiber == nil +--- +- true +... +-- start daemon +box.cfg{ snapshot_period = 10 } +--- +... +daemon.fiber ~= nil +--- +- true +... +-- reload configuration +box.cfg{ snapshot_period = 15, snapshot_count = 20 } +--- +... +daemon.snapshot_period == 15 +--- +- true +... +daemon.snapshot_count = 20 +--- +... +-- stop daemon +box.cfg{ snapshot_count = 0 } +--- ... diff --git a/test/box/snapshot_daemon.test.lua b/test/box/snapshot_daemon.test.lua index d81104d26c81ff694c130b9350efd14c924171a3..5c61107f71c50b71c701e3767facbc9a7e8b5132 100644 --- a/test/box/snapshot_daemon.test.lua +++ b/test/box/snapshot_daemon.test.lua @@ -72,3 +72,20 @@ space:drop() PERIOD box.cfg{ snapshot_count = .2 } + +daemon = box.internal.snapshot_daemon +-- stop daemon +box.cfg{ snapshot_period = 0 } +-- wait daemon to stop +while daemon.fiber ~= nil do fiber.sleep(0) end +daemon.fiber == nil +-- start daemon +box.cfg{ snapshot_period = 10 } +daemon.fiber ~= nil +-- reload configuration +box.cfg{ snapshot_period = 15, snapshot_count = 20 } +daemon.snapshot_period == 15 +daemon.snapshot_count = 20 + +-- stop daemon +box.cfg{ snapshot_count = 0 }