techage/basis/storage.lua

144 lines
3.2 KiB
Lua
Raw Normal View History

2020-01-26 01:22:06 +03:00
--[[
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.
]]--
2020-01-31 21:55:10 +03:00
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
2020-02-24 22:59:26 +03:00
local CYCLE_TIME = 60
2020-01-26 01:22:06 +03:00
local NvmStore = {}
local MemStore = {}
local NumNodes = 0
local StoredNodes = 0
2020-01-31 21:55:10 +03:00
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)
2020-01-26 01:22:06 +03:00
local function set_metadata(hash, tbl)
local pos = minetest.get_position_from_hash(hash)
2020-01-31 21:55:10 +03:00
tbl.USED = nil
2020-01-26 01:22:06 +03:00
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
2020-01-31 21:55:10 +03:00
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
2020-01-26 01:22:06 +03:00
set_metadata(hash, tbl)
StoredNodes = StoredNodes + 1
end
2020-01-31 21:55:10 +03:00
else
ToBeDeleted[#ToBeDeleted+1] = hash
2020-01-26 01:22:06 +03:00
end
end
2020-01-31 21:55:10 +03:00
for _,hash in ipairs(ToBeDeleted) do
NvmStore[hash] = nil
end
return #ToBeDeleted
2020-01-26 01:22:06 +03:00
end
local function cyclic_task()
local t = minetest.get_us_time()
2020-01-31 21:55:10 +03:00
Timeslot = (Timeslot + 1) % NUM_SLOTS
2020-01-26 01:22:06 +03:00
NumNodes = 0
StoredNodes = 0
2020-01-31 21:55:10 +03:00
local deleted = nvm_storage()
2020-01-26 01:22:06 +03:00
t = minetest.get_us_time() - t
2020-02-24 22:59:26 +03:00
if StoredNodes > 0 then
minetest.log("action", "[TA NVM Storage] duration="..t.."us, total="..NumNodes..", stored="..StoredNodes..", deleted="..deleted)
end
2020-01-31 21:55:10 +03:00
minetest.after(CYCLE_TIME, cyclic_task)
end
minetest.after(CYCLE_TIME, cyclic_task)
2020-01-26 01:22:06 +03:00
-- To get the volatile node data as table
2020-01-31 21:55:10 +03:00
function techage.get_mem(pos)
2020-01-26 01:22:06 +03:00
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
2020-01-31 21:55:10 +03:00
NvmStore[hash].USED = true
2020-01-26 01:22:06 +03:00
return NvmStore[hash]
end
2020-01-31 21:55:10 +03:00
function techage.peek_nvm(pos)
local hash = minetest.hash_node_position(pos)
return NvmStore[hash] or {}
end
2020-01-26 01:22:06 +03:00
-- 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