Comparison

mod_storage_gdbm/mod_storage_gdbm.lua @ 1596:b362e6c00fd1

mod_storage_gdbm: Add archive support
author Kim Alvefur <zash@zash.se>
date Sun, 25 Jan 2015 22:18:05 +0100
parent 1595:6288591d5edf
child 1602:3912a53fd4db
comparison
equal deleted inserted replaced
1595:6288591d5edf 1596:b362e6c00fd1
7 -- http://webserver2.tecgraf.puc-rio.br/~lhf/ftp/lua/#lgdbm 7 -- http://webserver2.tecgraf.puc-rio.br/~lhf/ftp/lua/#lgdbm
8 8
9 local gdbm = require"gdbm"; 9 local gdbm = require"gdbm";
10 local path = require"util.paths"; 10 local path = require"util.paths";
11 local lfs = require"lfs"; 11 local lfs = require"lfs";
12 local uuid = require"util.uuid".generate;
12 local serialization = require"util.serialization"; 13 local serialization = require"util.serialization";
14 local st = require"util.stanza";
13 local serialize = serialization.serialize; 15 local serialize = serialization.serialize;
14 local deserialize = serialization.deserialize; 16 local deserialize = serialization.deserialize;
17
18 local function id(v) return v; end
19
20 local function is_stanza(s)
21 return getmetatable(s) == st.stanza_mt;
22 end
23
24 local function ifelse(cond, iftrue, iffalse)
25 if cond then return iftrue; end return iffalse;
26 end
15 27
16 local base_path = path.resolve_relative_path(prosody.paths.data, module.host); 28 local base_path = path.resolve_relative_path(prosody.paths.data, module.host);
17 lfs.mkdir(base_path); 29 lfs.mkdir(base_path);
18 30
19 local cache = {}; 31 local cache = {};
31 local data, err = gdbm.fetch(self._db, user or "@"); 43 local data, err = gdbm.fetch(self._db, user or "@");
32 if not data then return nil, err; end 44 if not data then return nil, err; end
33 return deserialize(data); 45 return deserialize(data);
34 end 46 end
35 47
48 local archive = {};
49 local archive_mt = { __index = archive, suffix = ".adb" };
50
51 archive.get = keyval.get;
52 archive.set = keyval.set;
53
54 function archive:append(username, key, when, with, value)
55 key = key or uuid();
56 local meta = self:get(username);
57 if not meta then
58 meta = {};
59 end
60 local i = meta[key] or #meta+1;
61 local type;
62 if is_stanza(value) then
63 type, value = "stanza", st.preserialize(value);
64 end
65 meta[i] = { key = key, when = when, with = with, type = type };
66 meta[key] = i;
67 local ok, err = self:set(username, meta);
68 if not ok then return nil, err; end
69 ok, err = self:set(key, value);
70 if not ok then return nil, err; end
71 return key;
72 end
73
74 local deserialize = {
75 stanza = st.deserialize;
76 };
77
78 function archive:find(username, query)
79 local meta = self:get(username);
80 local r = query.reverse;
81 local d = r and -1 or 1;
82 local s = meta[ifelse(r, query.before, meta.after)];
83 if s then
84 s = s + d;
85 else
86 s = ifelse(r, #meta, 1)
87 end
88 local e = ifelse(r, 1, #meta);
89 return function ()
90 local item, value;
91 for i = s, e, d do
92 item = meta[i];
93 if (not query.with or item.with == query.with)
94 and (not query.start or item.when >= query.start)
95 and (not query["end"] or item.when >= query["end"]) then
96 s = i + d;
97 value = self:get(item.key);
98 return item.key, (deserialize[item.type] or id)(value), item.when, item.with;
99 end
100 end
101 end
102 end
103
36 local drivers = { 104 local drivers = {
37 keyval = keyval_mt; 105 keyval = keyval_mt;
106 archive = archive_mt;
38 } 107 }
39 108
40 function open(_, store, typ) 109 function open(_, store, typ)
41 typ = typ or "keyval"; 110 typ = typ or "keyval";
42 local driver_mt = drivers[typ]; 111 local driver_mt = drivers[typ];