Mercurial > prosody-modules
view mod_storage_memory/mod_storage_memory.lua @ 2398:7e922b968b44
mod_storage_xmlarchive: Find item indices for 'before' or 'after' queries and behave as if they were excluded if the items don't exist (thanks MattJ)
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Fri, 25 Nov 2016 23:17:13 +0100 |
parents | a347b71adb07 |
children | 1e4bbff0a6fd |
line wrap: on
line source
local memory = setmetatable({}, { __index = function(t, k) local store = module:shared(k) t[k] = store; return store; end }); local NULL = {}; local keyval_store = {}; keyval_store.__index = keyval_store; function keyval_store:get(username) return self.store[username or NULL]; end function keyval_store:set(username, data) self.store[username or NULL] = data; return true; end local map_store = {}; map_store.__index = map_store; function map_store:get(username, key) local userstore = self.store[username or NULL]; if type(userstore) == "table" then return userstore[key]; end end function map_store:set(username, key, data) local userstore = self.store[username or NULL]; if userstore == nil then userstore = {}; self.store[username or NULL] = userstore; end userstore[key] = data; return true; end map_store.remove = {}; function map_store:set_keys(username, keydatas) local userstore = self.store[username or NULL]; if userstore == nil then userstore = {}; self.store[username or NULL] = userstore; end for k,v in pairs(keydatas) do if v == self.remove then v = nil; end userstore[k] = v; end return true; end local archive_store = {}; archive_store.__index = archive_store; function archive_store:append(username, key, value, when, with) if type(when) ~= "number" then when, with, value = value, when, with; end local a = self.store[username or NULL]; if not a then a = {}; self.store[username or NULL] = a; end local i = #a+1; local v = { key = key, when = when, with = with, value = value }; if not key or a[key] then key = tostring(a):match"%x+$"..tostring(v):match"%x+$"; v.key = key; end a[i] = v; a[key] = i; return true; end local function archive_iter (a, start, stop, step, limit, when_start, when_end, match_with) local item, when, with; local count = 0; coroutine.yield(true); -- Ready 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); count = count + 1; if limit and count >= limit then return end end end end function archive_store:find(username, query) local a = self.store[username or NULL] or {}; local start, stop, step = 1, #a, 1; local qstart, qend, qwith = -math.huge, math.huge; local limit; if query then module:log("debug", "query included") 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 limit = query.limit; qstart = query.start or qstart; qend = query["end"] or qend; end if not start then return nil, "invalid-key"; end local iter = coroutine.wrap(archive_iter); iter(a, start, stop, step, limit, qstart, qend, qwith); return iter; end function archive_store:delete(username, query) if not query or next(query) == nil then self.store[username or NULL] = nil; return true; end local old = self.store[username or NULL]; if not old then return true; end local qstart = query.start or -math.huge; local qend = query["end"] or math.huge; local qwith = query.with; local new = {}; self.store[username or NULL] = new; local t; for i = 1, #old do i = old[i]; t = i.when; if not(qstart >= t and qend <= t and (not qwith or i.with == qwith)) then self:append(username, i.key, i.value, t, i.with); end end if #new == 0 then self.store[username or NULL] = nil; end return true; end local stores = { keyval = keyval_store; map = map_store; archive = archive_store; } 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);