techage/basis/storage.lua
Joachim Stolberg f049f7b18c pipe2 addded
2020-01-31 19:55:10 +01:00

142 lines
3.2 KiB
Lua

--[[
TechAge
=======
Copyright (C) 2019 Joachim Stolberg
GPL v3
See LICENSE.txt for more information
Memory storage system for volatile and non-volatile memory.
Non-volatile memory is stored from time to time and at shutdown
as node metadata. Volatile memory is lost at every shutdown.
]]--
local S = function(pos) if pos then return minetest.pos_to_string(pos) end end
-- Node data will be stored every NUM_SLOTS * CYCLE_TIME seconds
local NUM_SLOTS = 50
local CYCLE_TIME = 30
local NvmStore = {}
local MemStore = {}
local NumNodes = 0
local StoredNodes = 0
local NextNum = 0
local Timeslot = 0
local FNAME = minetest.get_worldpath()..DIR_DELIM.."techage_metadata.txt"
local function read_file()
local f = io.open(FNAME, "r")
if f ~= nil then
local s = f:read("*all")
io.close(f)
return minetest.deserialize(s) or {}
end
return {}
end
local function write_file(tbl)
local s = minetest.serialize(tbl)
local f = io.open(FNAME, "w")
f:write(s)
f:close()
end
NvmStore = read_file()
minetest.register_on_shutdown(function()
write_file(NvmStore)
end)
local function set_metadata(hash, tbl)
local pos = minetest.get_position_from_hash(hash)
tbl.USED = nil
local data = minetest.serialize(tbl)
local meta = minetest.get_meta(pos)
meta:set_string("ta_data", data)
meta:mark_as_private("ta_data")
end
local function get_metadata(hash)
local pos = minetest.get_position_from_hash(hash)
local meta = minetest.get_meta(pos)
local s = meta:get_string("ta_data")
if s ~= "" then
return minetest.deserialize(s)
end
end
local function nvm_storage()
local ToBeDeleted = {}
for hash,tbl in pairs(NvmStore) do
NumNodes = NumNodes + 1
if tbl.USED then
if not tbl.SLOT then
tbl.SLOT = NextNum % NUM_SLOTS
NextNum = NextNum + 1
end
if tbl.SLOT == Timeslot then
set_metadata(hash, tbl)
StoredNodes = StoredNodes + 1
end
else
ToBeDeleted[#ToBeDeleted+1] = hash
end
end
for _,hash in ipairs(ToBeDeleted) do
NvmStore[hash] = nil
end
return #ToBeDeleted
end
local function cyclic_task()
local t = minetest.get_us_time()
Timeslot = (Timeslot + 1) % NUM_SLOTS
NumNodes = 0
StoredNodes = 0
local deleted = nvm_storage()
t = minetest.get_us_time() - t
print("[TA NVM Storage] duration="..t.."us, total="..NumNodes..", stored="..StoredNodes..", deleted="..deleted)
minetest.after(CYCLE_TIME, cyclic_task)
end
minetest.after(CYCLE_TIME, cyclic_task)
-- To get the volatile node data as table
function techage.get_mem(pos)
local hash = minetest.hash_node_position(pos)
if not MemStore[hash] then
MemStore[hash] = {}
end
return MemStore[hash]
end
-- To get the nonvolatile node data as table
function techage.get_nvm(pos)
local hash = minetest.hash_node_position(pos)
if not NvmStore[hash] then
NvmStore[hash] = get_metadata(hash) or {}
end
NvmStore[hash].USED = true
return NvmStore[hash]
end
function techage.peek_nvm(pos)
local hash = minetest.hash_node_position(pos)
return NvmStore[hash] or {}
end
-- To be called when a node is removed
function techage.del_mem(pos)
local meta = minetest.get_meta(pos)
meta:set_string("ta_data", "")
local hash = minetest.hash_node_position(pos)
NvmStore[hash] = nil
MemStore[hash] = nil
end