-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmultiple_cache.lua
166 lines (150 loc) · 4.28 KB
/
multiple_cache.lua
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
local cache = require "cache"
local multiple_cache = {}
function multiple_cache:new(cache_names, key_field_name, ...)
assert(#cache_names >= 2)
local c = {}
c.caches = {}
for _, field_name in ipairs({key_field_name, ...}) do
assert(field_name ~= "REMOVED")
end
assert(#cache_names >= 1)
for _, cache_name in ipairs(cache_names) do
c.caches[cache_name] = cache:new(key_field_name, ...)
end
self.cache_names = cache_names
self.key_field_name = key_field_name
setmetatable(c, self)
self.__index = self
return c
end
function multiple_cache:set(obj)
local cache_name = self.cache_names[#self.cache_names]
local cache = self.caches[cache_name]
local key = obj[self.key_field_name]
if cache:selectkey(key) then
cache:remove(key)
end
cache:add(obj)
end
function multiple_cache:remove(key)
assert(self:selectkey(key))
local function get_cache_names(cache_names)
local t = {}
for i = 1, #cache_names - 1 do
t[#t+1] = cache_names[i]
end
return t
end
local cache_name = self.cache_names[#self.cache_names]
local cache = self.caches[cache_name]
local obj = cache:selectkey(key, get_cache_names(self.cache_names))
if obj then
if not self:selectkey(key) then
cache:remove(key)
else
cache:remove(key)
cache:add({
[self.key_field_name] = key,
REMOVED = true,
})
end
else
cache:add({
[self.key_field_name] = key,
REMOVED = true,
})
end
end
function multiple_cache:select(field_name, value, cache_names)
cache_names = cache_names or self.cache_names
local t = {}
for _, cache_name in ipairs(cache_names) do
for key, obj in self.caches[cache_name]:select(field_name, value) do
t[key] = obj
end
end
for key, obj in pairs(t) do
if obj[field_name] ~= value then
t[key] = nil
end
if obj.REMOVED then
t[key] = nil
end
end
return next, t, nil
end
function multiple_cache:selectkey(key, cache_names)
assert(#cache_names > 0)
cache_names = cache_names or self.cache_names
for i = #cache_names, 1, -1 do
local obj = self.caches[self.cache_names[i]]:selectkey(key)
if obj then
if not obj.REMOVED then
return obj
else
return
end
end
end
end
function multiple_cache:selectall()
local t = {}
for _, cache_name in ipairs(self.cache_names) do
for key, obj in self.caches[cache_name]:selectall() do
t[key] = obj
end
end
for key, obj in pairs(t) do
if obj.REMOVED then
t[key] = nil
end
end
return next, t, nil
end
function multiple_cache:revert(cache_names)
for _, cache_name in ipairs(cache_names) do
local cache = self.caches[cache_name]
cache:clearall()
end
end
function multiple_cache:commit(cache_name_1, cache_name_2)
local cache_1 = assert(self.caches[cache_name_1])
local cache_2 = assert(self.caches[cache_name_2])
for _, obj in cache_1:selectall() do
local key = obj[self.key_field_name]
if cache_2:selectkey(key) then
cache_2:remove(key)
end
cache_2:add(obj)
end
cache_1:clearall()
end
function multiple_cache:patch(cache_name_1, cache_name_2)
local t = {add = {}, del = {}, mod = {}}
local cache_1 = assert(self.caches[cache_name_1])
local cache_2 = assert(self.caches[cache_name_2])
for _, obj in cache_1:selectall() do
local key = obj[self.key_field_name]
if cache_2:selectkey(key) then
if obj.REMOVED then
t.del[#t.del + 1] = obj
else
t.mod[#t.mod + 1] = obj
end
else
assert(obj.REMOVED == nil)
t.add[#t.add + 1] = obj
end
end
end
function multiple_cache:cleanup()
for _, cache_name in ipairs(self.cache_names) do
local cache = self.caches[cache_name]
for key, obj in cache:selectall() do
if obj.REMOVED then
cache:remove(key)
end
end
end
end
return multiple_cache