colddb/colddb.lua
2019-05-23 10:27:02 -05:00

333 lines
6.4 KiB
Lua

colddb = {}
colddb.serializers = {}
colddb.serializers.default = 0
function colddb.Colddb(dir)
if not minetest.mkdir(dir) then
error(string.format("%s is not a directory.", dir))
end
local self = {}
local directory = dir
local mem_pool = {}
local mem_pool_del = {}
local add_to_mem_pool = true
local async = async.Async()
local use_async = true
local serializer = minetest.serialize
local deserializer = minetest.deserialize
local serializer_type = colddb.serializers.default
async.priority(150, 250)
-- make tables weak so the garbage-collector will remove unused data
setmetatable(mem_pool, {__mode = "kv"})
setmetatable(mem_pool_del, {__mode = "kv"})
self.get_directory = function()
return directory
end
self.set_directory = function(new_directory)
directory = new_directory
if not minetest.mkdir(directory) then
error(string.format("%s is not a directory.", dir))
end
end
self.get_memory_pool = function()
return mem_pool
end
self.set_memory_pool = function(pool)
mem_pool = pool
end
self.get_async = function()
return async
end
self.set_async = function(new_async)
async = new_async
end
self.add_to_memory_pool = function(value)
if value then
add_to_mem_pool = value
end
return add_to_mem_pool
end
self.use_async = function(value)
use_async = value
end
self.get_serializer_type = function()
return serializer_type
end
self.set_serializer_type = function(value)
serializer_type = value
if serializer_type == colddb.serializers.default then
serializer = minetest.serialize
deserializer = minetest.deserialize
end
end
self.get_serializer = function()
return serializer, deserializer
end
self.set_serializer = function(coder, decoder)
serializer = coder
deserializer = decoder
end
local function file_exists(name)
local f = io.open(string.format("%s/%s.cold", directory, name), "r")
if f ~= nil then
io.close(f)
return true
else
return false
end
return false
end
local function load_into_mem(name, _table)
if add_to_mem_pool then
mem_pool[name] = {mem = _table}
end
end
self.exists = function(name)
return file_exists(name)
end
local function delete_file(name)
local text = string.format("%s/%s.cold", directory, name)
local err, msg = os.remove(text)
if err == nil then
minetest.log(string.format("error removing db data %s error message: %s", text, msg))
end
end
local function load_table(name)
local f = io.open(string.format("%s/%s.cold", directory, name), "r")
if f then
local data = deserializer(f:read("*a"))
f:close()
return data
end
return nil
end
local function save_table(name, _table)
minetest.log(string.format("%s/%s.cold", directory, name))
if save_table == nil or name == nil then
return false
end
return minetest.safe_file_write(string.format("%s/%s.cold", directory, name), minetest.serialize(_table))
end
local function save_key(name)
return minetest.safe_file_write(string.format("%s/%s.cold", directory, name), "")
end
local function load_key(name)
local f = io.open(string.format("%s/%s.cold", directory, name), "r")
if f then
f:close()
return true
end
return false
end
self.set_mem = function(name, _table)
load_into_mem(name, _table)
mem_pool_del[name] = nil
end
self.save_mem = function(name)
if use_async then
async.queue_task(function()
if mem_pool[name] ~= nil then
save_table(name, mem_pool[name].mem)
end
end)
else
if mem_pool[name] ~= nil then
save_table(name, mem_pool[name].mem)
end
end
mem_pool_del[name] = nil
end
self.clear_mem = function(name)
mem_pool[name] = nil
mem_pool_del[name] = nil
end
self.set = function(name, _table)
if use_async then
async.queue_task(function()
save_table(name, _table)
end)
else
save_table(name, _table)
end
if add_to_mem_pool then
load_into_mem(name, _table)
end
mem_pool_del[name] = nil
end
self.set_key = function(name)
if use_async then
async.queue_task(function()
save_key(name)
end)
else
save_key(name)
end
if add_to_mem_pool then
load_into_mem(name, "")
end
mem_pool_del[name] = nil
end
self.get = function(name, callback)
if mem_pool_del[name] then
if callback then
callback(nil)
end
return nil
end
if callback then
async.queue_task(function()
local pm = mem_pool[name]
if pm then
return pm.mem
else
local _table = load_table(name)
if _table then
load_into_mem(name, _table)
return _table
end
end
mem_pool_del[name] = true
return nil
end,callback)
else
local pm = mem_pool[name]
if pm then
return pm.mem
else
local _table = load_table(name)
if _table then
load_into_mem(name, _table)
return _table
end
end
mem_pool_del[name] = true
return nil
end
end
self.get_key = function(name, callback)
if mem_pool_del[name] then
if callback then
callback(false)
end
return false
end
if callback then
async.queue_task(function()
local pm = mem_pool[name]
if pm then
return true
else
local bool = load_key(name)
if bool then
load_into_mem(name, bool)
return bool
end
end
mem_pool_del[name] = true
return nil
end,callback)
else
local pm = mem_pool[name]
if pm then
return true
else
local bool = load_key(name)
if bool then
load_into_mem(name, bool)
return bool
end
end
mem_pool_del[name] = true
return nil
end
end
self.remove = function(name)
mem_pool[name] = nil
mem_pool_del[name] = true
if use_async then
async.queue_task(function()
delete_file(name)
end)
else
delete_file(name)
end
end
self.sub_database = function(path)
local db = colddb.Colddb(dir .. "/" .. path)
db.set_async(async)
return db
end
self.to_array = function()
local entries = {}
for k, v in pairs(minetest.get_dir_list(directory, false)) do
entries[#entries + 1] = v:sub(0, v:len() - 5)
end
return entries
end
self.to_table = function()
local entries = {}
for k, v in pairs(minetest.get_dir_list(directory, false)) do
entries[v:sub(0, v:len() - 5)] = true
end
return entries
end
self.iterate = function()
local entries = {}
for k, v in pairs(minetest.get_dir_list(directory, false)) do
entries[v:sub(0, v:len() - 5)] = true
end
return pairs(entries)
end
return self
end