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 |