comparison mod_storage_lmdb/mod_storage_lmdb.lua @ 1755:0a21b16b9075

mod_storage_lmdb: Storage module using Lightning Memory-Mapped Database
author Kim Alvefur <zash@zash.se>
date Tue, 19 May 2015 23:29:37 +0200
parents
children d2dd1db9ece6
comparison
equal deleted inserted replaced
1754:c04d10557bbc 1755:0a21b16b9075
1 -- mod_storage_lmdb
2 -- Copyright (C) 2015 Kim Alvefur
3 --
4 -- This file is MIT/X11 licensed.
5 --
6 -- Depends on lightningdbm
7 -- https://github.com/shmul/lightningdbm
8 --
9 -- luacheck: globals prosody open
10
11 local lmdb = require"lightningmdb";
12 local lfs = require"lfs";
13 local path = require"util.paths";
14 local serialization = require"util.serialization";
15 local serialize = serialization.serialize;
16 local deserialize = serialization.deserialize;
17
18 local base_path = path.resolve_relative_path(prosody.paths.data, module.host);
19 lfs.mkdir(base_path);
20
21 local env = lmdb.env_create();
22 assert(env:set_maxdbs(module:get_option_number("lmdb_maxdbs", 20)));
23 local env_flags = 0;
24 for i, flag in ipairs(module:get_option_array("lmdb_flags", {})) do
25 env_flags = env_flags + assert(lmdb["MDB_"..flag:upper()], "No such flag "..flag);
26 end
27 env:open(base_path, env_flags, tonumber("640", 8));
28
29 local keyval = {};
30 local keyval_mt = { __index = keyval, flags = lmdb.MDB_CREATE };
31
32 function keyval:set(user, value)
33 local t = self.env:txn_begin(nil, 0);
34 if type(value) == "table" and next(value) == nil then
35 value = nil;
36 end
37 if value ~= nil then
38 value = serialize(value);
39 end
40 local ok, err;
41 if value ~= nil then
42 ok, err = t:put(self.db, user, value, 0);
43 else
44 ok, err = t:del(self.db, user, value);
45 end
46 if not ok then
47 t:abort();
48 return nil, err;
49 end
50 return t:commit();
51 end
52
53 function keyval:get(user)
54 local t = self.env:txn_begin(nil, 0);
55 local data, err = t:get(self.db, user, 0);
56 if not data then
57 t:abort();
58 return nil, err;
59 end
60 t:commit();
61 return deserialize(data);
62 end
63
64 local drivers = {
65 keyval = keyval_mt;
66 }
67
68 function open(_, store, typ)
69 typ = typ or "keyval";
70 local driver_mt = drivers[typ];
71 if not driver_mt then
72 return nil, "unsupported-store";
73 end
74 local t = env:txn_begin(nil, 0);
75 local db = t:dbi_open(store.."_"..typ, driver_mt.flags);
76 assert(t:commit());
77
78 return setmetatable({ env = env, store = store, type = typ, db = db }, driver_mt);
79 end
80
81 function module.unload()
82 env:sync(1);
83 env:close();
84 end
85
86 module:provides("storage");