Custom InvRef implementation for in-memory cache

This commit is contained in:
Evert Prants 2018-04-09 23:43:15 +03:00
parent dfc8e4adcc
commit 109f6e1aa6
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
8 changed files with 243 additions and 107 deletions

View File

@ -66,7 +66,7 @@ if quartz then
minetest.register_craft({ minetest.register_craft({
type = "cooking", type = "cooking",
output = "holostorage:silicon", output = "holostorage:silicon",
recipe = "holostorage:quartz_iron" recipe = "quartz:quartz_crystal"
}) })
else else
minetest.register_craft({ minetest.register_craft({

View File

@ -7,6 +7,9 @@ holostorage.modpath = modpath
holostorage.devices = {} holostorage.devices = {}
-- Memory Storage
dofile(modpath.."/masscache.lua")
-- Network -- Network
dofile(modpath.."/network.lua") dofile(modpath.."/network.lua")

View File

@ -1,29 +1,6 @@
-- Storage disks -- Storage disks
holostorage.disks = {} holostorage.disks = {}
holostorage.disks.memcache = {}
local function inv_to_table(inv)
local t = {}
for listname, list in pairs(inv:get_lists()) do
local size = inv:get_size(listname)
if size then
t[listname] = {}
for i = 1, size, 1 do
t[listname][i] = inv:get_stack(listname, i):to_table()
end
end
end
return t
end
local function table_to_inv(inv, t)
for listname, list in pairs(t) do
for i, stack in pairs(list) do
inv:set_stack(listname, i, stack)
end
end
end
function holostorage.disks.register_disk(index, desc, capacity) function holostorage.disks.register_disk(index, desc, capacity)
local mod = minetest.get_current_modname() local mod = minetest.get_current_modname()
@ -40,88 +17,12 @@ function holostorage.disks.register_disk(index, desc, capacity)
}) })
end end
local function create_invref(ptr, capacity)
local inv = minetest.create_detached_inventory(ptr, {})
inv:set_size("main", capacity)
return inv
end
function holostorage.disks.ensure_disk_inventory(stack, pstr)
local meta = stack:get_meta()
local tag = meta:get_string("storage_tag")
local cap = minetest.registered_items[stack:get_name()].holostorage_capacity
if not tag or tag == "" then
local rnd = PseudoRandom(os.clock())
local rndint = rnd.next(rnd)
local diskid = "d"..pstr.."-"..rndint
meta:set_string("storage_tag", diskid)
holostorage.disks.memcache[diskid] = create_invref(diskid, cap)
end
return stack
end
function holostorage.disks.load_disk_from_file(stack, diskptr)
local world = minetest.get_worldpath()
local directory = world.."/holostorage"
local cap = minetest.registered_items[stack:get_name()].holostorage_capacity
local inv = create_invref(diskptr, cap)
minetest.mkdir(directory)
local filetag = minetest.sha1(diskptr)..".invref"
local file = io.open(directory.."/"..filetag)
if not file then
holostorage.disks.memcache[diskptr] = inv
return diskptr
end
local str = ""
for line in file:lines() do
str = str..line
end
file:close()
table_to_inv(inv, minetest.deserialize(str))
holostorage.disks.memcache[diskptr] = inv
return diskptr
end
function holostorage.disks.save_disk_to_file(diskptr)
if not holostorage.disks.memcache[diskptr] then return nil end
local world = minetest.get_worldpath()
local directory = world.."/holostorage"
local filetag = minetest.sha1(diskptr)..".invref"
minetest.mkdir(directory)
local inv = holostorage.disks.memcache[diskptr]
local data = minetest.serialize(inv_to_table(inv))
minetest.safe_file_write(directory.."/"..filetag, data)
return diskptr
end
function holostorage.disks.save_disks_to_file()
for diskptr in pairs(holostorage.disks.memcache) do
holostorage.disks.save_disk_to_file(diskptr)
end
end
-- Make sure stack is disk -- Make sure stack is disk
function holostorage.disks.is_valid_disk(stack) function holostorage.disks.is_valid_disk(stack)
local stack_name = stack:get_name() local stack_name = stack:get_name()
return minetest.get_item_group(stack_name, "holostorage_disk") > 0 return minetest.get_item_group(stack_name, "holostorage_disk") > 0
end end
-- Save disks on shutdown
minetest.register_on_shutdown(function ()
holostorage.disks.save_disks_to_file()
end)
local capacities = {1000, 8000, 16000, 32000, 64000} local capacities = {1000, 8000, 16000, 32000, 64000}
local descriptions = {"1K Disk", "8K Disk", "16K Disk", "32K Disk", "64K Disk"} local descriptions = {"1K Disk", "8K Disk", "16K Disk", "32K Disk", "64K Disk"}
for i = 1, 5 do for i = 1, 5 do

233
masscache.lua Normal file
View File

@ -0,0 +1,233 @@
-- INVENTORY CACHE
holostorage.server_inventory = {
cache = {},
new = function (size)
local system = {
size = size,
stacks = {}
}
function system:get_size(abs)
return system.size
end
function system:get_stack(abs, index)
if not index then index = abs end
if system.stacks[index] then
return system.stacks[index]
end
return ItemStack(nil)
end
function system:set_stack(abs, index, stack)
if not stack then
stack = index
index = abs
end
if type(stack) == "table" or type(stack) == "string" then
stack = ItemStack(stack)
end
system.stacks[index] = stack
return stack
end
function system:get_list(abs)
return system.stacks
end
function system:set_list(abs, list)
if not list then list = abs end
system.stacks = list
end
function system:get_width(abs)
local size = 0
for _,v in pairs(system.stacks) do
if v and not v:is_empty() then
size = size + 1
end
end
return size
end
function system:first_empty_index()
local index = 0
local last = 0
for inx, stack in pairs(system.stacks) do
if stack:is_empty() then
index = inx
break
end
if last ~= inx - 1 then
index = inx - 1
break
end
last = inx
end
if index == 0 then
return #system.stacks + 1
end
return index
end
function system:room_for_item(abs, stack)
if not stack then stack = abs end
local matching = false
if system:get_width() < system.size then return true end
for _,stc in pairs(system.stacks) do
if not stc or stc:is_empty() then
matching = true
break
end
if stc:get_name() == stack:get_name() and
stc:get_meta() == stack:get_meta() then
if stc:item_fits(stack) then
matching = true
break
end
end
end
return matching
end
function system:add_item(abs, stack)
if not stack then stack = abs end
local leftover = nil
for i,stc in pairs(system.stacks) do
if not stc or stc:is_empty() then
system[i] = stack
break
end
if stc:get_name() == stack:get_name() and stc:get_meta() == stack:get_meta() then
if stc:get_count() == stack:get_stack_max() then
break
end
leftover = system.stacks[i]:add_item(stack)
if leftover and not leftover:is_empty() and system:room_for_item(leftover) then
leftover = system:add_item(leftover)
end
else
break
end
end
if not leftover then
system.stacks[system:first_empty_index()] = stack
leftover = ItemStack(nil)
end
return leftover
end
return system
end,
from_table = function (inv, table)
if table["main"] then
table = table["main"]
end
for i, stack in pairs(table) do
inv:set_stack(i, stack)
end
return inv
end,
to_table = function (inv)
local t = {}
local size = inv:get_size()
if size then
for i = 1, size, 1 do
t[i] = inv:get_stack(i):to_table()
end
end
return t
end
}
local function create_invref(capacity)
return holostorage.server_inventory.new(capacity)
end
function holostorage.server_inventory.ensure_disk_inventory(stack, pstr)
local meta = stack:get_meta()
local tag = meta:get_string("storage_tag")
local cap = minetest.registered_items[stack:get_name()].holostorage_capacity
if not tag or tag == "" then
local rnd = PseudoRandom(os.clock())
local rndint = rnd.next(rnd)
local diskid = "d"..pstr.."-"..rndint
meta:set_string("storage_tag", diskid)
holostorage.server_inventory.cache[diskid] = create_invref(cap)
end
return stack
end
function holostorage.server_inventory.load_disk_from_file(stack, diskptr)
local world = minetest.get_worldpath()
local directory = world.."/holostorage"
local cap = minetest.registered_items[stack:get_name()].holostorage_capacity
local inv = create_invref(cap)
minetest.mkdir(directory)
local filetag = minetest.sha1(diskptr)..".invref"
local file = io.open(directory.."/"..filetag)
if not file then
holostorage.server_inventory.cache[diskptr] = inv
return diskptr
end
local str = ""
for line in file:lines() do
str = str..line
end
file:close()
holostorage.server_inventory.from_table(inv, minetest.deserialize(str))
holostorage.server_inventory.cache[diskptr] = inv
return diskptr
end
function holostorage.server_inventory.save_disk_to_file(diskptr)
if not holostorage.server_inventory.cache[diskptr] then return nil end
local world = minetest.get_worldpath()
local directory = world.."/holostorage"
local filetag = minetest.sha1(diskptr)..".invref"
minetest.mkdir(directory)
local inv = holostorage.server_inventory.cache[diskptr]
local data = minetest.serialize(holostorage.server_inventory.to_table(inv))
minetest.safe_file_write(directory.."/"..filetag, data)
return diskptr
end
function holostorage.server_inventory.save_disks_to_file()
for diskptr in pairs(holostorage.server_inventory.cache) do
holostorage.server_inventory.save_disk_to_file(diskptr)
end
end
-- Save disks on shutdown
minetest.register_on_shutdown(function ()
holostorage.server_inventory.save_disks_to_file()
end)

View File

@ -197,7 +197,6 @@ minetest.register_node("holostorage:export_bus", {
meta:set_string("infotext", "Inventory full") meta:set_string("infotext", "Inventory full")
end end
meta:set_string("infotext", "Exporting to Inventory at "..front_pos) meta:set_string("infotext", "Exporting to Inventory at "..front_pos)
if can_take then if can_take then

View File

@ -53,7 +53,7 @@ function holostorage.stack_list(pos)
local tabl = {} local tabl = {}
for _,diskptr in pairs(invs) do for _,diskptr in pairs(invs) do
local invref = holostorage.disks.memcache[diskptr] local invref = holostorage.server_inventory.cache[diskptr]
local inv_n = "main" local inv_n = "main"
local inv_p local inv_p
if diskptr:find("chest/") then if diskptr:find("chest/") then
@ -86,7 +86,7 @@ function holostorage.insert_stack(pos, stack)
local leftover local leftover
for _,diskptr in pairs(invs) do for _,diskptr in pairs(invs) do
local invref = holostorage.disks.memcache[diskptr] local invref = holostorage.server_inventory.cache[diskptr]
local inv_n = "main" local inv_n = "main"
local inv_p local inv_p
if diskptr:find("chest/") then if diskptr:find("chest/") then
@ -116,7 +116,7 @@ function holostorage.take_stack(pos, stack)
local success = false local success = false
for _,diskptr in pairs(invs) do for _,diskptr in pairs(invs) do
local invref = holostorage.disks.memcache[diskptr] local invref = holostorage.server_inventory.cache[diskptr]
local inv_n = "main" local inv_n = "main"
local inv_p local inv_p
if diskptr:find("chest/") then if diskptr:find("chest/") then

View File

@ -111,7 +111,7 @@ local function register_disk_drive(index)
minetest.get_node_timer(pos):start(0.02) minetest.get_node_timer(pos):start(0.02)
end, end,
on_metadata_inventory_put = function(pos, listname, index, stack, player) on_metadata_inventory_put = function(pos, listname, index, stack, player)
stack = holostorage.disks.ensure_disk_inventory(stack, minetest.pos_to_string(pos)) stack = holostorage.server_inventory.ensure_disk_inventory(stack, minetest.pos_to_string(pos))
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
@ -149,9 +149,9 @@ minetest.register_abm({
local meta = stack:get_meta() local meta = stack:get_meta()
local tag = meta:get_string("storage_tag") local tag = meta:get_string("storage_tag")
if tag and tag ~= "" then if tag and tag ~= "" then
if not holostorage.disks.memcache[tag] then if not holostorage.server_inventory.cache[tag] then
print("loading drive",tag) print("loading drive",tag)
holostorage.disks.load_disk_from_file(stack, tag) holostorage.server_inventory.load_disk_from_file(stack, tag)
end end
end end
end end

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B