Software /
code /
prosody-modules
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 |
child | 1799: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"); |