🔧 build: 调整库目录
parent
1370b072f7
commit
0702cee580
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@
|
|||||||
|
有用的 独立 基础 lua 库
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
-- tbl_weight = {
|
||||||
|
-- [xx] = { id = xx, weight = xx },
|
||||||
|
-- ...
|
||||||
|
-- }
|
||||||
|
|
||||||
|
-- https://github.com/kinbei/lua-misc/blob/master/weighted_random.lua
|
||||||
|
|
||||||
|
return function(tbl_weight, random_func, id, weight)
|
||||||
|
random_func = random_func or math.random
|
||||||
|
id = id or "id"
|
||||||
|
weight = weight or "weight"
|
||||||
|
|
||||||
|
local t = {}
|
||||||
|
local total_index = #tbl_weight
|
||||||
|
local total_weight = 0
|
||||||
|
|
||||||
|
for _, v in pairs(tbl_weight) do
|
||||||
|
assert(type(v[weight]) == "number")
|
||||||
|
|
||||||
|
total_weight = total_weight + v[weight]
|
||||||
|
table.insert(t, {
|
||||||
|
[id] = v[id],
|
||||||
|
[weight] = v[weight],
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
return function()
|
||||||
|
local rand_index
|
||||||
|
|
||||||
|
while true do
|
||||||
|
rand_index = random_func(1, total_index)
|
||||||
|
if random_func(1, total_weight) < t[rand_index].weight then
|
||||||
|
return t[rand_index][id]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------------------------------
|
||||||
|
-- math.randomseed( os.time() )
|
||||||
|
|
||||||
|
-- local function test_case_1()
|
||||||
|
-- print("test_case_1")
|
||||||
|
|
||||||
|
-- local t = {}
|
||||||
|
-- table.insert(t, { id = 1, weight = 400 } )
|
||||||
|
-- table.insert(t, { id = 2, weight = 30 } )
|
||||||
|
-- table.insert(t, { id = 3, weight = 100 } )
|
||||||
|
-- table.insert(t, { id = 4, weight = 8 } )
|
||||||
|
-- table.insert(t, { id = 5, weight = 30 } )
|
||||||
|
-- table.insert(t, { id = 6, weight = 500 } )
|
||||||
|
-- table.insert(t, { id = 7, weight = 20 } )
|
||||||
|
-- table.insert(t, { id = 8, weight = 200 } )
|
||||||
|
-- table.insert(t, { id = 9, weight = 40 } )
|
||||||
|
-- table.insert(t, { id = 10, weight = 70 } )
|
||||||
|
-- table.insert(t, { id = 11, weight = 300 } )
|
||||||
|
-- table.insert(t, { id = 12, weight = 500 } )
|
||||||
|
-- table.insert(t, { id = 13, weight = 350 } )
|
||||||
|
-- table.insert(t, { id = 14, weight = 20 } )
|
||||||
|
-- table.insert(t, { id = 15, weight = 480 } )
|
||||||
|
-- table.insert(t, { id = 16, weight = 250 } )
|
||||||
|
-- table.insert(t, { id = 17, weight = 500 } )
|
||||||
|
-- table.insert(t, { id = 18, weight = 50 } )
|
||||||
|
-- table.insert(t, { id = 19, weight = 300 } )
|
||||||
|
-- table.insert(t, { id = 20, weight = 500 } )
|
||||||
|
|
||||||
|
-- local f = weighted_random(t)
|
||||||
|
|
||||||
|
-- local result = {}
|
||||||
|
-- for i = 1, 4648 do
|
||||||
|
-- local id = f()
|
||||||
|
-- result[id] = result[id] or 0
|
||||||
|
-- result[id] = result[id] + 1
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local r = {}
|
||||||
|
-- for k, v in pairs(result) do
|
||||||
|
-- table.insert(r, { id = k, times = v })
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- table.sort(r, function(a, b) return a.times > b.times end)
|
||||||
|
-- for _, v in ipairs(r) do
|
||||||
|
-- print(v.id, v.times)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local function test_case_2()
|
||||||
|
-- print("test_case_2")
|
||||||
|
|
||||||
|
-- local t = {}
|
||||||
|
-- t[1] = { weight = 2000, id = 1 }
|
||||||
|
-- t[2] = { weight = 2000, id = 2 }
|
||||||
|
-- t[3] = { weight = 30, id = 3 }
|
||||||
|
-- t[4] = { weight = 40, id = 4 }
|
||||||
|
-- t[5] = { weight = 50, id = 5 }
|
||||||
|
|
||||||
|
-- local f = weighted_random(t)
|
||||||
|
|
||||||
|
-- local result = {}
|
||||||
|
-- for i = 1, 4120 do
|
||||||
|
-- local id = f()
|
||||||
|
-- result[id] = result[id] or 0
|
||||||
|
-- result[id] = result[id] + 1
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local r = {}
|
||||||
|
-- for k, v in pairs(result) do
|
||||||
|
-- table.insert(r, { id = k, times = v })
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- table.sort(r, function(a, b) return a.times > b.times end)
|
||||||
|
-- for _, v in ipairs(r) do
|
||||||
|
-- print(v.id, v.times)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- test_case_1()
|
||||||
|
-- test_case_2()
|
||||||
@ -1,6 +0,0 @@
|
|||||||
local skynet = require "skynet"
|
|
||||||
|
|
||||||
return function(dbconf)
|
|
||||||
local addr = skynet.uniqueservice("dbmgr")
|
|
||||||
return skynet.call(addr, "lua", "init", dbconf)
|
|
||||||
end
|
|
||||||
@ -1,76 +0,0 @@
|
|||||||
local skynet = require "skynet"
|
|
||||||
local log_define = require "zlog.log_define"
|
|
||||||
|
|
||||||
local getinfo = debug.getinfo
|
|
||||||
local LOG_LEVEL = log_define.LOG_LEVEL
|
|
||||||
local DEFAULT_CATEGORY = log_define.DEFAULT_CATEGORY
|
|
||||||
local log_format = log_define.format
|
|
||||||
|
|
||||||
local category_addr = {}
|
|
||||||
|
|
||||||
local function get_service(category)
|
|
||||||
local addr = category_addr[category]
|
|
||||||
if addr then
|
|
||||||
return addr
|
|
||||||
end
|
|
||||||
|
|
||||||
local root_addr = skynet.localname(".logger")
|
|
||||||
if not root_addr then
|
|
||||||
-- no logger config
|
|
||||||
root_addr = skynet.uniqueservice("logger")
|
|
||||||
end
|
|
||||||
|
|
||||||
addr = skynet.call(root_addr, "lua", "get_service", category)
|
|
||||||
category_addr[category] = addr
|
|
||||||
return addr
|
|
||||||
end
|
|
||||||
|
|
||||||
local function sendlog(category, level, ...)
|
|
||||||
local di = getinfo(3, "Sl")
|
|
||||||
local msg = log_format(skynet.self(), level, di, ...)
|
|
||||||
skynet.call(get_service(category), "lua", "log", level, msg)
|
|
||||||
end
|
|
||||||
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
function M.d(...)
|
|
||||||
sendlog(DEFAULT_CATEGORY, LOG_LEVEL.DEBUG, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.d2(category, ...)
|
|
||||||
sendlog(category, LOG_LEVEL.DEBUG, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.i(...)
|
|
||||||
sendlog(DEFAULT_CATEGORY, LOG_LEVEL.INFO, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.i2(category, ...)
|
|
||||||
sendlog(category, LOG_LEVEL.INFO, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.w(...)
|
|
||||||
sendlog(DEFAULT_CATEGORY, LOG_LEVEL.WARN, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.w2(category, ...)
|
|
||||||
sendlog(category, LOG_LEVEL.WARN, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.e(...)
|
|
||||||
sendlog(DEFAULT_CATEGORY, LOG_LEVEL.ERROR, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.e2(category, ...)
|
|
||||||
sendlog(category, LOG_LEVEL.ERROR, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.f(...)
|
|
||||||
sendlog(DEFAULT_CATEGORY, LOG_LEVEL.FATAL, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.f2(category, ...)
|
|
||||||
sendlog(category, LOG_LEVEL.FATAL, ...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
local string_format = string.format
|
|
||||||
local tconcat = table.concat
|
|
||||||
local os_date = os.date
|
|
||||||
local string_sub = string.sub
|
|
||||||
local os_clock = os.clock
|
|
||||||
|
|
||||||
local ESC = string.char(27, 91)
|
|
||||||
local RESET = ESC .. '0m'
|
|
||||||
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
M.LOG_LEVEL = {
|
|
||||||
DEBUG = 1,
|
|
||||||
INFO = 2,
|
|
||||||
WARN = 3,
|
|
||||||
ERROR = 4,
|
|
||||||
FATAL = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
M.LOG_LEVEL_NAME = {
|
|
||||||
[1] = "DEBUG",
|
|
||||||
[2] = "INFO ",
|
|
||||||
[3] = "WARN ",
|
|
||||||
[4] = "ERROR",
|
|
||||||
[5] = "FATAL",
|
|
||||||
}
|
|
||||||
|
|
||||||
M.LOG_COLOR = {
|
|
||||||
[1] = ESC .. '34m',
|
|
||||||
[2] = ESC .. '32m',
|
|
||||||
[3] = ESC .. '33m',
|
|
||||||
[4] = ESC .. '31m',
|
|
||||||
[5] = ESC .. '35m',
|
|
||||||
}
|
|
||||||
|
|
||||||
M.DEFAULT_CATEGORY = "root"
|
|
||||||
|
|
||||||
function M.log_dir(log_root, date)
|
|
||||||
return string_format("%s/%04d-%02d-%02d", log_root or ".", date.year, date.month, date.day)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.log_path(dir, prefix, category, date)
|
|
||||||
return string_format("%s/%s%s_%04d-%02d-%02d.log", dir or ".", prefix or "", category or M.DEFAULT_CATEGORY,
|
|
||||||
date.year, date.month, date.day)
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.format(addr, level, di, ...)
|
|
||||||
local param = {...}
|
|
||||||
local date = os_date("*t")
|
|
||||||
local ms = string_sub(os_clock(), 3, 6)
|
|
||||||
|
|
||||||
local time = string_format("%02d:%02d:%02d.%02d", date.hour, date.min, date.sec, ms)
|
|
||||||
|
|
||||||
local fileline = ""
|
|
||||||
if di then
|
|
||||||
fileline = (" [%s:%d]"):format(di.short_src, di.currentline)
|
|
||||||
end
|
|
||||||
|
|
||||||
for k, v in pairs(param) do
|
|
||||||
param[k] = tostring(v)
|
|
||||||
end
|
|
||||||
|
|
||||||
local msg =
|
|
||||||
string_format("[:%08x][%s][%s] %s%s", addr, M.LOG_LEVEL_NAME[level], time, tconcat(param, " "), fileline)
|
|
||||||
|
|
||||||
return msg
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.color(level, msg)
|
|
||||||
local c = M.LOG_COLOR[level]
|
|
||||||
if not c then
|
|
||||||
return msg
|
|
||||||
end
|
|
||||||
return c .. msg .. RESET
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
local skynet = require "skynet"
|
||||||
|
require "skynet.manager"
|
||||||
|
|
||||||
|
local dbconf
|
||||||
|
|
||||||
|
local CMD = {}
|
||||||
|
|
||||||
|
function CMD.init(cconf)
|
||||||
|
assert(not dbconf, "dbmgr has been initialized.")
|
||||||
|
dbconf = cconf -- init is allowed only once
|
||||||
|
|
||||||
|
local redisconf = dbconf.redis
|
||||||
|
for dbkey, conf in pairs(redisconf) do
|
||||||
|
for index = 1, conf.service_num do
|
||||||
|
local addr = skynet.newservice("redisd", dbkey, index)
|
||||||
|
local ok = skynet.call(addr, "lua", "init", conf)
|
||||||
|
if not ok then
|
||||||
|
assert(false, ("redisd init failed. [dbkey] %s [id] %d"):format(dbkey, index))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local mysqlconf = dbconf.mysql
|
||||||
|
for dbkey, conf in pairs(mysqlconf) do
|
||||||
|
for index = 1, conf.service_num do
|
||||||
|
local addr = skynet.newservice("mysqld", dbkey, index)
|
||||||
|
local ok = skynet.call(addr, "lua", "init", conf)
|
||||||
|
if not ok then
|
||||||
|
assert(false, ("mysqld init failed. [dbkey] %s [id] %d"):format(dbkey, index))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function CMD.mysql_service_num(dbkey)
|
||||||
|
if not dbconf then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local mysqlconf = dbconf.mysql
|
||||||
|
if not mysqlconf then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local conf = mysqlconf[dbkey]
|
||||||
|
if not conf then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return conf.service_num
|
||||||
|
end
|
||||||
|
|
||||||
|
function CMD.redis_service_num(dbkey)
|
||||||
|
if not dbconf then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local redisconf = dbconf.redis
|
||||||
|
if not redisconf then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local conf = redisconf[dbkey]
|
||||||
|
if not conf then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return conf.service_num
|
||||||
|
end
|
||||||
|
|
||||||
|
skynet.start(function()
|
||||||
|
skynet.dispatch("lua", function(_, _, cmd, ...)
|
||||||
|
local f = CMD[cmd]
|
||||||
|
assert(f, cmd)
|
||||||
|
skynet.retpack(f(...))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
skynet.register(".dbmgr")
|
||||||
@ -1,34 +0,0 @@
|
|||||||
local skynet = require "skynet"
|
|
||||||
local st = require "skynet.sharetable"
|
|
||||||
local mc = require "skynet.multicast"
|
|
||||||
|
|
||||||
local channel
|
|
||||||
|
|
||||||
local CMD = {}
|
|
||||||
|
|
||||||
function CMD.query(filename)
|
|
||||||
assert(channel)
|
|
||||||
return st.query(filename)
|
|
||||||
end
|
|
||||||
|
|
||||||
function CMD.loadfiles(filenames)
|
|
||||||
assert(type(filenames) == "table")
|
|
||||||
for _, filename in pairs(filenames) do
|
|
||||||
st.loadfile(filename)
|
|
||||||
end
|
|
||||||
channel:publish(filenames)
|
|
||||||
end
|
|
||||||
|
|
||||||
function CMD.channel()
|
|
||||||
return channel.channel
|
|
||||||
end
|
|
||||||
|
|
||||||
skynet.start(function()
|
|
||||||
channel = mc.new()
|
|
||||||
skynet.dispatch("lua", function(_, _, cmd, ...)
|
|
||||||
local f = CMD[cmd]
|
|
||||||
assert(f, cmd)
|
|
||||||
skynet.retpack(f(...))
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
@ -1,212 +0,0 @@
|
|||||||
local skynet = require "skynet"
|
|
||||||
local log_define = require "zlog.log_define"
|
|
||||||
local queue = require "skynet.queue"
|
|
||||||
require "skynet.manager"
|
|
||||||
|
|
||||||
local LOG_LEVEL = log_define.LOG_LEVEL
|
|
||||||
local DEFAULT_CATEGORY = log_define.DEFAULT_CATEGORY
|
|
||||||
local log_format = log_define.format
|
|
||||||
local color = log_define.color
|
|
||||||
local string_match = string.match
|
|
||||||
|
|
||||||
local skynet_env = require("skynet.env")
|
|
||||||
local nodeid = skynet_env.get("nodeid")
|
|
||||||
|
|
||||||
local zenv = require("zenv.init")
|
|
||||||
local define = zenv.Logger
|
|
||||||
|
|
||||||
local log_root = define.log_root
|
|
||||||
local log_level = define.log_level or LOG_LEVEL.INFO
|
|
||||||
local log_console = define.log_console
|
|
||||||
|
|
||||||
local name = zenv.get_node_conf(nodeid).name
|
|
||||||
local log_prefix = name .. "_"
|
|
||||||
|
|
||||||
local last_day = -1
|
|
||||||
local category = ...
|
|
||||||
local is_master = not category
|
|
||||||
local category_addr = {}
|
|
||||||
local lock = queue()
|
|
||||||
local file
|
|
||||||
|
|
||||||
local function close_file()
|
|
||||||
if not file then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
file:close()
|
|
||||||
file = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local function open_file(date)
|
|
||||||
date = date or os.date("*t")
|
|
||||||
|
|
||||||
local dir = log_define.log_dir(log_root, date)
|
|
||||||
if not os.rename(dir, dir) then
|
|
||||||
os.execute("mkdir -p " .. dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
if file then
|
|
||||||
close_file()
|
|
||||||
end
|
|
||||||
|
|
||||||
local path = log_define.log_path(dir, log_prefix, category, date)
|
|
||||||
local f, e = io.open(path, "a")
|
|
||||||
if not f then
|
|
||||||
print("logger error:", tostring(e))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
file = f
|
|
||||||
last_day = date.day
|
|
||||||
end
|
|
||||||
|
|
||||||
local CMD = {}
|
|
||||||
|
|
||||||
function CMD.console(level, msg)
|
|
||||||
print(color(level, msg))
|
|
||||||
end
|
|
||||||
|
|
||||||
function CMD.log(level, msg)
|
|
||||||
if level < log_level then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
msg = msg or ""
|
|
||||||
local date = os.date("*t")
|
|
||||||
if not file or date.day ~= last_day then
|
|
||||||
open_file(date)
|
|
||||||
end
|
|
||||||
|
|
||||||
file:write(msg .. '\n')
|
|
||||||
file:flush()
|
|
||||||
|
|
||||||
if log_console then
|
|
||||||
if is_master then
|
|
||||||
CMD.console(level, msg)
|
|
||||||
else
|
|
||||||
skynet.call(".logger", "lua", "console", level, msg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function CMD.set_console(is_open)
|
|
||||||
log_console = is_open
|
|
||||||
if is_master then
|
|
||||||
for _, addr in pairs(category_addr) do
|
|
||||||
skynet.call(addr, "lua", "set_console", is_open)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function CMD.set_level(level)
|
|
||||||
log_level = level
|
|
||||||
if is_master then
|
|
||||||
for _, addr in pairs(category_addr) do
|
|
||||||
skynet.call(addr, "lua", "set_level", level)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function CMD.get_service(cate)
|
|
||||||
if not is_master then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local addr
|
|
||||||
lock(function()
|
|
||||||
addr = category_addr[cate]
|
|
||||||
if not addr then
|
|
||||||
addr = skynet.newservice("logger", cate)
|
|
||||||
category_addr[cate] = addr
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
return addr
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_master then
|
|
||||||
skynet.info_func(function()
|
|
||||||
return {
|
|
||||||
log_console = log_console,
|
|
||||||
log_level = log_level,
|
|
||||||
}
|
|
||||||
end)
|
|
||||||
|
|
||||||
skynet.register_protocol {
|
|
||||||
name = "text",
|
|
||||||
id = skynet.PTYPE_TEXT,
|
|
||||||
unpack = skynet.tostring,
|
|
||||||
dispatch = function(_, addr, msg)
|
|
||||||
local level = LOG_LEVEL.INFO
|
|
||||||
if string_match(msg, "maybe in an endless loop") then
|
|
||||||
level = LOG_LEVEL.WARN
|
|
||||||
end
|
|
||||||
if string_match(msg, "stack traceback:") then
|
|
||||||
level = LOG_LEVEL.ERROR
|
|
||||||
end
|
|
||||||
msg = log_format(addr, level, nil, msg)
|
|
||||||
CMD.log(level, msg)
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
local SIGHUP_CMD = {}
|
|
||||||
local function get_first_line(filename)
|
|
||||||
local f = io.open(filename, "r")
|
|
||||||
if not f then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local first_line = f:read("l")
|
|
||||||
f:close()
|
|
||||||
return first_line
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_sighup_cmd(sighup_file)
|
|
||||||
local cmd = get_first_line(sighup_file)
|
|
||||||
if not cmd then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
return SIGHUP_CMD[cmd]
|
|
||||||
end
|
|
||||||
|
|
||||||
local sighup_file = "./.sighup_file"
|
|
||||||
|
|
||||||
-- 捕捉sighup信号(kill -1)
|
|
||||||
skynet.register_protocol {
|
|
||||||
name = "SYSTEM",
|
|
||||||
id = skynet.PTYPE_SYSTEM,
|
|
||||||
unpack = function(...)
|
|
||||||
return ...
|
|
||||||
end,
|
|
||||||
dispatch = function(_, addr)
|
|
||||||
-- https://blog.hanxi.cc/p/75/
|
|
||||||
local cmd = get_sighup_cmd(sighup_file)
|
|
||||||
if cmd then
|
|
||||||
cmd = cmd:match("^%s*(.-)%s*$")
|
|
||||||
local func = SIGHUP_CMD[cmd]
|
|
||||||
if func then
|
|
||||||
func()
|
|
||||||
else
|
|
||||||
skynet.error(
|
|
||||||
string.format("unknow sighup cmd, need set sighup file. sighup_file: '%s'", sighup_file))
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local level = LOG_LEVEL.FATAL
|
|
||||||
local msg = log_format(addr, level, nil, "SIGHUP")
|
|
||||||
CMD.log(level, msg)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
category_addr[DEFAULT_CATEGORY] = skynet.self()
|
|
||||||
skynet.register(".logger")
|
|
||||||
end
|
|
||||||
|
|
||||||
open_file()
|
|
||||||
|
|
||||||
skynet.start(function()
|
|
||||||
skynet.dispatch("lua", function(_, _, cmd, ...)
|
|
||||||
local f = CMD[cmd]
|
|
||||||
assert(f, cmd)
|
|
||||||
return skynet.retpack(f(...))
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
local skynet = require "skynet"
|
||||||
|
local mysql = require "skynet.db.mysql"
|
||||||
|
local util = require "store_util"
|
||||||
|
require "skynet.manager"
|
||||||
|
|
||||||
|
local traceback = debug.traceback
|
||||||
|
|
||||||
|
local dbkey, index = ...
|
||||||
|
local db
|
||||||
|
|
||||||
|
local CMD = {}
|
||||||
|
|
||||||
|
local function success(ret)
|
||||||
|
if not ret or ret.err or ret.badresult then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function CMD.init(conf)
|
||||||
|
db = mysql.connect(conf)
|
||||||
|
db:query("set names utf8mb4")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function CMD.exec_one(sql)
|
||||||
|
local ok, ret = xpcall(db.query, traceback, db, sql)
|
||||||
|
if not ok or not success(ret) then
|
||||||
|
assert(false, ("sql=[%s] ret=[%s]"):format(sql, util.encode(ret)))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function CMD.exec(sqls)
|
||||||
|
for i = 1, #sqls do
|
||||||
|
local sql = sqls[i]
|
||||||
|
CMD.exec_one(sql)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
skynet.start(function()
|
||||||
|
skynet.dispatch("lua", function(_, _, cmd, ...)
|
||||||
|
local f = CMD[cmd]
|
||||||
|
assert(f, cmd)
|
||||||
|
skynet.retpack(f(...))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
skynet.register(util.mysql_sname(dbkey, index))
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
local skynet = require "skynet"
|
||||||
|
local redis = require "skynet.db.redis"
|
||||||
|
local util = require "store_util"
|
||||||
|
require "skynet.manager"
|
||||||
|
|
||||||
|
local traceback = debug.traceback
|
||||||
|
local tunpack = table.unpack
|
||||||
|
local tconcat = table.concat
|
||||||
|
local dbkey, index = ...
|
||||||
|
local db
|
||||||
|
|
||||||
|
local CMD = {}
|
||||||
|
|
||||||
|
function CMD.init(conf)
|
||||||
|
db = redis.connect(conf)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function CMD.exec_one(cmd, ...)
|
||||||
|
local ok, ret = xpcall(db[cmd], traceback, db, ...)
|
||||||
|
if not ok then
|
||||||
|
assert(false, ("cmd=[%s %s] ret=[%s]"):format(cmd, tconcat({...}, " "), ret))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function CMD.exec(cmds)
|
||||||
|
for _, cmd in pairs(cmds) do
|
||||||
|
xpcall(CMD.exec_one, traceback, tunpack(cmd))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
skynet.start(function()
|
||||||
|
skynet.dispatch("lua", function(_, _, cmd, ...)
|
||||||
|
local f = CMD[cmd]
|
||||||
|
assert(f, cmd)
|
||||||
|
skynet.retpack(f(...))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
skynet.register(util.redis_sname(dbkey, index))
|
||||||
@ -1,198 +0,0 @@
|
|||||||
local skynet = require "skynet"
|
|
||||||
local redis = require "skynet.db.redis"
|
|
||||||
local crypt = require "skynet.crypt"
|
|
||||||
|
|
||||||
local math_floor = math.floor
|
|
||||||
local math_ceil = math.ceil
|
|
||||||
local math_random = math.random
|
|
||||||
|
|
||||||
local function hash(script)
|
|
||||||
local key = crypt.sha1(script)
|
|
||||||
return crypt.hexencode(key)
|
|
||||||
end
|
|
||||||
|
|
||||||
local QUORUM
|
|
||||||
|
|
||||||
local SCRIPT = {
|
|
||||||
LOCK = [[
|
|
||||||
local key = KEYS[1]
|
|
||||||
if redis.call("exists", key) == 1 then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
redis.call("set", key, ARGV[1], "PX", ARGV[2])
|
|
||||||
return 1
|
|
||||||
]],
|
|
||||||
UNLOCK = [[
|
|
||||||
local key = KEYS[1]
|
|
||||||
if redis.call("get", key) == ARGV[1] then
|
|
||||||
redis.pcall("del", key)
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
return 0
|
|
||||||
]],
|
|
||||||
EXTEND = [[
|
|
||||||
local key = KEYS[1]
|
|
||||||
if redis.call("get", key) ~= ARGV[1] then
|
|
||||||
return 0
|
|
||||||
end
|
|
||||||
redis.call("set", key, ARGV[1], "PX", ARGV[2])
|
|
||||||
return 1
|
|
||||||
]],
|
|
||||||
}
|
|
||||||
|
|
||||||
local SCRIPT_HASH = {
|
|
||||||
LOCK = hash(SCRIPT.LOCK),
|
|
||||||
UNLOCK = hash(SCRIPT.UNLOCK),
|
|
||||||
EXTEND = hash(SCRIPT.EXTEND),
|
|
||||||
}
|
|
||||||
|
|
||||||
local conf
|
|
||||||
local dbs = {}
|
|
||||||
local sessions = {}
|
|
||||||
|
|
||||||
local function execute_script(db, type, s)
|
|
||||||
local ok, ret = pcall(db["evalsha"], db, SCRIPT_HASH[type], 1, s.lockname, s.uuid, s.timeout)
|
|
||||||
if not ok and ret:find("NOSCRIPT") then
|
|
||||||
ok, ret = pcall(db["eval"], db, SCRIPT[type], 1, s.lockname, s.uuid, s.timeout)
|
|
||||||
end
|
|
||||||
if not ok then
|
|
||||||
skynet.error("redis execute_script err.", ret, s.lockname, s.uuid, s.timeout)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
if ret == 1 then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function execute_script_timeout(db, type, s)
|
|
||||||
local co = coroutine.running()
|
|
||||||
local ok, ret = false, "timeout"
|
|
||||||
|
|
||||||
skynet.fork(function()
|
|
||||||
ok, ret = execute_script(db, type, s)
|
|
||||||
if co then
|
|
||||||
skynet.wakeup(co)
|
|
||||||
co = nil
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
skynet.sleep(conf.request_timeout / 10)
|
|
||||||
if co then
|
|
||||||
co = nil
|
|
||||||
end
|
|
||||||
return ok, ret
|
|
||||||
end
|
|
||||||
|
|
||||||
local function calc_time(s)
|
|
||||||
local now = skynet.now() * 10
|
|
||||||
local drift = math_floor(conf.drift_factor * s.timeout) + 2
|
|
||||||
s.starttime = now
|
|
||||||
s.endtime = now + s.timeout - drift
|
|
||||||
end
|
|
||||||
|
|
||||||
local function make_session(lockname, uuid, timeout)
|
|
||||||
local s = {
|
|
||||||
lockname = lockname,
|
|
||||||
uuid = uuid,
|
|
||||||
timeout = timeout,
|
|
||||||
attempts = 0,
|
|
||||||
starttime = 0,
|
|
||||||
endtime = 0,
|
|
||||||
}
|
|
||||||
calc_time(s)
|
|
||||||
return s
|
|
||||||
end
|
|
||||||
|
|
||||||
local function unlock(s)
|
|
||||||
s.endtime = 0
|
|
||||||
for _, db in pairs(dbs) do
|
|
||||||
execute_script(db, "UNLOCK", s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function attempt(s, is_extend)
|
|
||||||
s.attempts = s.attempts + 1
|
|
||||||
local votes = 0
|
|
||||||
for _, db in pairs(dbs) do
|
|
||||||
local ok
|
|
||||||
if is_extend then
|
|
||||||
ok = execute_script_timeout(db, "EXTEND", s)
|
|
||||||
else
|
|
||||||
ok = execute_script_timeout(db, "LOCK", s)
|
|
||||||
end
|
|
||||||
if ok then
|
|
||||||
votes = votes + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local now = skynet.now() * 10
|
|
||||||
if votes >= QUORUM and s.endtime > now then
|
|
||||||
local ti = s.timeout / 3 - (now - s.starttime)
|
|
||||||
ti = math_floor(ti / 10)
|
|
||||||
if ti < 0 then
|
|
||||||
ti = 0
|
|
||||||
end
|
|
||||||
skynet.timeout(ti, function()
|
|
||||||
if s.endtime == 0 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
s.attempts = 0
|
|
||||||
calc_time(s)
|
|
||||||
attempt(s, true)
|
|
||||||
end)
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
unlock(s)
|
|
||||||
-- retry
|
|
||||||
if conf.retry_count == -1 or s.attempts <= conf.retry_count then
|
|
||||||
local t = conf.retry_delay + math_floor((math_random() * 2 - 1) * conf.retry_jitter)
|
|
||||||
skynet.sleep(math_ceil(t / 10))
|
|
||||||
calc_time(s)
|
|
||||||
return attempt(s)
|
|
||||||
end
|
|
||||||
-- failed
|
|
||||||
sessions[s.uuid] = nil
|
|
||||||
return false, "timeout"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local CMD = {}
|
|
||||||
|
|
||||||
function CMD.lock(lockname, uuid, timeout)
|
|
||||||
timeout = timeout or conf.timeout
|
|
||||||
local s = sessions[uuid]
|
|
||||||
if s then
|
|
||||||
return false, "session exist"
|
|
||||||
end
|
|
||||||
s = make_session(lockname, uuid, timeout)
|
|
||||||
sessions[uuid] = s
|
|
||||||
|
|
||||||
return attempt(s)
|
|
||||||
end
|
|
||||||
|
|
||||||
function CMD.unlock(_, uuid)
|
|
||||||
local s = sessions[uuid]
|
|
||||||
if not s then
|
|
||||||
return false, "session not exist."
|
|
||||||
end
|
|
||||||
sessions[uuid] = nil
|
|
||||||
return unlock(s)
|
|
||||||
end
|
|
||||||
|
|
||||||
skynet.init(function()
|
|
||||||
conf = require "redlock_conf"
|
|
||||||
for _, client in ipairs(conf.servers) do
|
|
||||||
table.insert(dbs, redis.connect(client))
|
|
||||||
end
|
|
||||||
QUORUM = math_floor(#conf.servers / 2) + 1
|
|
||||||
end)
|
|
||||||
|
|
||||||
skynet.start(function()
|
|
||||||
skynet.dispatch("lua", function(_, _, cmd, ...)
|
|
||||||
local f = CMD[cmd]
|
|
||||||
assert(f, cmd)
|
|
||||||
skynet.retpack(f(...))
|
|
||||||
end)
|
|
||||||
end)
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue