comparison mod_storage_lmdb/mod_storage_lmdb.lua @ 1981:1f815f57fa57

mod_storage_lmdb: Factor out a transaction wrapper
author Kim Alvefur <zash@zash.se>
date Fri, 18 Dec 2015 22:00:00 +0100
parents 669d1208221a
children bb0b2eae5563
comparison
equal deleted inserted replaced
1980:5e0ee0e4d5b1 1981:1f815f57fa57
6 -- Depends on lightningdbm 6 -- Depends on lightningdbm
7 -- https://github.com/shmul/lightningdbm 7 -- https://github.com/shmul/lightningdbm
8 -- 8 --
9 -- luacheck: globals prosody open 9 -- luacheck: globals prosody open
10 10
11 local assert = assert;
12 local select = select;
13 local xpcall = xpcall;
14 local traceback = debug.traceback;
15
11 local lmdb = require"lightningmdb"; 16 local lmdb = require"lightningmdb";
12 local lfs = require"lfs"; 17 local lfs = require"lfs";
13 local path = require"util.paths"; 18 local path = require"util.paths";
14 local serialization = require"util.serialization"; 19 local serialization = require"util.serialization";
15 local serialize = serialization.serialize; 20 local serialize = serialization.serialize;
16 local deserialize = serialization.deserialize; 21 local deserialize = serialization.deserialize;
22
23 local function transaction(env, func, ...)
24 local args, n_args = {...}, select("#", ...);
25 local t = env:txn_begin(nil, 0);
26 local function f() return func(t, unpack(args, 1, n_args)); end
27 local success, a, b, c = xpcall(f, traceback);
28 if not success then
29 io.stderr:write(a, "\n\n");
30 t:abort();
31 os.exit()
32 return success, a;
33 end
34 local ok, err = t:commit();
35 if not ok then
36 return ok, err;
37 end
38 return success, a, b, c;
39 end
40
41 local function keyvalue_set(t, db, key, value)
42 if value ~= nil then
43 return assert(t:put(db, key, value, 0));
44 else
45 return t:del(db, key, value);
46 end
47 end
48
49 local function keyvalue_get(t, db, key)
50 local data, err = t:get(db, key, 0);
51 assert(data or not err, err);
52 return data;
53 end
17 54
18 local drivers = {}; 55 local drivers = {};
19 local provider = {}; 56 local provider = {};
20 57
21 local keyval = {}; 58 local keyval = {};
22 local keyval_mt = { __index = keyval, flags = lmdb.MDB_CREATE }; 59 local keyval_mt = { __index = keyval, flags = lmdb.MDB_CREATE };
23 drivers.keyval = keyval_mt; 60 drivers.keyval = keyval_mt;
24 61
25 function keyval:set(user, value) 62 function keyval:set(user, value)
26 local t = self.env:txn_begin(nil, 0);
27 if type(value) == "table" and next(value) == nil then 63 if type(value) == "table" and next(value) == nil then
28 value = nil; 64 value = nil;
29 end 65 end
30 if value ~= nil then 66 if value ~= nil then
31 value = serialize(value); 67 value = serialize(value);
32 end 68 end
33 local ok, err; 69 return transaction(self.env, keyvalue_set, self.db, user, value);
34 if value ~= nil then
35 ok, err = t:put(self.db, user, value, 0);
36 else
37 ok, err = t:del(self.db, user, value);
38 end
39 if not ok then
40 t:abort();
41 return nil, err;
42 end
43 return t:commit();
44 end 70 end
45 71
46 function keyval:get(user) 72 function keyval:get(user)
47 local t = self.env:txn_begin(nil, 0); 73 local ok, data = transaction(self.env, keyvalue_get, self.db, user);
48 local data, err = t:get(self.db, user, 0); 74 if not ok then return ok, data; end
49 if not data then
50 t:abort();
51 return nil, err;
52 end
53 t:commit();
54 return deserialize(data); 75 return deserialize(data);
55 end 76 end
56 77
57 function provider:init(config) 78 function provider:init(config)
58 if config.base_path then 79 if config.base_path then
93 base_path = path.resolve_relative_path(prosody.paths.data, module.host); 114 base_path = path.resolve_relative_path(prosody.paths.data, module.host);
94 flags = module:get_option_set("lmdb_flags", {}); 115 flags = module:get_option_set("lmdb_flags", {});
95 maxdbs = module:get_option_number("lmdb_maxdbs", 20); 116 maxdbs = module:get_option_number("lmdb_maxdbs", 20);
96 }); 117 });
97 118
98 function module.unload() 119 function module.unload() --luacheck: ignore
99 provider.env:sync(1); 120 provider.env:sync(1);
100 provider.env:close(); 121 provider.env:close();
101 end 122 end
102 123
103 module:provides("storage", provider); 124 module:provides("storage", provider);