Mercurial > prosody-modules
changeset 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 (2015-05-19) |
parents | c04d10557bbc |
children | c619425dafe7 |
files | mod_storage_lmdb/mod_storage_lmdb.lua |
diffstat | 1 files changed, 86 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_storage_lmdb/mod_storage_lmdb.lua Tue May 19 23:29:37 2015 +0200 @@ -0,0 +1,86 @@ +-- mod_storage_lmdb +-- Copyright (C) 2015 Kim Alvefur +-- +-- This file is MIT/X11 licensed. +-- +-- Depends on lightningdbm +-- https://github.com/shmul/lightningdbm +-- +-- luacheck: globals prosody open + +local lmdb = require"lightningmdb"; +local lfs = require"lfs"; +local path = require"util.paths"; +local serialization = require"util.serialization"; +local serialize = serialization.serialize; +local deserialize = serialization.deserialize; + +local base_path = path.resolve_relative_path(prosody.paths.data, module.host); +lfs.mkdir(base_path); + +local env = lmdb.env_create(); +assert(env:set_maxdbs(module:get_option_number("lmdb_maxdbs", 20))); +local env_flags = 0; +for i, flag in ipairs(module:get_option_array("lmdb_flags", {})) do + env_flags = env_flags + assert(lmdb["MDB_"..flag:upper()], "No such flag "..flag); +end +env:open(base_path, env_flags, tonumber("640", 8)); + +local keyval = {}; +local keyval_mt = { __index = keyval, flags = lmdb.MDB_CREATE }; + +function keyval:set(user, value) + local t = self.env:txn_begin(nil, 0); + if type(value) == "table" and next(value) == nil then + value = nil; + end + if value ~= nil then + value = serialize(value); + end + local ok, err; + if value ~= nil then + ok, err = t:put(self.db, user, value, 0); + else + ok, err = t:del(self.db, user, value); + end + if not ok then + t:abort(); + return nil, err; + end + return t:commit(); +end + +function keyval:get(user) + local t = self.env:txn_begin(nil, 0); + local data, err = t:get(self.db, user, 0); + if not data then + t:abort(); + return nil, err; + end + t:commit(); + return deserialize(data); +end + +local drivers = { + keyval = keyval_mt; +} + +function open(_, store, typ) + typ = typ or "keyval"; + local driver_mt = drivers[typ]; + if not driver_mt then + return nil, "unsupported-store"; + end + local t = env:txn_begin(nil, 0); + local db = t:dbi_open(store.."_"..typ, driver_mt.flags); + assert(t:commit()); + + return setmetatable({ env = env, store = store, type = typ, db = db }, driver_mt); +end + +function module.unload() + env:sync(1); + env:close(); +end + +module:provides("storage");