--[[ Copyright (c) 2012-2014 Kaarle Ritvanen See LICENSE file for license details --]] local pth = require('aconf.path') local Cache = require('aconf.persistence.backends.volatile') local util = require('aconf.persistence.util') local copy = require('aconf.util').copy local json = require('cjson') local posix = require('posix') local backend = require('aconf.object').class() function backend:init() -- TODO cache expiration self.cache = {} self.dirty = {} end function backend:split_path(path) local fpath = copy(path) local jpath = {} local res while #fpath > 0 do local fp = pth.join('/', unpack(fpath)) if self.cache[fp] then return fp, jpath end table.insert(jpath, 1, fpath[#fpath]) table.remove(fpath) end fpath = '/' while true do fpath = pth.join(fpath, jpath[1]) table.remove(jpath, 1) local t = posix.stat(fpath, 'type') if t == 'link' then t = posix.stat(posix.readlink(fpath), 'type') end if not t or not ({directory=true, regular=true})[t] then error('File or directory does not exist: '..fpath) end if t == 'regular' then return fpath, jpath end assert(#jpath > 0) end end function backend:get(path, top) local fpath, jpath = self:split_path(path) if not self.cache[fpath] then self.cache[fpath] = Cache(json.decode(util.read_file(fpath))) end return self.cache[fpath]:get(jpath, top) end function backend:set(mods) local dirty = {} for _, mod in ipairs(mods) do local path, value = unpack(mod) local fpath, jpath = self:split_path(path) self.cache[fpath]:_set(jpath, value) dirty[fpath] = true end for path, _ in pairs(dirty) do local file = util.open_file(path, 'w') file:write(json.encode(self.cache[path]:_get{})) file:close() end end return backend