🔧 build: 调整库目录

develop
xiaojin 5 years ago
parent 1370b072f7
commit 0702cee580

File diff suppressed because it is too large Load Diff

@ -5,132 +5,149 @@
struct entity_world;
struct ecs_capi
{
void *(*iter)(struct entity_world *w, int cid, int index);
struct ecs_capi {
void * (*iter)(struct entity_world *w, int cid, int index);
void (*clear_type)(struct entity_world *w, int cid);
void *(*sibling)(struct entity_world *w, int cid, int index, int slibling_id);
void *(*add_sibling)(struct entity_world *w, int cid, int index, int slibling_id, const void *buffer, void *L, int world_index);
int (*sibling_id)(struct entity_world *w, int cid, int index, int slibling_id);
void* (*add_sibling)(struct entity_world *w, int cid, int index, int slibling_id, const void *buffer, void *L, int world_index);
int (*new_entity)(struct entity_world *w, int cid, const void *buffer, void *L, int world_index);
void (*remove)(struct entity_world *w, int cid, int index, void *L, int world_index);
void (*enable_tag)(struct entity_world *w, int cid, int index, int tag_id, void *L, int world_index);
void (*disable_tag)(struct entity_world *w, int cid, int index, int tag_id);
void (*sort_key)(struct entity_world *w, int orderid, int cid, void *L, int world_index);
void *(*iter_lua)(struct entity_world *w, int cid, int index, void *L);
void * (*iter_lua)(struct entity_world *w, int cid, int index, void *L, int world_index);
int (*assign_lua)(struct entity_world *w, int cid, int index, void *L, int world_index);
};
struct ecs_context
{
struct ecs_context {
struct ecs_capi *api;
struct entity_world *world;
void *L; // for memory allocator
void *L; // for memory allocator
int max_id;
int cid[1];
};
static inline void
check_id_(struct ecs_context *ctx, int cid)
{
check_id_(struct ecs_context *ctx, int cid) {
assert(cid >= 0 && cid <= ctx->max_id);
}
static inline void *
entity_iter(struct ecs_context *ctx, int cid, int index)
{
entity_iter(struct ecs_context *ctx, int cid, int index) {
check_id_(ctx, cid);
return ctx->api->iter(ctx->world, ctx->cid[cid], index);
}
static inline void *
entity_ref_object(struct ecs_context *ctx, int cid, int index) {
if (index <= 0)
return NULL;
check_id_(ctx, cid);
return ctx->api->iter_lua(ctx->world, ctx->cid[cid], index - 1, ctx->L, 1);
}
static inline void
entity_clear_type(struct ecs_context *ctx, int cid)
{
entity_clear_type(struct ecs_context *ctx, int cid) {
check_id_(ctx, cid);
ctx->api->clear_type(ctx->world, ctx->cid[cid]);
}
static inline int
entity_sibling_id(struct ecs_context *ctx, int cid, int index, int sibling_id) {
check_id_(ctx, cid);
check_id_(ctx, sibling_id);
return ctx->api->sibling_id(ctx->world, ctx->cid[cid], index, ctx->cid[sibling_id]);
}
static inline void *
entity_sibling(struct ecs_context *ctx, int cid, int index, int slibling_id)
{
entity_sibling(struct ecs_context *ctx, int cid, int index, int sibling_id) {
check_id_(ctx, cid);
check_id_(ctx, slibling_id);
return ctx->api->sibling(ctx->world, ctx->cid[cid], index, ctx->cid[slibling_id]);
check_id_(ctx, sibling_id);
int id = ctx->api->sibling_id(ctx->world, ctx->cid[cid], index, ctx->cid[sibling_id]);
if (id == 0) {
return NULL;
} else {
return ctx->api->iter(ctx->world, ctx->cid[sibling_id], id-1);
}
}
static inline void *
entity_add_sibling(struct ecs_context *ctx, int cid, int index, int slibling_id, const void *buffer)
{
entity_add_sibling(struct ecs_context *ctx, int cid, int index, int sibling_id, const void *buffer) {
check_id_(ctx, cid);
check_id_(ctx, sibling_id);
return ctx->api->add_sibling(ctx->world, ctx->cid[cid], index, ctx->cid[sibling_id], buffer, ctx->L, 1);
}
static inline int
entity_new(struct ecs_context *ctx, int cid, const void *buffer) {
check_id_(ctx, cid);
check_id_(ctx, slibling_id);
return ctx->api->add_sibling(ctx->world, ctx->cid[cid], index, ctx->cid[slibling_id], buffer, ctx->L, 1);
return ctx->api->new_entity(ctx->world, ctx->cid[cid], buffer, ctx->L, 1);
}
static inline void
entity_remove(struct ecs_context *ctx, int cid, int index)
{
entity_remove(struct ecs_context *ctx, int cid, int index) {
check_id_(ctx, cid);
ctx->api->remove(ctx->world, ctx->cid[cid], index, ctx->L, 1);
}
static inline void
entity_enable_tag(struct ecs_context *ctx, int cid, int index, int tag_id)
{
entity_enable_tag(struct ecs_context *ctx, int cid, int index, int tag_id) {
check_id_(ctx, cid);
check_id_(ctx, tag_id);
ctx->api->enable_tag(ctx->world, ctx->cid[cid], index, ctx->cid[tag_id], ctx->L, 1);
}
static inline void
entity_disable_tag(struct ecs_context *ctx, int cid, int index, int tag_id)
{
entity_disable_tag(struct ecs_context *ctx, int cid, int index, int tag_id) {
check_id_(ctx, cid);
check_id_(ctx, tag_id);
ctx->api->disable_tag(ctx->world, ctx->cid[cid], index, ctx->cid[tag_id]);
}
static inline void
entity_sort_key(struct ecs_context *ctx, int orderid, int cid)
{
entity_sort_key(struct ecs_context *ctx, int orderid, int cid) {
check_id_(ctx, orderid);
check_id_(ctx, cid);
ctx->api->sort_key(ctx->world, ctx->cid[orderid], ctx->cid[cid], ctx->L, 1);
}
static inline void *
entity_iter_lua(struct ecs_context *ctx, int cid, int index)
{
static inline int
entity_assign_lua(struct ecs_context *ctx, int cid, int index) {
check_id_(ctx, cid);
return ctx->api->iter_lua(ctx->world, ctx->cid[cid], index, ctx->L);
assert(index > 0);
return ctx->api->assign_lua(ctx->world, ctx->cid[cid], index-1, ctx->L, 1);
}
struct ecs_ref_i
{
struct ecs_capi_ref *api;
};
struct ecs_ref;
struct ecs_capi_ref
{
int (*create)(struct ecs_ref *);
void (*release)(struct ecs_ref *, int id);
void *(*index)(struct ecs_ref *, int id);
};
static inline int
robject_create(struct ecs_ref_i *R)
{
return R->api->create((struct ecs_ref *)R);
entity_new_ref(struct ecs_context *ctx, int cid) {
check_id_(ctx, cid);
int object_id = ctx->cid[cid];
int live_tag = object_id + 1;
int dead_tag = object_id + 2;
int id;
if (ctx->api->iter(ctx->world, dead_tag, 0)) {
// reuse
id = ctx->api->sibling_id(ctx->world, dead_tag, 0, object_id);
assert(id > 0);
--id;
ctx->api->disable_tag(ctx->world, dead_tag, 0, dead_tag);
} else {
id = ctx->api->new_entity(ctx->world, object_id, NULL, ctx->L, 1);
}
ctx->api->enable_tag(ctx->world, object_id, id, live_tag, ctx->L, 1);
return id + 1;
}
static inline void
robject_release(struct ecs_ref_i *R, int id)
{
R->api->release((struct ecs_ref *)R, id);
}
static inline void *
robject_index(struct ecs_ref_i *R, int id)
{
return R->api->index((struct ecs_ref *)R, id);
entity_release_ref(struct ecs_context *ctx, int cid, int id) {
if (id == 0)
return;
check_id_(ctx, cid);
int object_id = ctx->cid[cid];
int live_tag = object_id + 1;
int dead_tag = object_id + 2;
ctx->api->disable_tag(ctx->world, object_id, id-1, live_tag);
ctx->api->enable_tag(ctx->world, object_id, id-1, dead_tag, ctx->L, 1);
}
#endif

@ -1,5 +1,3 @@
-- https://github.com/cloudwu/luaecs
local ecs = require "ecs.core"
local function get_attrib(opt, inout)
@ -16,7 +14,7 @@ local function get_attrib(opt, inout)
end
if inout == "in" then
desc.r = true
elseif inout == "out" then
elseif inout == "out" or inout == "new" then
desc.w = true
elseif inout == "update" then
desc.r = true
@ -35,8 +33,30 @@ local function cache_world(obj, k)
typenames = {},
id = 0,
select = {},
ref = {},
}
local function gen_ref_pat(key)
local typenames = c.typenames
local desc = {}
local tc = typenames[key]
if tc == nil then
error("Unknown type " .. key)
end
local a = {
exist = true,
name = tc.name,
id = tc.id,
type = tc.type,
}
local n = #tc
for i = 1, #tc do
a[i] = tc[i]
end
desc[1] = a
return desc
end
local function gen_select_pat(pat)
local typenames = c.typenames
local desc = {}
@ -49,11 +69,25 @@ local function cache_world(obj, k)
opt, inout = padding:match "^([:?])(%l+)$"
assert(opt, "Invalid pattern")
end
local tc = assert(typenames[key])
local tc = typenames[key]
if tc == nil then
error("Unknown type " .. key)
end
if tc.ref and inout ~= "new" then
local live = typenames[key .. "_live"]
local a = {
exist = true,
name = live.name,
id = live.id,
}
desc[idx] = a
idx = idx + 1
end
local a = get_attrib(opt, inout)
a.name = tc.name
a.id = tc.id
a.type = tc.type
local n = #tc
for i = 1, #tc do
a[i] = tc[i]
end
@ -74,6 +108,17 @@ local function cache_world(obj, k)
__index = cache_select,
})
local function cache_ref(cache, pat)
local pat_desc = gen_ref_pat(pat)
cache[pat] = k:_groupiter(pat_desc)
return cache[pat]
end
setmetatable(c.ref, {
__mode = "kv",
__index = cache_ref,
})
obj[k] = c
return c
end
@ -85,17 +130,23 @@ local typeid = {
int = assert(ecs._TYPEINT),
float = assert(ecs._TYPEFLOAT),
bool = assert(ecs._TYPEBOOL),
int64 = assert(ecs._TYPEINT64),
dword = assert(ecs._TYPEDWORD),
word = assert(ecs._TYPEWORD),
byte = assert(ecs._TYPEBYTE),
double = assert(ecs._TYPEDOUBLE),
userdata = assert(ecs._TYPEUSERDATA),
}
local typesize = {
[typeid.int] = 4,
[typeid.float] = 4,
[typeid.bool] = 1,
}
local typepack = {
[typeid.int] = 'i4',
[typeid.float] = 'f',
[typeid.bool] = 'B',
[typeid.int64] = 8,
[typeid.dword] = 4,
[typeid.word] = 2,
[typeid.byte] = 1,
[typeid.double] = 8,
[typeid.userdata] = 8,
}
local M = ecs._METHODS
@ -103,30 +154,24 @@ local M = ecs._METHODS
do -- newtype
local function parse(s)
-- s is "name:typename"
local name, typename = s:match "([%w_]+):(%l+)"
local tid = assert(typeid[typename])
return {tid, name}
local name, typename = s:match "^([%w_]+):(%w+)$"
local typeid = assert(typeid[typename])
return {typeid, name}
end
local function align(c, field)
local t = field[1]
local size = c.size
if t == typeid.int or t == typeid.float then
local offset = ((size + 3) & ~3)
c.size = offset + 4
field[3] = offset
elseif t == typeid.bool then
c.size = size + 1
field[3] = size
else
error("Invalid type " .. t)
end
local tsize = typesize[t]
local offset = ((c.size + tsize - 1) & ~(tsize - 1))
c.size = offset + tsize
field[3] = offset
return field
end
local function align_struct(c, t)
if t == typeid.int or t == typeid.float then
c.size = ((c.size + 3) & ~3)
if t then
local s = typesize[t] - 1
c.size = ((c.size + s) & ~s)
end
end
@ -152,18 +197,12 @@ do -- newtype
c.islua = true
elseif c.size > 0 then
align_struct(c, typeclass[1][1])
local pack = "!4="
for i = 1, #c do
pack = pack .. typepack[c[i][1]]
end
c.pack = pack
else
-- size == 0, one value
if ttype then
local t = assert(typeid[typeclass.type])
c.type = t
c.size = typesize[t]
c.pack = typepack[t]
c[1] = {t, "v", 0}
else
c.tag = true
@ -171,35 +210,32 @@ do -- newtype
end
typenames[name] = c
self:_newtype(id, c.size)
if typeclass.ref then
c.ref = true
self:register{
name = name .. "_live",
}
self:register{
name = name .. "_dead",
}
end
end
end
local _ref = ecs._ref
function ecs.ref(typeclass)
local c = {
size = 0,
}
for i, v in ipairs(typeclass) do
c[i] = align(c, parse(v))
end
if c.size == 0 and typeclass.type then
if typeclass.type ~= "lua" then
local id = assert(typeid[typeclass.type])
c[1] = align(c, {id, nil, 0})
local function dump(obj)
for e, v in pairs(obj) do
if type(v) == "table" then
for k, v in pairs(v) do
print(e, k, v)
end
else
print(e, v)
end
if c.size > 0 then
align_struct(c, c[1][1])
end
return _ref(c)
end
end
local mapbool = {
[true] = 1,
[false] = 0,
}
function M:new(obj)
-- dump(obj)
local eid = self:_newentity()
local typenames = context[self].typenames
for k, v in pairs(obj) do
@ -207,23 +243,44 @@ function M:new(obj)
if not tc then
error("Invalid key : " .. k)
end
if tc.islua then
self:_addcomponent(eid, tc.id, v)
elseif tc.tag then
assert(tc.size == 0)
self:_addcomponent(eid, tc.id)
elseif tc.type then
self:_addcomponent(eid, tc.id, string.pack(tc.pack, mapbool[v] or v))
else
local tmp = {}
for i, f in ipairs(tc) do
tmp[i] = v[f[2]]
end
self:_addcomponent(eid, tc.id, string.pack(tc.pack, table.unpack(tmp)))
end
local id = self:_addcomponent(eid, tc.id)
self:object(k, id, v)
end
end
local ref_key = setmetatable({}, {
__index = function(cache, key)
local select_key = string.format("%s_dead:out %s_live?out %s:new", key, key, key)
cache[key] = select_key
return select_key
end,
})
function M:ref(name, obj)
local ctx = context[self]
local typenames = ctx.typenames
local tc = assert(typenames[name])
local live = name .. "_live"
local dead = name .. "_dead"
obj = obj or tc.tag
for v in self:select(dead) do
v[dead] = false
v[live] = true
v[name] = obj
return self:sync(ref_key[name], v)
end
local eid = self:_newentity()
local id = self:_addcomponent(eid, tc.id)
self:object(name, id, obj)
self:object(live, self:_addcomponent(eid, typenames[live].id), true)
return id
end
function M:release(name, refid)
local id = assert(context[self].typenames[name].id)
self:_release(id, refid)
end
function M:context(t)
local typenames = context[self].typenames
local id = {}
@ -243,7 +300,7 @@ end
function M:sync(pat, iter)
local p = context[self].select[pat]
self:_sync(p, iter)
return self:_sync(p, iter)
end
function M:clear(name)
@ -276,10 +333,15 @@ function M:sort(sorted, name)
end
do
local _singleton = M._singleton
local _object = M._object
function M:object(name, refid, v)
local pat = context[self].ref[name]
return _object(pat, v, refid)
end
function M:singleton(name, v)
local pat = context[self].select[name]
return _singleton(pat, v)
local pat = context[self].ref[name]
return _object(pat, v)
end
end

@ -1,4 +1,5 @@
-- 嵌套表
local skynet = require "skynet"
local class = class
local select = select
local next = next
@ -31,7 +32,7 @@ local function isKind(obj, strKind)
end
local function exception(e)
-- Log.e(e)
skynet.error(e)
return e
end
@ -57,7 +58,6 @@ end
-- @param ... 多个键值
function NestingTable:add(item, k, ...)
if not item or not k or select("#", k, ...) ~= self.m_deep then
-- Log.w("NestingTable add nil!")
return
end
@ -71,7 +71,6 @@ function NestingTable:add(item, k, ...)
_item:add(item, ...)
else
self.m_items[k] = item
-- Log.d("NestingTable add", k, item)
end
end
@ -80,13 +79,11 @@ end
-- @param ... 多个键值
function NestingTable:remove(k, ...)
if not k or select("#", k, ...) ~= self.m_deep then
-- Log.w("NestingTable remove k nil!")
return
end
local _item = self:get(k)
if not ... then
-- Log.d("NestingTable remove", k, _item)
self.m_items[k] = nil
elseif _item then
_item:remove(...)

@ -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 +1,6 @@
local single_entity = require "single_entity"
local multi_entity = require "multi_entity"
local util = require "store_util"
local single_entity = require "storage.single_entity"
local multi_entity = require "storage.multi_entity"
local util = require "storage.util"
local traceback = debug.traceback
@ -73,12 +73,12 @@ function mt:flush()
entity:collect_dirty(rediscmds, sqls)
end
for addr, cmds in pairs(rediscmds) do
xpcall(util.redis_execute, traceback, addr, cmds)
for addr, elements in pairs(rediscmds) do
xpcall(util.redis_execute, traceback, addr, elements)
end
for addr, sqls in pairs(sqls) do
xpcall(util.mysql_execute, traceback, addr, sqls)
for addr, elements in pairs(sqls) do
xpcall(util.mysql_execute, traceback, addr, elements)
end
end

@ -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,4 +1,4 @@
local util = require "store_util"
local util = require "storage.util"
local strformat = string.format
local tinsert = table.insert

@ -1,4 +1,4 @@
local util = require "store_util"
local util = require "storage.util"
local strformat = string.format
local tinsert = table.insert

@ -1,5 +1,5 @@
local skynet = require "skynet"
local entity_pool = requier "entity_pool"
local entity_pool = require "storage.entity_pool"
local _store = {}
local inited = false
@ -19,7 +19,7 @@ local function open(flush_interval)
pool:flush()
skynet.yield()
end
skynet.sleep(flush_interval*100)
skynet.sleep(flush_interval * 100)
end
end)
end
@ -33,8 +33,10 @@ local function close()
inited = false
end
local store = setmetatable(_store, {__index = function(self, name)
error(("can not find entity pool [%s]"):format(name))
end})
local store = setmetatable(_store, {
__index = function(self, name)
error(("can not find entity pool [%s]"):format(name))
end,
})
return store, add_pool, open, close

@ -10,6 +10,7 @@ local mysqld_service_num = {}
local redisd_service_num = {}
local guid_generator_addrs
local M = {}
function M.config(opts)
@ -51,7 +52,7 @@ function M.balance_mysqld_addr(dbkey, id)
mysqld_service_num[dbkey] = num
end
assert(num)
local sname = M.mysqld_sname(dbkey, (id % num) + 1)
local sname = M.mysqld_sname(dbkey, (id%num)+1)
return skynet.localname(sname)
end
@ -62,7 +63,7 @@ function M.balance_redisd_addr(dbkey, id)
redisd_service_num[dbkey] = num
end
assert(num)
local sname = M.redis_sname(dbkey, (id % num) + 1)
local sname = M.redis_sname(dbkey, (id%num)+1)
return skynet.localname(sname)
end
@ -72,25 +73,21 @@ function M.guid()
end
assert(guid_generator_addrs, ".dbmgr must be init")
local num = #guid_generator_addrs
return skynet.call(guid_generator_addrs[random(1, num)], "lua")
return skynet.call(guid_generator_addrs[random(1,num)], "lua")
end
function M.encode(val)
if not val then
return
end
if not val then return end
local ok, ret = xpcall(json.encode, traceback, val)
if not ok then
assert(false, strformat("encode error. val=[%s] ret=[%s]", tostring(val), tostring(ret)))
assert(false, strformat("encode error. val=[%s] ret=[%s]",tostring(val), tostring(ret)))
return
end
return ret
end
function M.decode(val)
if not val then
return
end
if not val then return end
local ok, ret = xpcall(json.decode, traceback, val)
if not ok then
assert(false, strformat("decode error. val=[%s] ret=[%s]", tostring(val), tostring(ret)))
@ -111,14 +108,12 @@ local escape_map = {
['"'] = '\\"',
}
function M.quote_sql_str(str)
function M.quote_sql_str( str)
return strformat("'%s'", strgsub(str, "[\0\b\n\r\t\26\\\'\"]", escape_map))
end
function M.redis_key_field(conf, id)
if not conf.redisd_addr then
return
end
if not conf.redisd_addr then return end
local key, field
if id then
key = conf.tbl .. ":" .. conf.id

@ -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…
Cancel
Save