Software /
code /
prosody-modules
Comparison
mod_storage_appendmap/mod_storage_appendmap.lua @ 2061:b84284144e21
mod_storage_appendmap: Experimental storage module optimized for map stores
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sun, 06 Mar 2016 17:03:19 +0100 |
child | 2062:8f7083b980cf |
comparison
equal
deleted
inserted
replaced
2060:bd0c5d546bf8 | 2061:b84284144e21 |
---|---|
1 local dump = require "util.serialization".serialize; | |
2 local load = require "util.envload".envloadfile; | |
3 local dm = require "core.storagemanager".olddm; | |
4 | |
5 local driver = {}; | |
6 | |
7 local map = {}; | |
8 local map_mt = { __index = map }; | |
9 map.remove = {}; | |
10 | |
11 function map:get(user, key) | |
12 module:log("debug", "map:get(%s, %s)", tostring(user), tostring(key)) | |
13 local filename = dm.getpath(user, module.host, self.store, "map"); | |
14 module:log("debug", "File is %s", filename); | |
15 local env = {}; | |
16 if _VERSION == "Lua 5.1" then -- HACK | |
17 env._ENV = env; -- HACK | |
18 end -- SO MANY HACKS | |
19 local chunk, err = load(filename, env); | |
20 if not chunk then return chunk, err; end | |
21 local ok, err = pcall(chunk); | |
22 if not ok then return ok, err; end | |
23 if _VERSION == "Lua 5.1" then -- HACK | |
24 env._ENV = nil; -- HACK | |
25 end -- HACKS EVERYWHERE | |
26 if key == nil then | |
27 return env; | |
28 end | |
29 return env[key]; | |
30 end | |
31 | |
32 function map:set_keys(user, keyvalues) | |
33 local keys, values = {}, {}; | |
34 if _VERSION == "Lua 5.1" then | |
35 assert(not keyvalues._ENV, "'_ENV' is a restricted key"); | |
36 end | |
37 for key, value in pairs(keyvalues) do | |
38 module:log("debug", "user %s sets %q to %s", user, key, tostring(value)) | |
39 if type(key) ~= "string" or not key:find("^[%w_][%w%d_]*$") or key == "_ENV" then | |
40 key = "_ENV[" .. dump(key) .. "]"; | |
41 end | |
42 table.insert(keys, key); | |
43 if value == self.remove then | |
44 table.insert(values, "nil") | |
45 else | |
46 table.insert(values, dump(value)) | |
47 end | |
48 end | |
49 local data = table.concat(keys, ", ") .. " = " .. table.concat(values, ", ") .. ";\n"; | |
50 return dm.append_raw(user, module.host, self.store, "map", data); | |
51 end | |
52 | |
53 function map:set(user, key, value) | |
54 if _VERSION == "Lua 5.1" then | |
55 assert(key ~= "_ENV", "'_ENV' is a restricted key"); | |
56 end | |
57 if key == nil then | |
58 local filename = dm.getpath(user, module.host, self.store, "map"); | |
59 os.remove(filename); | |
60 return true; | |
61 end | |
62 if type(key) ~= "string" or not key:find("^[%w_][%w%d_]*$") or key == "_ENV" then | |
63 key = "_ENV[" .. dump(key) .. "]"; | |
64 end | |
65 local data = key .. " = " .. dump(value) .. ";\n"; | |
66 return dm.append_raw(user, module.host, self.store, "map", data); | |
67 end | |
68 | |
69 local keyval = {}; | |
70 local keyval_mt = { __index = keyval }; | |
71 | |
72 function keyval:get(user) | |
73 return map.get(self, user); | |
74 end | |
75 | |
76 keyval.set = map.set_keys; | |
77 | |
78 -- TODO some kind of periodic compaction thing? | |
79 function map:_compact(user) | |
80 local data = self:get(user); | |
81 return keyval.set(self, user, data); | |
82 end | |
83 | |
84 function driver:open(store, typ) | |
85 if typ == "map" then | |
86 return setmetatable({ store = store, }, map_mt); | |
87 elseif typ == nil or typ == "keyval" then | |
88 return setmetatable({ store = store, }, keyval_mt); | |
89 end | |
90 return nil, "unsupported-store"; | |
91 end | |
92 | |
93 module:provides("storage", driver); | |
94 |