Software /
code /
prosody-modules
Diff
mod_storage_memory/mod_storage_memory.lua @ 1608:59fdf4f12343
mod_storage_memory: Add support for archive stores
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Thu, 12 Feb 2015 21:17:06 +0100 |
parent | 1607:8b997d9cf09e |
child | 1753:54c8a0cb2996 |
line wrap: on
line diff
--- a/mod_storage_memory/mod_storage_memory.lua Thu Feb 12 15:13:50 2015 +0100 +++ b/mod_storage_memory/mod_storage_memory.lua Thu Feb 12 21:17:06 2015 +0100 @@ -39,9 +39,96 @@ 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 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 {}; + 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] = nil; + return true; + end + local old = self.store[username]; + 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] = 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, 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 = archive_store; } local driver = {};