1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
--[[
Copyright (c) 2012-2013 Kaarle Ritvanen
See LICENSE file for license details
--]]
module(..., package.seeall)
local pth = require('acf.path')
local Cache = require('acf.persistence.backends.volatile').backend
local util = require('acf.persistence.util')
local copy = require('acf.util').copy
require 'json'
require 'lfs'
backend = require('acf.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.mjoin('/', 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.mjoin(fpath, jpath[1])
table.remove(jpath, 1)
local attrs = lfs.attributes(fpath)
if not attrs or not ({directory=true, file=true})[attrs.mode] then
error('File or directory does not exist: '..fpath)
end
if attrs.mode == 'file' then return fpath, jpath end
assert(#jpath > 0)
end
end
function backend:get(path)
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)
end
function backend:set(mods)
local dirty = {}
for _, mod in ipairs(mods) do
local path, tpe, value = unpack(mod)
local fpath, jpath = self:split_path(path)
self.cache[fpath]:_set(jpath, tpe, 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
|