mod_storage_gdbm: Use require directly instead of util.import (which is not available in prosodyctl, breaks adduser etc)
local memory = setmetatable({}, {
__index = function(t, k)
local store = module:shared(k)
t[k] = store;
return store;
end
});
local keyval_store = {};
keyval_store.__index = keyval_store;
function keyval_store:get(username)
return self.store[username];
end
function keyval_store:set(username, data)
self.store[username] = data;
return true;
end
local map_store = {};
map_store.__index = map_store;
function map_store:get(username, key)
local userstore = self.store[username];
if type(userstore) == "table" then
return userstore[key];
end
end
function map_store:set(username, key, data)
local userstore = self.store[username];
if userstore == nil then
userstore = {};
self.store[username] = userstore;
end
userstore[key] = data;
return true;
end
local archive_store = {};
archive_store.__index = archive_store;
function archive_store:append(username, key, when, with, value)
local a = self.store[username];
if not a then
a = {};
self.store[username] = a;
end
local i = #a+1;
local v = { key = key, when = when, with = with, value = value };
if not key then
key = tostring(a):match"%x+$"..tostring(v):match"%x+$";
v.key = key;
end
a[i] = v;
a[key] = i;
return true;
end
function archive_store:find(username, query)
local a = self.store[username] or {};
local start, stop, step = 1, #a, 1;
if query then
if query.reverse then
start, stop, step = stop, start, -1;
if query.before then
start = a[query.before];
end
elseif query.after then
start = a[query.after];
end
end
if not start then return nil, "invalid-key";
local iter = coroutine.wrap(function (a, start, stop, step, when_start, when_end, match_with)
local item, when, with;
for i = start, stop, step do
item = a[i];
when, with = item.when, item.with;
if when >= when_start and when_end >= when and (not match_with or match_with == with) then
coroutine.yield(item.key, item.value, when, with);
end
end
end);
iter(a, start, stop, step, query and query.start or 0, query and query["end"] or math.huge, query and query.with);
return iter;
end
function archive_store:delete(username, query)
if not query then
self.store[username] = nil;
return true;
end
local old = self.store[username];
if not old then return true; end
local qstart = query.start or 0;
local qend = query["end"] or math.huge;
local with = query.with;
local new = {};
self.store[username] = new;
local t;
for i = 1, #old do
i = old[i];
t = i.when;
if not(qstart >= t and qend <= t and (not with or i.with == with)) then
self:append(username, i.key, t, i.with, i.value);
end
end
if #new == 0 then
self.store[username] = nil;
end
return true;
end
local stores = {
keyval = keyval_store;
map = map_store;
archive = nil;
}
local driver = {};
function driver:open(store, typ)
local store_mt = stores[typ or "keyval"];
if store_mt then
return setmetatable({ store = memory[store] }, store_mt);
end
return nil, "unsupported-store";
end
module:provides("storage", driver);