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