changeset 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
parents 8b997d9cf09e
children 5f139770061e
files mod_storage_memory/mod_storage_memory.lua
diffstat 1 files changed, 87 insertions(+), 0 deletions(-) [+]
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 = {};