Mercurial > prosody-modules
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); |
