Software /
code /
prosody-modules
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]; |