From 7d9c43916b0600ac4879dfe9793eab807a83ab2b Mon Sep 17 00:00:00 2001 From: Kaarle Ritvanen Date: Mon, 10 Mar 2014 22:45:18 +0200 Subject: rename ACF2 to Alpine Configurator (aconf) --- aconf/persistence/init.lua | 113 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 aconf/persistence/init.lua (limited to 'aconf/persistence/init.lua') diff --git a/aconf/persistence/init.lua b/aconf/persistence/init.lua new file mode 100644 index 0000000..991776a --- /dev/null +++ b/aconf/persistence/init.lua @@ -0,0 +1,113 @@ +--[[ +Copyright (c) 2012-2014 Kaarle Ritvanen +See LICENSE file for license details +--]] + +local loadmods = require('aconf.loader') +local topology = require('aconf.model.root').topology +local object = require('aconf.object') +local pth = require('aconf.path') + +local util = require('aconf.util') +local contains = util.contains +local setdefault = util.setdefault + +local stringy = require('stringy') + + +local DataStore = object.class( + require('aconf.transaction.base').TransactionBackend +) + +function DataStore:init() + object.super(self, DataStore):init() + self.backends = util.map( + function(m) return m() end, + loadmods('persistence/backends') + ) + self.triggers = {pre={}, post={}} +end + +function DataStore:trigger(phase, path, func) + local funcs = setdefault(self.triggers[phase], path, {}) + if not contains(funcs, func) then table.insert(funcs, func) end +end + +function DataStore:split_path(path) + local comps = pth.split(path) + local backend = self.backends[comps[1]] + assert(backend) + table.remove(comps, 1) + return backend, comps +end + +function DataStore:get(path) + local backend, comps = self:split_path(path) + local top = topology(path) + + local res = backend:get(comps, top) + + if top then + local t = top.type + if t and res ~= nil then + local atype = type(res) + + if t == 'table' then assert(atype == 'table') + + else + assert(atype ~= 'table') + + if t == 'string' then res = tostring(res) + elseif t == 'number' then res = tonumber(res) + + elseif t == 'boolean' then + if atype == 'string' then res = res:lower() end + if res == 1 or contains({'1', 't', 'true', 'y', 'yes'}, res) then + res = true + elseif res == 0 or contains( + {'0', 'f', 'false', 'n', 'no'}, res + ) then + res = false + else res = res and true or false end + + elseif contains({'binary', 'reference'}, t) then + assert(atype == 'string') + + else assert(false) end + end + end + end + + return util.copy(res), self.mod_time[path] or 0 +end + +function DataStore:_set_multiple(mods) + local bms = {} + local trigger = {} + + for _, mod in ipairs(mods) do + local path, value = unpack(mod) + + local tp = path + while not trigger[tp] do + trigger[tp] = true + tp = pth.parent(tp) + end + + local backend, comps = self:split_path(path) + table.insert(setdefault(bms, backend, {}), {comps, value}) + end + + local function exec_triggers(phase) + for path, _ in pairs(trigger) do + for _, func in ipairs(self.triggers[phase][path] or {}) do func() end + end + end + + exec_triggers('pre') + for backend, bm in pairs(bms) do backend:set(bm) end + exec_triggers('post') +end + + +return DataStore() -- cgit v1.2.3