-
Notifications
You must be signed in to change notification settings - Fork 1
/
mod_storage_multi.lua
81 lines (71 loc) · 2.21 KB
/
mod_storage_multi.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
-- mod_storage_multi
local storagemanager = require"core.storagemanager";
local backends = module:get_option_array(module.name); -- TODO better name?
-- TODO migrate data "upwards"
-- one → one successful write is success
-- all → all backends must report success
-- majority → majority of backends must report success
local policy = module:get_option_string(module.name.."_policy", "all");
local keyval_store = {};
keyval_store.__index = keyval_store;
function keyval_store:get(username)
local backends = self.backends;
local data, err;
for i = 1, #backends do
module:log("debug", "%s:%s:get(%q)", tostring(backends[i].get), backends[i]._store, username);
data, err = backends[i]:get(username);
if err then
module:log("error", tostring(err));
elseif not data then
module:log("debug", "No data returned");
else
module:log("debug", "Data returned");
return data, err;
end
end
end
-- This is where it gets complicated
function keyval_store:set(username, data)
local backends = self.backends;
local ok, err, backend;
local all, one, oks = true, false, 0;
for i = 1, #backends do
backend = backends[i];
module:log("debug", "%s:%s:set(%q)", tostring(backends[i].get), backends[i].store, username);
ok, err = backend:set(username, data);
if not ok then
module:log("error", "Error in storage driver %s: %s", backend.name, tostring(err));
else
oks = oks + 1;
end
one = one or ok; -- At least one successful write
all = all and ok; -- All successful
end
if policy == "all" then
return all, err
elseif policy == "majority" then
return oks > (#backends/2), err;
end
-- elseif policy == "one" then
return one, err;
end
local stores = {
keyval = keyval_store;
}
local driver = {};
function driver:open(store, typ)
local store_mt = stores[typ or "keyval"];
if store_mt then
local my_backends = {};
local driver, opened
for i = 1, #backends do
driver = storagemanager.load_driver(module.host, backends[i]);
opened = driver:open(store, typ);
my_backends[i] = assert(driver:open(store, typ));
my_backends[i]._store = store;
end
return setmetatable({ backends = my_backends }, store_mt);
end
return nil, "unsupported-store";
end
module:provides("storage", driver);