-- 对sharetable 的一层封装 实现热更新 local skynet = require "skynet" local service = require "skynet.service" local sharetable = require "skynet.sharetable" local function sharetable_service() local skynet = require "skynet" local sharetable = require "skynet.sharetable" local files = {} -- filename local csvdata = {} local initfile = { ["src/csvdata/init.lua"] = {}, ["src/csvdata/init_adv.lua"] = {}, } function csvdata.query(source, filename) files[filename] = files[filename] or {} files[filename][source] = 1 end function csvdata.close(source) for filename, info in pairs(files) do info[source] = nil end end function csvdata.realName(file) if string.match(file, "Csv$") then if initfile["src/csvdata/init.lua"] and initfile["src/csvdata/init.lua"][file] then file = initfile["src/csvdata/init.lua"][file] elseif initfile["src/csvdata/init_adv.lua"] and initfile["src/csvdata/init_adv.lua"][file] then file = initfile["src/csvdata/init_adv.lua"][file] end file = "src/" .. file .. ".lua" end return file end function csvdata.hotfix(_, ...) local now = skynet.timex() local filenames = {...} local needHotfix = {} for _, filename in ipairs(filenames) do -- 更新下 skynet.error(string.format("hotfix_csvdata time: %s, file: %s", now, filename)) if initfile[filename] then sharetable.loadfile(filename) sharetable.update(filename) else sharetable.loadfile(csvdata.realName(filename)) end if files[filename] then for source, _ in pairs(files[filename]) do needHotfix[source] = needHotfix[source] or {} table.insert(needHotfix[source], filename) end end end for source, files in pairs(needHotfix) do skynet.send(source, "csvdata", "hotfix", table.unpack(files)) end end skynet.dispatch("lua", function(_,source,cmd,...) skynet.ignoreret() csvdata[cmd](source,...) end) skynet.register_protocol { name = "csvdata", id = 102, pack = skynet.pack, unpack = skynet.unpack, } -- 初始化csvdata skynet.start(function() for file, _ in pairs(initfile) do sharetable.loadfile(file) local init = sharetable.query(file) if not init then error("csvdata load init file error " .. file) return end initfile[file] = init for _, one in pairs(init) do sharetable.loadfile("src/" .. one .. ".lua") end end end) end local cache = {} local csvdata local function load_csvdata(t, key) if key == "address" then t.address = service.new("csvdata", sharetable_service) return t.address else if cache[key] then return cache[key] end local realName = csvdata.realName(key) local tab = sharetable.query(realName) if not tab then error("dont have csvdata : " .. realName) return end cache[key] = tab -- 增加引用 skynet.send(csvdata.address, "lua", "query", key) return tab end end local function close_hotfix(t) local addr = rawget(t, "address") if addr then skynet.send(addr, "lua", "close") end end csvdata = setmetatable ( {} , { __index = load_csvdata, __gc = close_hotfix, }) function csvdata.init() return csvdata.address end function csvdata.hotfix(...) skynet.send(csvdata.address, "lua", "hotfix", ...) end function csvdata.realName(file) if string.match(file, "Csv$") then if csvdata["src/csvdata/init.lua"] and csvdata["src/csvdata/init.lua"][file] then file = csvdata["src/csvdata/init.lua"][file] elseif csvdata["src/csvdata/init_adv.lua"] and csvdata["src/csvdata/init_adv.lua"][file] then file = csvdata["src/csvdata/init_adv.lua"][file] end file = "src/" .. file .. ".lua" end return file end local function update(file) -- 更新一下 if cache[file] then sharetable.update(csvdata.realName(file)) end end skynet.register_protocol { name = "csvdata", id = 102, pack = skynet.pack, unpack = skynet.unpack, dispatch = function(_, _, cmd, ...) skynet.ignoreret() if cmd == "hotfix" then -- skynet.error("csvdara hotfix update", ...) local files = {...} for _, file in ipairs(files) do update(file) end return end end, } return csvdata