diff --git a/extend/lbson/src/bson.h b/extend/lbson/src/bson.h index 8081d36e..4e0ca7bf 100644 --- a/extend/lbson/src/bson.h +++ b/extend/lbson/src/bson.h @@ -5,6 +5,8 @@ using namespace std; using namespace luakit; +#define PHEX(v,c) { char tmp = (char) c; if (tmp >= '0' && tmp <= '9') { v = tmp-'0'; } else { v = tmp - 'a' + 10; } } + //https://bsonspec.org/spec.html namespace lbson { const uint8_t max_bson_depth = 64; @@ -43,18 +45,6 @@ namespace lbson { BSON_MAXKEY = 127, }; - class bson_value { - public: - int64_t val = 0; - string str = ""; - string opt = ""; - uint8_t stype = 0; - bson_type type = bson_type::BSON_EOO; - bson_value(bson_type t, string s, uint8_t st = 0) : str(s), stype(st), type(t) {} - bson_value(bson_type t, int64_t i, uint8_t st = 0) : val(i), stype(st), type(t) {} - bson_value(bson_type t, string s, string o, uint8_t st = 0) : str(s), opt(s), stype(st), type(t) {} - bson_value(bson_type t, const char* p, size_t l, uint8_t st = 0) : str(p, l), stype(st), type(t) {} - }; class mgocodec; class bson { public: @@ -91,22 +81,6 @@ namespace lbson { return lua_gettop(L); } - int pairs(lua_State* L) { - m_buffer.clean(); - size_t data_len = 0; - bson_value* value = lua_to_object(L, -1); - if (value == nullptr) { - char* data = (char*)encode_pairs(L, &data_len); - value = new bson_value(bson_type::BSON_DOCUMENT, data, data_len); - } else { - lua_pop(L, 1); - char* data = (char*)encode_pairs(L, &data_len); - value->str = string(data, data_len); - } - lua_push_object(L, value); - return 1; - } - uint8_t* encode_pairs(lua_State* L, size_t* data_len) { int n = lua_gettop(L); if (n < 2 || n % 2 != 0) { @@ -138,7 +112,69 @@ namespace lbson { return &m_buffer;; } + int date(lua_State* L, int64_t value) { + return make_bson_value(L, bson_type::BSON_DATE, (const char *)&value, sizeof(value)); + } + + int int64(lua_State* L, int64_t value) { + return make_bson_value(L, bson_type::BSON_INT64, (const char *)&value, sizeof(value)); + } + + int objectid(lua_State* L) { + size_t data_len = 0; + const char* value = lua_tolstring(L, 1, &data_len); + if (data_len != 24) return luaL_error(L, "Invalid object id"); + char buffer[16] = { 0 }; + write_objectid(L, buffer, value); + return make_bson_value(L, bson_type::BSON_OBJECTID, buffer, 12); + } + + int pairs(lua_State* L) { + m_buffer.clean(); + size_t data_len = 0; + char* data = (char*)encode_pairs(L, &data_len); + return make_bson_value(L, bson_type::BSON_DOCUMENT, data, data_len); + } + + int binary(lua_State* L) { + size_t data_len = 0; + const char* value = lua_tolstring(L, 1, &data_len); + luaL_Buffer b; + luaL_buffinit(L, &b); + luaL_addchar(&b, 0); + luaL_addchar(&b, (uint8_t)bson_type::BSON_BINARY); + luaL_addchar(&b, 0); + luaL_addlstring(&b, value, data_len); + luaL_pushresult(&b); + return 1; + } + + int regex(lua_State* L) { + luaL_Buffer b; + luaL_buffinit(L, &b); + luaL_addchar(&b, 0); + luaL_addchar(&b, (uint8_t)bson_type::BSON_REGEX); + lua_pushvalue(L,1); + luaL_addvalue(&b); + luaL_addchar(&b, 0); + lua_pushvalue(L,2); + luaL_addvalue(&b); + luaL_addchar(&b, 0); + luaL_pushresult(&b); + return 1; + } + protected: + int make_bson_value(lua_State *L, bson_type type, const char* ptr, size_t len) { + luaL_Buffer b; + luaL_buffinit(L, &b); + luaL_addchar(&b, 0); + luaL_addchar(&b, (uint8_t)type); + luaL_addlstring(&b, ptr, len); + luaL_pushresult(&b); + return 1; + } + size_t bson_index(char* str, size_t i) { if (i < max_bson_index) { memcpy(str, bson_numstrs[i], 4); @@ -147,12 +183,59 @@ namespace lbson { return sprintf(str, "%zd", i); } - void write_binary(bson_value* value) { - m_buffer.write(value->str.size() + 1); - m_buffer.write(value->stype); - m_buffer.write(value->str); + void pack_date(lua_State* L) { + lua_getfield(L, -1, "date"); + m_buffer.write(lua_tointeger(L, -1) * 1000); + lua_pop(L, 1); + } + + void pack_int64(lua_State* L) { + lua_getfield(L, -1, "value"); + m_buffer.write(lua_tointeger(L, -1)); + lua_pop(L, 1); + } + + void pack_string(lua_State* L) { + size_t data_len; + lua_getfield(L, -1, "value"); + const char* data = lua_tolstring(L, -1, &data_len); + m_buffer.push_data((uint8_t*)data, data_len); + lua_pop(L, 1); } + void pack_objectid(lua_State* L) { + size_t data_len; + lua_getfield(L, -1, "objid"); + const char* data = lua_tolstring(L, -1, &data_len); + if (data_len != 24) luaL_error(L, "Invalid object id"); + char buffer[16] = { 0 }; + write_objectid(L, buffer, data); + m_buffer.push_data((uint8_t*)buffer, 12); + lua_pop(L, 1); + } + + void pack_binary(lua_State* L) { + lua_guard g(L); + size_t bin_len; + lua_getfield(L, -1, "binrary"); + const char* bin = lua_tolstring(L, -1, &bin_len); + lua_getfield(L, -2, "subtype"); + m_buffer.write(bin_len); + m_buffer.write(lua_tointeger(L, -1)); + m_buffer.push_data((uint8_t*)bin, bin_len); + } + + void pack_regex(lua_State* L) { + lua_guard g(L); + size_t regex_len; + lua_getfield(L, -1, "pattern"); + const char* pattern = lua_tolstring(L, -1, ®ex_len); + write_cstring(pattern, regex_len); + lua_getfield(L, -2, "option"); + const char* option = lua_tolstring(L, -1, ®ex_len); + write_cstring(option, regex_len); + } + void write_cstring(const char* buf, size_t len) { m_buffer.push_data((uint8_t*)buf, len); m_buffer.write('\0'); @@ -183,6 +266,29 @@ namespace lbson { return *value; } + void read_objectid(lua_State* L, slice* slice) { + char buffer[32] = { 0 }; + static char hextxt[] = "0123456789abcdef"; + const char* text = read_bytes(L, slice, 12); + for (size_t i = 0; i < 12; i++) { + buffer[i * 2] = hextxt[(text[i] >> 4) & 0xf]; + buffer[i * 2 + 1] = hextxt[text[i] & 0xf]; + } + lua_pushlstring(L, buffer, 24); + } + + void write_objectid(lua_State* L, char* buffer, const char* hexoid) { + for (int i = 0; i < 24; i += 2) { + char hi, low; + PHEX(hi, hexoid[i]); + PHEX(low, hexoid[i + 1]); + if (hi > 16 || low > 16) { + luaL_error(L, "Invalid hex text : %s", hexoid); + } + buffer[i / 2] = hi << 4 | low; + } + } + void write_number(lua_State *L, const char* key, size_t len) { if (lua_isinteger(L, -1)) { int64_t v = lua_tointeger(L, -1); @@ -245,35 +351,35 @@ namespace lbson { } } - void pack_bson_value(lua_State* L, bson_value* value){ - switch(value->type) { + void pack_bson_value(lua_State* L, bson_type type){ + switch(type) { case bson_type::BSON_MINKEY: case bson_type::BSON_MAXKEY: case bson_type::BSON_NULL: break; case bson_type::BSON_BINARY: - write_binary(value); - break; - case bson_type::BSON_INT32: - m_buffer.write(value->val); + pack_binary(L); break; case bson_type::BSON_DATE: + pack_date(L); + break; case bson_type::BSON_INT64: case bson_type::BSON_TIMESTAMP: - m_buffer.write(value->val); + pack_int64(L); break; case bson_type::BSON_ARRAY: case bson_type::BSON_JSCODE: case bson_type::BSON_DOCUMENT: + pack_string(L); + break; case bson_type::BSON_OBJECTID: - m_buffer.write(value->str); + pack_objectid(L); break; case bson_type::BSON_REGEX: - write_cstring(value->str.c_str(), value->str.size()); - write_cstring(value->opt.c_str(), value->opt.size()); + pack_regex(L); break; default: - luaL_error(L, "Invalid value type : %d", (int)value->type); + luaL_error(L, "Invalid value type : %d", (int)type); } } @@ -287,11 +393,14 @@ namespace lbson { write_pair(bson_type::BSON_BOOLEAN, key, len, lua_toboolean(L, -1)); break; case LUA_TTABLE:{ - bson_value* value = lua_to_object(L, -1); - if (value){ - write_key(value->type, key, len); - pack_bson_value(L, value); + lua_getfield(L, -1, "__type"); + if (lua_type(L, -1) == LUA_TNUMBER) { + bson_type type = (bson_type)lua_tointeger(L, -1); + write_key(type, key, len); + lua_pop(L, 1); + pack_bson_value(L, type); } else { + lua_pop(L, 1); pack_table(L, key, len, depth + 1); } } @@ -299,8 +408,13 @@ namespace lbson { case LUA_TSTRING: { size_t sz; const char* buf = lua_tolstring(L, -1, &sz); - write_key(bson_type::BSON_STRING, key, len); - write_string(buf, sz); + if (buf[0] == 0 && sz >= 2) { + write_key((bson_type)buf[1], key, len); + if (sz > 2) m_buffer.push_data((uint8_t*)(buf + 2), sz - 2); + } else { + write_key(bson_type::BSON_STRING, key, len); + write_string(buf, sz); + } } break; case LUA_TNIL: @@ -414,14 +528,14 @@ namespace lbson { lua_pushinteger(L, read_val(L, slice)); break; case bson_type::BSON_DATE: + lua_pushinteger(L, read_val(L, slice) / 1000); + break; case bson_type::BSON_INT64: case bson_type::BSON_TIMESTAMP: lua_pushinteger(L, read_val(L, slice)); break; - case bson_type::BSON_OBJECTID:{ - const char* s = read_bytes(L, slice, 12); - lua_pushlstring(L, s, 12); - } + case bson_type::BSON_OBJECTID: + read_objectid(L, slice); break; case bson_type::BSON_JSCODE: case bson_type::BSON_STRING:{ @@ -430,14 +544,25 @@ namespace lbson { } break; case bson_type::BSON_BINARY: { - uint32_t sz = read_val(L, slice); - uint8_t subtype = read_val(L, slice); + lua_createtable(L, 0, 4); + lua_pushinteger(L, (uint32_t)bt); + lua_setfield(L, -2, "__type"); + lua_pushinteger(L, read_val(L, slice)); + lua_setfield(L, -2, "subtype"); const char* s = read_bytes(L, slice, sz); lua_pushlstring(L, s, sz); + lua_setfield(L, -2, "binray"); } break; - case bson_type::BSON_REGEX: - lua_push_object(L, new bson_value(bt, read_cstring(slice, klen), read_cstring(slice, klen))); + case bson_type::BSON_REGEX: { + lua_createtable(L, 0, 4); + lua_pushinteger(L, (uint32_t)bt); + lua_setfield(L, -2, "__type"); + lua_pushstring(L, read_cstring(slice, klen)); + lua_setfield(L, -2, "pattern"); + lua_pushstring(L, read_cstring(slice, klen)); + lua_setfield(L, -2, "option"); + } break; case bson_type::BSON_DOCUMENT: unpack_dict(L, slice, false); @@ -447,8 +572,11 @@ namespace lbson { break; case bson_type::BSON_MINKEY: case bson_type::BSON_MAXKEY: - case bson_type::BSON_NULL: - lua_push_object(L, new bson_value(bt, 0)); + case bson_type::BSON_NULL: { + lua_createtable(L, 0, 2); + lua_pushinteger(L, (uint32_t)bt); + lua_setfield(L, -2, "__type"); + } break; default: throw lua_exception("invalid bson type: %d", (int)bt); diff --git a/extend/lbson/src/lbson.cpp b/extend/lbson/src/lbson.cpp index 16ac366a..89af3594 100644 --- a/extend/lbson/src/lbson.cpp +++ b/extend/lbson/src/lbson.cpp @@ -15,20 +15,20 @@ namespace lbson { static int pairs(lua_State* L) { return thread_bson.pairs(L); } - static bson_value* doc() { - return new bson_value(bson_type::BSON_DOCUMENT, ""); + static int regex(lua_State* L) { + return thread_bson.regex(L); } - static bson_value* int32(int32_t value) { - return new bson_value(bson_type::BSON_INT64, value); + static int binary(lua_State* L) { + return thread_bson.binary(L); } - static bson_value* int64(int64_t value) { - return new bson_value(bson_type::BSON_INT64, value); + static int objectid(lua_State* L) { + return thread_bson.objectid(L); } - static bson_value* date(int64_t value) { - return new bson_value(bson_type::BSON_DATE, value * 1000); + static int int64(lua_State* L, int64_t value) { + return thread_bson.int64(L, value); } - static bson_value* timestamp(int64_t value) { - return new bson_value(bson_type::BSON_TIMESTAMP, value); + static int date(lua_State* L, int64_t value) { + return thread_bson.date(L, value * 1000); } static void init_static_bson() { @@ -48,21 +48,34 @@ namespace lbson { luakit::lua_table open_lbson(lua_State* L) { luakit::kit_state kit_state(L); auto llbson = kit_state.new_table("bson"); + llbson.set_function("mongocodec", mongo_codec); + llbson.set_function("objectid", objectid); llbson.set_function("encode", encode); llbson.set_function("decode", decode); - llbson.set_function("mongocodec", mongo_codec); - llbson.set_function("timestamp", timestamp); - llbson.set_function("int32", int32); + llbson.set_function("binary", binary); llbson.set_function("int64", int64); llbson.set_function("pairs", pairs); + llbson.set_function("regex", regex); llbson.set_function("date", date); - llbson.set_function("doc", doc); - kit_state.new_class( - "val", &bson_value::val, - "str", &bson_value::str, - "type", &bson_value::type, - "stype", &bson_value::stype - ); + llbson.new_enum("BSON_TYPE", + "BSON_EOO", bson_type::BSON_EOO, + "BSON_REAL", bson_type::BSON_REAL, + "BSON_STRING", bson_type::BSON_STRING, + "BSON_DOCUMENT", bson_type::BSON_DOCUMENT, + "BSON_ARRAY", bson_type::BSON_ARRAY, + "BSON_BINARY", bson_type::BSON_BINARY, + "BSON_OBJECTID", bson_type::BSON_OBJECTID, + "BSON_BOOLEAN", bson_type::BSON_BOOLEAN, + "BSON_DATE", bson_type::BSON_DATE, + "BSON_NULL", bson_type::BSON_NULL, + "BSON_REGEX", bson_type::BSON_REGEX, + "BSON_JSCODE", bson_type::BSON_JSCODE, + "BSON_INT32", bson_type::BSON_INT32, + "BSON_INT64", bson_type::BSON_INT64, + "BSON_INT128", bson_type::BSON_INT128, + "BSON_MINKEY", bson_type::BSON_MINKEY, + "BSON_MAXKEY", bson_type::BSON_MAXKEY + ); return llbson; } } diff --git a/extend/lcodec/lcodec.vcxproj b/extend/lcodec/lcodec.vcxproj index 057950c3..ce3bcfab 100644 --- a/extend/lcodec/lcodec.vcxproj +++ b/extend/lcodec/lcodec.vcxproj @@ -7,7 +7,7 @@ - + diff --git a/extend/lcodec/lcodec.vcxproj.filters b/extend/lcodec/lcodec.vcxproj.filters index bd7a67ab..b7e46004 100644 --- a/extend/lcodec/lcodec.vcxproj.filters +++ b/extend/lcodec/lcodec.vcxproj.filters @@ -1,7 +1,7 @@  - + src diff --git a/extend/lcodec/src/bitarray.h b/extend/lcodec/src/bitarray.h deleted file mode 100644 index 8e076570..00000000 --- a/extend/lcodec/src/bitarray.h +++ /dev/null @@ -1,262 +0,0 @@ -#pragma once - -#include -#include - -namespace lcodec { - typedef unsigned int BWORD; - - /* number of bits in a word */ - #define BITS_PER_BWORD (CHAR_BIT * sizeof(BWORD)) - /* gets the word that contains the bit corresponding to a given index i */ - #define I_BWORD(i) ((BWORD)(i) / BITS_PER_BWORD) - /* computes a mask to access the correct bit inside this word */ - #define I_BIT(i) ((BWORD)1 << ((BWORD)(i) % BITS_PER_BWORD)) - /* computes how many words to store n bits */ - #define BWORDS_FOR_BITS(n) (I_BWORD((n) - 1) + 1) - - class bitarray - { - public: - ~bitarray() { - if (values_) { - free(values_); - values_ = nullptr; - } - size_ = 0; - } - - size_t general(size_t nbits) { - values_ = (BWORD*)calloc(BWORDS_FOR_BITS(nbits), sizeof(BWORD)); - if (values_ != nullptr) - return size_ = nbits; - return 0; - } - - /* set ith bit to 1 if b is truthy, else 0 */ - void set_bit(size_t i, size_t b) { - raw_set_bit(check_index(i), b); - } - - /* get ith bit (1 or 0) */ - size_t get_bit(size_t i) { - return raw_get_bit(check_index(i)); - } - - /* 1 -> 0 and 0 -> 1 */ - void flip_bit(size_t i) { - size_t idx = check_index(i); - if (idx < size_) { - BWORD mask; - BWORD* word = get_bit_access(idx, &mask); - *word = (*word & mask) ? (*word & ~mask) : (*word | mask); - } - } - - void flip() { - size_t nwords = BWORDS_FOR_BITS(size_); - for (size_t i = 0; i < nwords; ++i) { - values_[i] = ~values_[i]; - } - for (size_t i = size_; i < nwords * BITS_PER_BWORD; ++i) { - raw_set_bit(i, 0); - } - } - - void fill(bool b) { - BWORD bb = b ? (BWORD)-1 : 0; - size_t nwords = BWORDS_FOR_BITS(size_); - for (size_t i = 0; i < nwords; ++i) { - values_[i] = bb; - } - for (size_t i = size_; i < nwords * BITS_PER_BWORD; ++i) { - raw_set_bit(i, 0); - } - } - - /* resize the array. if new size is bigger, fill the new bit positions with 0. - also set any unused bits to 0 (ie the gap between size and the actual end - of WORDs). returns the new size, or 0 is returned if failed (array unchanged)*/ - size_t resize(size_t nbits) { - if (nbits == size_) - return nbits; - size_t oldwords = BWORDS_FOR_BITS(size_); - size_t newwords = BWORDS_FOR_BITS(nbits); - if (oldwords != newwords) { - BWORD* tmp = (BWORD* )realloc(values_, newwords * sizeof(BWORD)); - if (tmp == nullptr) - return 0; - values_ = tmp; - } - size_ = nbits; - size_t oldbits = size_; - if (nbits < oldbits) { - for (size_t i = nbits; i < newwords * BITS_PER_BWORD; ++i) - raw_set_bit(i, 0); - } else { - /* gap between oldbits and oldwords*BITS_PER_BWORD is guaranteed to be 0 */ - for (size_t i = oldwords; i < newwords; ++i) - values_[i] = 0; - } - return nbits; - } - - void reverse() { - for (size_t i = 0, j = size_ - 1; i < j; ++i, --j) { - int tmp = raw_get_bit(i); - raw_set_bit(i, raw_get_bit(j)); - raw_set_bit(j, tmp); - } - } - - /* copy values from ba to tg */ - void concat(bitarray* tg) { - resize(size_ + tg->size_); - for (size_t i = 0; i < BWORDS_FOR_BITS(size_); ++i) - values_[size_] = tg->values_[i]; - } - - /* copy values from ba to tg */ - bitarray* clone() { - bitarray* ba = new bitarray(); - if (!ba->general(size_)) { - delete ba; - return nullptr; - } - for (size_t i = 0; i < BWORDS_FOR_BITS(size_); ++i) { - ba->values_[i] = values_[i]; - } - return ba; - } - - bitarray* slice(size_t from, size_t to) { - size_t ifrom = check_index(from); - size_t ito = check_index(to, true); - size_t len = ito - ifrom + 1; - bitarray* ba = new bitarray(); - if (!ba->general(len)) { - delete ba; - return nullptr; - } - for(size_t i = 0; i < len; ++i) { - ba->raw_set_bit(i, raw_get_bit(ifrom + i)); - } - return ba; - } - - void from_string(std::string str, size_t i) { - size_t idx = check_index(i); - size_t slen = str.size(); - resize(i + slen); - for (size_t j = 0; j < slen; ++j) - raw_set_bit(idx + j, str[j] != '0'); - } - - template - void from_number(T src, size_t i) { - size_t idx = check_index(i); - size_t tgt = sizeof(T) * CHAR_BIT; - resize(i + tgt); - for (size_t j = idx, k = 0; k < tgt; ++j, ++k) { - T maskt = (T)1 << (T)(tgt - k - 1); - size_t b = !!(src & maskt); - raw_set_bit(j, b); - } - } - - template - T to_number(size_t i) { - T res = 0; - size_t idx = check_index(i); - size_t tgt = sizeof(T) * CHAR_BIT; - for (size_t j = idx, k = 0; k < tgt; ++j, ++k) { - BWORD mask; - BWORD* word = get_bit_access(j, &mask); - T maskt = (T)1 << (T)(tgt - k - 1); - res = (*word & mask) ? (res | maskt) : (res & ~maskt); - } - return res; - } - - std::string to_string(size_t i) { - std::string str = "bitarray<"; - str.append(std::to_string(size_)); - str.append(">["); - for (size_t i = 0; i < size_; ++i) { - str.append(raw_get_bit(i) ? "1," : "0,"); - } - return str; - } - - bool equal(bitarray *r) { - if (size_ != r->size_) - return false; - for (size_t i = 0; i < BWORDS_FOR_BITS(size_); ++i) - if (values_[i] != r->values_[i]) - return false; - return true; - } - - void lshift(size_t s) { - size_t sz = size_; - for (size_t i = 0; i + s < sz; ++i) - raw_set_bit(i, raw_get_bit(i + s)); - for (size_t i = sz > s ? sz - s : 0; i < sz; ++i) - raw_set_bit(i, 0); - } - - void rshift(size_t s) { - size_t sz = size_; - for (size_t i = 0; i + s < sz; ++i) - raw_set_bit(sz - i - 1, raw_get_bit(sz - i - 1 - s)); - for (size_t i = sz > s ? sz - s : 0; i < sz; ++i) - raw_set_bit(sz - i - 1, 0); - } - - size_t length() { - return size_; - } - - private: - size_t check_index(size_t i, bool tail = false) { - if (tail) { - return (i > 0 && i <= size_) ? i - 1 : size_ - 1; - } - return i > 0 ? i - 1 : 0; - } - - /* set ith bit to 1 if b is truthy, else 0 */ - void raw_set_bit(size_t i, size_t b) { - if (i < size_) { - BWORD mask; - BWORD* word = get_bit_access(i, &mask); - if (b) - *word |= mask; /* set bit */ - else - *word &= ~mask; /* reset bit */ - } - } - - /* get ith bit (1 or 0) */ - size_t raw_get_bit(size_t i) { - if (i < size_) { - BWORD mask; - BWORD* word = get_bit_access(i, &mask); - return (*word & mask) ? 1 : 0; - } - return -1; - } - - /* given an index, returns the word address and the mask to access the bit */ - BWORD* get_bit_access(size_t i, BWORD* mask) { - if (mask != nullptr) - *mask = I_BIT(i); - return &values_[I_BWORD(i)]; - } - - private: - size_t size_; - BWORD* values_; /* uses little endian to store bits */ - }; - -} diff --git a/extend/lcodec/src/bitset.h b/extend/lcodec/src/bitset.h new file mode 100644 index 00000000..3bdaae7b --- /dev/null +++ b/extend/lcodec/src/bitset.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +namespace lcodec { + + template + std::string lua_bitset_new(std::string val) { + std::bitset bit(val); + return bit.to_string(); + } + + template + bool lua_bitset_get(std::string val, size_t pos) { + std::bitset bit(val); + return bit[pos - 1]; + } + + template + std::string lua_bitset_set(std::string val, size_t pos, bool bval) { + std::bitset bit(val); + return bit.set(pos - 1, bval).to_string(); + } + + template + std::string lua_bitset_flip(std::string val, size_t pos) { + std::bitset bit(val); + return bit.flip(pos - 1).to_string(); + } + + template + std::string lua_bitset_reset(std::string val, size_t pos) { + std::bitset bit(val); + if (pos == 0) { + return bit.reset().to_string(); + } + return bit.reset(pos - 1).to_string(); + } + + template + bool lua_bitset_check(std::string val, size_t len) { + if (len > N) return false; + std::bitset bit(val); + for (size_t i = 0; i < len; ++i) { + if (!bit[i]) return false; + } + return true; + } +} diff --git a/extend/lcodec/src/lcodec.cpp b/extend/lcodec/src/lcodec.cpp index 72c2ac60..d488d730 100644 --- a/extend/lcodec/src/lcodec.cpp +++ b/extend/lcodec/src/lcodec.cpp @@ -41,20 +41,10 @@ namespace lcodec { codec->set_buff(&thread_buff); return codec; } - - static bitarray* lbarray(lua_State* L, size_t nbits) { - bitarray* barray = new bitarray(); - if (!barray->general(nbits)) { - delete barray; - return nullptr; - } - return barray; - } luakit::lua_table open_lcodec(lua_State* L) { luakit::kit_state kit_state(L); auto llcodec = kit_state.new_table("codec"); - llcodec.set_function("bitarray", lbarray); llcodec.set_function("guid_new", guid_new); llcodec.set_function("guid_string", guid_string); llcodec.set_function("guid_tostring", guid_tostring); @@ -76,34 +66,37 @@ namespace lcodec { llcodec.set_function("rediscodec", rds_codec); llcodec.set_function("wsscodec", wss_codec); llcodec.set_function("url_encode", url_encode); - llcodec.set_function("url_decode", url_decode); - - kit_state.new_class( - "flip", &bitarray::flip, - "fill", &bitarray::fill, - "equal", &bitarray::equal, - "clone", &bitarray::clone, - "slice", &bitarray::slice, - "concat", &bitarray::concat, - "lshift", &bitarray::lshift, - "rshift", &bitarray::rshift, - "length", &bitarray::length, - "resize", &bitarray::resize, - "reverse", &bitarray::reverse, - "set_bit", &bitarray::set_bit, - "get_bit", &bitarray::get_bit, - "flip_bit", &bitarray::flip_bit, - "to_string", &bitarray::to_string, - "from_string", &bitarray::from_string, - "to_uint8", &bitarray::to_number, - "to_uint16", &bitarray::to_number, - "to_uint32", &bitarray::to_number, - "to_uint64", &bitarray::to_number, - "from_uint8", &bitarray::from_number, - "from_uint16", &bitarray::from_number, - "from_uint32", &bitarray::from_number, - "from_uint64", &bitarray::from_number - ); + llcodec.set_function("url_decode", url_decode); + llcodec.set_function("bit32_new", lua_bitset_new<32>); + llcodec.set_function("bit64_new", lua_bitset_new<64>); + llcodec.set_function("bit128_new", lua_bitset_new<128>); + llcodec.set_function("bit256_new", lua_bitset_new<256>); + llcodec.set_function("bit512_new", lua_bitset_new<512>); + llcodec.set_function("bit32_get", lua_bitset_get<32>); + llcodec.set_function("bit64_get", lua_bitset_get<64>); + llcodec.set_function("bit128_get", lua_bitset_get<128>); + llcodec.set_function("bit256_get", lua_bitset_get<256>); + llcodec.set_function("bit512_get", lua_bitset_get<512>); + llcodec.set_function("bit32_set", lua_bitset_set<32>); + llcodec.set_function("bit64_set", lua_bitset_set<64>); + llcodec.set_function("bit128_set", lua_bitset_set<128>); + llcodec.set_function("bit256_set", lua_bitset_set<256>); + llcodec.set_function("bit512_set", lua_bitset_set<512>); + llcodec.set_function("bit32_flip", lua_bitset_flip<32>); + llcodec.set_function("bit64_flip", lua_bitset_flip<64>); + llcodec.set_function("bit128_flip", lua_bitset_flip<128>); + llcodec.set_function("bit256_flip", lua_bitset_flip<256>); + llcodec.set_function("bit512_flip", lua_bitset_flip<512>); + llcodec.set_function("bit32_reset", lua_bitset_reset<32>); + llcodec.set_function("bit64_reset", lua_bitset_reset<64>); + llcodec.set_function("bit128_reset", lua_bitset_reset<128>); + llcodec.set_function("bit256_reset", lua_bitset_reset<256>); + llcodec.set_function("bit512_reset", lua_bitset_reset<512>); + llcodec.set_function("bit32_check", lua_bitset_check<32>); + llcodec.set_function("bit64_check", lua_bitset_check<64>); + llcodec.set_function("bit128_check", lua_bitset_check<128>); + llcodec.set_function("bit256_check", lua_bitset_check<256>); + llcodec.set_function("bit512_check", lua_bitset_check<512>); return llcodec; } } diff --git a/extend/lcodec/src/lcodec.h b/extend/lcodec/src/lcodec.h index eafa4c3c..aa277d4f 100644 --- a/extend/lcodec/src/lcodec.h +++ b/extend/lcodec/src/lcodec.h @@ -10,4 +10,4 @@ #include "redis.h" #include "mysql.h" #include "websocket.h" -#include "bitarray.h" +#include "bitset.h" diff --git a/extend/lsqlite/src/lsqlite.h b/extend/lsqlite/src/lsqlite.h index 9191f2a2..226dd35f 100644 --- a/extend/lsqlite/src/lsqlite.h +++ b/extend/lsqlite/src/lsqlite.h @@ -151,7 +151,7 @@ namespace lsqlite { ~sqlite_driver() { close(); } void close() { - if (m_sdb) sqlite3_close(m_sdb); + if (m_sdb) sqlite3_close_v2(m_sdb); m_sdb = nullptr; } diff --git a/extend/lssl/src/ssl/lssl.cpp b/extend/lssl/src/ssl/lssl.cpp index 3ea18b0a..5a5fc4ed 100644 --- a/extend/lssl/src/ssl/lssl.cpp +++ b/extend/lssl/src/ssl/lssl.cpp @@ -41,8 +41,7 @@ namespace lssl { return 1; } - static int tohex(lua_State* L, const unsigned char* text, size_t sz) - { + static int tohex(lua_State* L, const unsigned char* text, size_t sz) { static char hex[] = "0123456789abcdef"; char tmp[UCHAR_MAX]; char* buffer = tmp; @@ -64,15 +63,15 @@ namespace lssl { } static int lrandomkey(lua_State* L) { - char tmp[8]; + char tmp[12]; int i; - for (i = 0; i < 8; i++) { + for (i = 0; i < 12; i++) { tmp[i] = rand() & 0xff; } if (luaL_optinteger(L, 1, 0)) { - return tohex(L, (const unsigned char*)tmp, 8); + return tohex(L, (const unsigned char*)tmp, 12); } - lua_pushlstring(L, tmp, 8); + lua_pushlstring(L, tmp, 12); return 1; } @@ -93,7 +92,7 @@ namespace lssl { HEX(hi, text[i]); HEX(low, text[i + 1]); if (hi > 16 || low > 16) { - return luaL_error(L, "Invalid hex text", text); + return luaL_error(L, "Invalid hex text: %s", text); } buffer[i / 2] = hi << 4 | low; } diff --git a/extend/luapb/src/luapb.cpp b/extend/luapb/src/luapb.cpp index 9cf68aa4..bdf069bc 100644 --- a/extend/luapb/src/luapb.cpp +++ b/extend/luapb/src/luapb.cpp @@ -9,11 +9,10 @@ using namespace luakit; namespace luapb { - thread_local luabuf thread_buff; - thread_local std::map pb_proto_ids; - thread_local std::map pb_decode_ids; - thread_local std::map pb_encode_ids; + thread_local luabuf thread_buff; + thread_local std::map pb_cmd_ids; thread_local std::map pb_cmd_indexs; + thread_local std::map pb_cmd_names; #pragma pack(1) struct pb_header { @@ -102,37 +101,27 @@ namespace luapb { protected: const pb_Type* pb_type_from_enum(lua_State* L, lpb_State* LS, size_t cmd_id) { - auto itd = pb_decode_ids.find(cmd_id); - if (itd != pb_decode_ids.end()) - return lpb_type(L, LS, pb_lslice(itd->second.c_str(), itd->second.size())); - auto itp = pb_proto_ids.find(cmd_id); - if (itp == pb_proto_ids.end()) throw lua_exception("pb decode invalid cmdid: %d!", cmd_id); - return lpb_type(L, LS, pb_lslice(itp->second.c_str(), itp->second.size())); + auto it = pb_cmd_ids.find(cmd_id); + if (it == pb_cmd_ids.end()) throw lua_exception("pb decode invalid cmdid: %d!", cmd_id); + return lpb_type(L, LS, pb_lslice(it->second.c_str(), it->second.size())); } const pb_Type* pb_type_from_stack(lua_State* L, lpb_State* LS, pb_header* header, int index) { - uint16_t cmd_id = 0; - switch (lua_type(L, index)) { - case LUA_TNUMBER: - cmd_id = lua_tointeger(L, index); - break; - case LUA_TSTRING: { - const char* pb_nane = lua_tostring(L, index); - auto it = pb_cmd_indexs.find(pb_nane); - if (it == pb_cmd_indexs.end()) luaL_error(L, "invalid pb cmd: %d", pb_nane); - cmd_id = it->second; - } - break; - default: - luaL_error(L, "invalid pb cmd type"); + if (lua_type(L, index) == LUA_TNUMBER) { + header->cmd_id = lua_tointeger(L, index); + auto it = pb_cmd_ids.find(header->cmd_id); + if (it == pb_cmd_ids.end()) luaL_error(L, "invalid pb cmd: %d", header->cmd_id); + return lpb_type(L, LS, pb_lslice(it->second.c_str(), it->second.size())); } - header->cmd_id = cmd_id; - auto ite = pb_encode_ids.find(cmd_id); - if (ite != pb_encode_ids.end()) - return lpb_type(L, LS, pb_lslice(ite->second.c_str(), ite->second.size())); - auto itp = pb_proto_ids.find(cmd_id); - if (itp == pb_proto_ids.end()) luaL_error(L, "invalid pb cmd: %d", header->cmd_id); - return lpb_type(L, LS, pb_lslice(itp->second.c_str(), itp->second.size())); + if (lua_type(L, index) == LUA_TSTRING) { + std::string cmd_name = lua_tostring(L, index); + auto it = pb_cmd_names.find(cmd_name); + if (it == pb_cmd_names.end()) luaL_error(L, "invalid pb cmd_name: %s", cmd_name.c_str()); + header->cmd_id = pb_cmd_indexs[cmd_name]; + return lpb_type(L, LS, pb_lslice(it->second.c_str(), it->second.size())); + } + luaL_error(L, "invalid pb cmd type"); + return nullptr; } }; @@ -145,20 +134,13 @@ namespace luapb { luakit::lua_table open_luapb(lua_State* L) { luaopen_pb(L); lua_table luapb(L); - luakit::kit_state kit_state(L); + kit_state kit_state(L); kit_state.set("protobuf", luapb); luapb.set_function("pbcodec", pb_codec); - luapb.set_function("bind_proto", [](uint32_t cmd_id, std::string name, std::string fullname) { - pb_cmd_indexs[name] = cmd_id; - pb_proto_ids[cmd_id] = fullname; - }); - luapb.set_function("bind_decode", [](uint32_t cmd_id, std::string name, std::string fullname) { - pb_cmd_indexs[name] = cmd_id; - pb_decode_ids[cmd_id] = fullname; - }); - luapb.set_function("bind_encode", [](uint32_t cmd_id, std::string name, std::string fullname) { + luapb.set_function("bind_cmd", [](uint32_t cmd_id, std::string name, std::string fullname) { pb_cmd_indexs[name] = cmd_id; - pb_encode_ids[cmd_id] = fullname; + pb_cmd_names[name] = fullname; + pb_cmd_ids[cmd_id] = fullname; }); return luapb; } diff --git a/extend/luaxml/luaxml.lmak b/extend/luaxml/luaxml.lmak index f680d638..a977c3d1 100644 --- a/extend/luaxml/luaxml.lmak +++ b/extend/luaxml/luaxml.lmak @@ -7,9 +7,6 @@ TARGET_NAME = "luaxml" ----工程类型: static/dynamic/exe PROJECT_TYPE = "dynamic" ---目标文件前缀 -LIB_PREFIX = 1 - --需要的include目录 INCLUDES = { "../../extend/lua/lua", diff --git a/extend/luaxml/luaxml.mak b/extend/luaxml/luaxml.mak index a8fde7c9..e51a23cd 100644 --- a/extend/luaxml/luaxml.mak +++ b/extend/luaxml/luaxml.mak @@ -70,7 +70,7 @@ endif INT_DIR = $(SOLUTION_DIR)temp/$(PROJECT_NAME) #目标文件前缀,定义则.so和.a加lib前缀,否则不加 -PROJECT_PREFIX = lib +PROJECT_PREFIX = #目标定义 MYCFLAGS += -fPIC diff --git a/extend/lworker/src/worker.h b/extend/lworker/src/worker.h index ab3db82b..e9842e0f 100644 --- a/extend/lworker/src/worker.h +++ b/extend/lworker/src/worker.h @@ -56,7 +56,9 @@ namespace lworker { { public: worker(ischeduler* schedulor, vstring name, vstring entry, vstring service, vstring sandbox) - : m_schedulor(schedulor), m_name(name), m_entry(entry), m_service(service), m_sandbox(sandbox) { } + : m_schedulor(schedulor), m_name(name), m_entry(entry), m_service(service), m_sandbox(sandbox) { + m_codec = m_lua->create_codec(); + } ~worker() { m_running = false; @@ -115,7 +117,6 @@ namespace lworker { } void run(){ - m_codec = m_lua->create_codec(); auto quanta = m_lua->new_table(m_service.c_str()); quanta.set("title", m_name); quanta.set_function("stop", [&]() { m_running = false; }); diff --git a/script/basic/logger.lua b/script/basic/logger.lua index 83bfa5f2..5dd4b14a 100644 --- a/script/basic/logger.lua +++ b/script/basic/logger.lua @@ -5,7 +5,6 @@ local pcall = pcall local pairs = pairs local tunpack = table.unpack local dtraceback = debug.traceback -local qtrack_id = quanta.track_id local lfilter = log.filter local lprint = log.print @@ -51,8 +50,7 @@ function logger.filter(level) end local function logger_output(flag, feature, lvl, lvl_name, fmt, ...) - local trace_id = qtrack_id() - local ok, msg = pcall(lprint, lvl, flag, title, feature, trace_id, fmt, ...) + local ok, msg = pcall(lprint, lvl, flag, title, feature, fmt, ...) if not ok then local wfmt = "[logger][{}] format failed: {}=> {})" lprint(LOG_LEVEL.WARN, 0, title, feature, trace_id, wfmt, lvl_name, msg, dtraceback()) diff --git a/script/constant.lua b/script/constant.lua index ab625577..b2a15a1b 100644 --- a/script/constant.lua +++ b/script/constant.lua @@ -91,10 +91,8 @@ GMType.GLOBAL = 0 -- 全局相关 GMType.PLAYER = 1 -- 玩家相关, ID为玩家的ID GMType.SERVICE = 2 -- 服务相关, 转发所有服务 GMType.SYSTEM = 3 -- 业务相关, ID为队伍ID,房间ID等 -GMType.OFFLINE = 4 -- 玩家相关, ID为玩家的ID,需要处理离线 -GMType.LOCAL = 5 -- 本地事件转发 -GMType.HASHKEY = 6 -- 服务相关, ID按hash分发 - +GMType.LOCAL = 4 -- 本地事件转发 +GMType.HASHKEY = 5 -- 服务相关, ID按hash分发 -- robot类型 local RobotType = enum("RobotType", 0) diff --git a/script/driver/lmdb.lua b/script/driver/lmdb.lua index bfa84487..2d00ef3b 100644 --- a/script/driver/lmdb.lua +++ b/script/driver/lmdb.lua @@ -2,6 +2,8 @@ local log_debug = logger.debug local sformat = string.format +local update_mgr = quanta.get("update_mgr") + local MDB_SUCCESS = lmdb.MDB_CODE.MDB_SUCCESS local MDB_NOTFOUND = lmdb.MDB_CODE.MDB_NOTFOUND @@ -24,6 +26,15 @@ prop:reader("jcodec", nil) function Lmdb:__init() stdfs.mkdir(LMDB_PATH) + update_mgr:attach_quit(self) +end + +function Lmdb:on_quit() + if self.driver then + log_debug("[Lmdb][on_quit]") + self.driver.close() + self.driver = nil + end end function Lmdb:open(name, dbname) diff --git a/script/driver/mongo.lua b/script/driver/mongo.lua index a8bd19be..671f15dd 100644 --- a/script/driver/mongo.lua +++ b/script/driver/mongo.lua @@ -27,6 +27,7 @@ local lb64decode = ssl.b64_decode local lhmac_sha1 = ssl.hmac_sha1 local lxor_byte = ssl.xor_byte local bsonpairs = bson.pairs +local bint64 = bson.int64 local lclock_ms = timer.clock_ms local timer_mgr = quanta.get("timer_mgr") @@ -49,8 +50,6 @@ prop:reader("passwd", nil) --passwd prop:reader("salted_pass", nil) --salted_pass prop:reader("executer", nil) --执行者 prop:reader("timer_id", nil) --timer_id -prop:reader("cursor_id", nil) --cursor_id -prop:reader("sort_doc", nil) --sort_doc prop:reader("connections", {}) --connections prop:reader("alives", {}) --alives prop:reader("req_counter", nil) @@ -60,8 +59,6 @@ function MongoDB:__init(conf) self.name = conf.db self.user = conf.user self.passwd = conf.passwd - self.sort_doc = bson.doc() - self.cursor_id = bson.int64(0) self.codec = bson.mongocodec() self:set_options(conf.opts) self:setup_pool(conf.hosts) @@ -380,14 +377,11 @@ function MongoDB:find_one(co_name, query, projection) return succ end -function MongoDB:format_pairs(args, doc) +function MongoDB:format_pairs(args) if args then if type(next(args)) == "string" then return args end - if doc then - tinsert(args, doc) - end return bsonpairs(tunpack(args)) end end @@ -395,7 +389,7 @@ end -- 参数说明 --sort: {k1=1} / {k1,1,k2,-1,k3,-1} function MongoDB:find(co_name, query, projection, sortor, limit, skip) - local fsortor = self:format_pairs(sortor, self.sort_doc) + local fsortor = self:format_pairs(sortor) local succ, reply = self:runCommand("find", co_name, "filter", query, "projection", projection, "sort", fsortor, "limit", limit, "skip", skip) if not succ then return succ, reply @@ -411,8 +405,8 @@ function MongoDB:find(co_name, query, projection, sortor, limit, skip) if limit and #results >= limit then break end - self.cursor_id.val = cursor.id - local msucc, moreply = self:runCommand("getMore", self.cursor_id, "collection", co_name, "batchSize", limit) + local new_cur_id = bint64(cursor.id) + local msucc, moreply = self:runCommand("getMore", new_cur_id, "collection", co_name, "batchSize", limit) if not msucc then return msucc, moreply end diff --git a/script/driver/sqlite.lua b/script/driver/sqlite.lua index a7437d57..5aa30130 100644 --- a/script/driver/sqlite.lua +++ b/script/driver/sqlite.lua @@ -3,6 +3,8 @@ local log_err = logger.err local log_debug = logger.debug local sformat = string.format +local update_mgr = quanta.get("update_mgr") + local SQLITE_OK = sqlite.SQLITE_CODE.SQLITE_OK local SQLITE_DONE = sqlite.SQLITE_CODE.SQLITE_DONE local SQLITE_NFOUND = sqlite.SQLITE_CODE.SQLITE_NOTFOUND @@ -19,6 +21,21 @@ prop:reader("prepares", {}) function Sqlite:__init() stdfs.mkdir(SQDB_PATH) + update_mgr:attach_quit(self) +end + +function Sqlite:on_quit() + if self.driver then + log_debug("[Sqlite][on_quit]") + for _, stmts in pairs(self.prepares) do + for _, stmt in pairs(stmts) do + stmt.close() + end + end + self.prepares = {} + self.driver.close() + self.driver = nil + end end function Sqlite:open(dbname) diff --git a/script/driver/unqlite.lua b/script/driver/unqlite.lua index 77f37cc2..4e5169c2 100644 --- a/script/driver/unqlite.lua +++ b/script/driver/unqlite.lua @@ -2,6 +2,8 @@ local log_debug = logger.debug local sformat = string.format +local update_mgr = quanta.get("update_mgr") + local UNQLITE_OK = unqlite.UNQLITE_CODE.UNQLITE_OK local UNQLITE_NOTFOUND = unqlite.UNQLITE_CODE.UNQLITE_NOTFOUND @@ -17,6 +19,15 @@ prop:reader("jcodec", nil) function Unqlite:__init() stdfs.mkdir(UNQLITE_PATH) + update_mgr:attach_quit(self) +end + +function Unqlite:on_quit() + if self.driver then + log_debug("[Unqlite][on_quit]") + self.driver.close() + self.driver = nil + end end function Unqlite:open(name) diff --git a/script/kernel/protobuf_mgr.lua b/script/kernel/protobuf_mgr.lua index 5cf4d3da..540571bb 100644 --- a/script/kernel/protobuf_mgr.lua +++ b/script/kernel/protobuf_mgr.lua @@ -9,9 +9,7 @@ local env_get = environ.get local pb_enum_id = protobuf.enum local pb_decode = protobuf.decode local pb_encode = protobuf.encode -local bind_proto = protobuf.bind_proto -local bind_decode = protobuf.bind_decode -local bind_encode = protobuf.bind_encode +local pb_bind_cmd = protobuf.bind_cmd local tunpack = table.unpack local supper = string.upper local ssplit = qstring.split @@ -23,7 +21,6 @@ local event_mgr = quanta.get("event_mgr") local ProtobufMgr = singleton() local prop = property(ProtobufMgr) -prop:reader("pb_names", {}) prop:reader("pb_indexs", {}) prop:reader("pb_callbacks", {}) prop:reader("allow_reload", false) @@ -95,7 +92,6 @@ function ProtobufMgr:load_protos() --注册CMDID和PB的映射 for name, basename, typ in protobuf.types() do if typ == "message" then - self.pb_names[basename] = name self:define_command(name, basename) end end @@ -180,28 +176,13 @@ function ProtobufMgr:define_command(full_name, proto_name) self.pb_callbacks[msg_id] = msg_res_id end end - bind_proto(msg_id, msg_name, full_name) + pb_bind_cmd(msg_id, msg_name, full_name) return end log_warn("[ProtobufMgr][define_command] proto_name: [{}] can't find msg enum:[{}] !", proto_name, msg_name) end end -function ProtobufMgr:bind_ntf(msg_name, pb_name) - local msg_id = self:enum("NCmdId", msg_name) - bind_encode(msg_id, msg_name, self.pb_names[pb_name]) -end - -function ProtobufMgr:bind_cmd(doer, msg_name, callback, pb_recv_name, pb_send_name) - local msg_id = self:enum("NCmdId", msg_name) - bind_decode(msg_id, msg_name, self.pb_names[pb_recv_name]) - event_mgr:add_cmd_listener(doer, msg_id, callback) - if pb_send_name then - self.pb_callbacks[msg_id] = msg_id - bind_encode(msg_id, msg_name, self.pb_names[pb_send_name]) - end -end - function ProtobufMgr:register(doer, pb_name, callback) local proto = self.pb_indexs[pb_name] if not proto then diff --git a/script/network/http_server.lua b/script/network/http_server.lua index a5096965..148d4c69 100644 --- a/script/network/http_server.lua +++ b/script/network/http_server.lua @@ -14,6 +14,8 @@ local jsoncodec = json.jsoncodec local httpdcodec = codec.httpdcodec local derive_port = luabus.derive_port +local update_mgr = quanta.get("update_mgr") + local HttpServer = class() local prop = property(HttpServer) prop:reader("ip", nil) --http server地址 @@ -29,6 +31,15 @@ function HttpServer:__init(http_addr) self.hcodec = httpdcodec(self.jcodec) self.handlers = { GET = {}, POST = {}, PUT = {}, DELETE = {} } self:setup(http_addr) + --注册退出 + update_mgr:attach_quit(self) +end + +function HttpServer:on_quit() + if self.listener then + log_debug("[HttpServer][on_quit]") + self.listener:close() + end end function HttpServer:setup(http_addr) diff --git a/script/network/net_server.lua b/script/network/net_server.lua index 09d11eac..18eec3d9 100644 --- a/script/network/net_server.lua +++ b/script/network/net_server.lua @@ -3,6 +3,7 @@ local log_err = logger.err local log_info = logger.info local log_warn = logger.warn +local log_debug = logger.debug local signalquit = signal.quit local qxpcall = quanta.xpcall local derive_port = luabus.derive_port @@ -10,6 +11,7 @@ local derive_port = luabus.derive_port local proto_pb = luabus.eproto_type.pb local event_mgr = quanta.get("event_mgr") +local update_mgr = quanta.get("update_mgr") local thread_mgr = quanta.get("thread_mgr") local socket_mgr = quanta.get("socket_mgr") local protobuf_mgr = quanta.get("protobuf_mgr") @@ -41,6 +43,15 @@ prop:accessor("msgtype", 0) --消息类型 function NetServer:__init(session_type) self.session_type = session_type self.codec = protobuf.pbcodec() + --注册退出 + update_mgr:attach_quit(self) +end + +function NetServer:on_quit() + if self.listener then + log_debug("[NetServer][on_quit]") + self.listener:close() + end end --induce:根据 order 推导port diff --git a/script/network/rpc_server.lua b/script/network/rpc_server.lua index be7ebe69..b53b2880 100644 --- a/script/network/rpc_server.lua +++ b/script/network/rpc_server.lua @@ -6,6 +6,7 @@ local signalquit = signal.quit local log_err = logger.err local log_warn = logger.warn local log_info = logger.info +local log_debug = logger.debug local qxpcall = quanta.xpcall local new_span = quanta.new_span local inject_span = quanta.inject_span @@ -13,6 +14,7 @@ local hash_code = codec.hash_code local derive_port = luabus.derive_port local event_mgr = quanta.get("event_mgr") +local update_mgr = quanta.get("update_mgr") local thread_mgr = quanta.get("thread_mgr") local socket_mgr = quanta.get("socket_mgr") @@ -54,8 +56,18 @@ function RpcServer:__init(holder, ip, port, induce) self.listener = listener self.ip, self.port = ip, real_port log_info("[RpcServer][setup] now listen {}:{} success!", ip, real_port) + --监听rpc event_mgr:add_listener(self, "rpc_heartbeat") event_mgr:add_listener(self, "rpc_register") + --注册退出 + update_mgr:attach_quit(self) +end + +function RpcServer:on_quit() + if self.listener then + log_debug("[RpcServer][on_quit]") + self.listener:close() + end end --rpc事件 diff --git a/server/center/center_gm.lua b/server/center/center_gm.lua index 5501cb08..3408a5b2 100644 --- a/server/center/center_gm.lua +++ b/server/center/center_gm.lua @@ -126,14 +126,16 @@ function CenterGM:show_snapshot(service_name, index) local ok, codeoe, res = router_mgr:call_router_id(quanta_id, "rpc_show_snapshot") if not ok then log_err("[CenterGM][show_snapshot] exec service={}-{} failed! codeoe={},res={}", service_name, index, codeoe, res) + return codeoe end - return codeoe, res + return res end local ok, codeoe, res = router_mgr:call_target(quanta_id, "rpc_show_snapshot") if not ok then log_err("[CenterGM][show_snapshot] exec service={}-{} failed! codeoe={},res={}", service_name, index, codeoe, res) + return codeoe end - return codeoe, res + return res end -- export diff --git a/server/center/gm_mgr.lua b/server/center/gm_mgr.lua index 1cf59d5e..8679fb9e 100644 --- a/server/center/gm_mgr.lua +++ b/server/center/gm_mgr.lua @@ -8,13 +8,11 @@ local log_err = logger.err local log_debug = logger.debug local sformat = string.format local tunpack = table.unpack -local tinsert = table.insert local make_sid = service.make_sid local guid_index = codec.guid_index local online = quanta.get("online") local cmdline = quanta.get("cmdline") -local monitor = quanta.get("monitor") local event_mgr = quanta.get("event_mgr") local update_mgr = quanta.get("update_mgr") local router_mgr = quanta.get("router_mgr") @@ -22,18 +20,15 @@ local router_mgr = quanta.get("router_mgr") local GLOBAL = quanta.enum("GMType", "GLOBAL") local SYSTEM = quanta.enum("GMType", "SYSTEM") local SERVICE = quanta.enum("GMType", "SERVICE") -local OFFLINE = quanta.enum("GMType", "OFFLINE") local LOCAL = quanta.enum("GMType", "LOCAL") local HASHKEY = quanta.enum("GMType", "HASHKEY") local PLAYER = quanta.enum("GMType", "PLAYER") local SUCCESS = quanta.enum("KernCode", "SUCCESS") -local PLAYER_NOT_EXIST = quanta.enum("KernCode", "PLAYER_NOT_EXIST") local GM_Mgr = singleton() local prop = property(GM_Mgr) prop:reader("http_server", nil) prop:reader("services", {}) -prop:reader("monitors", {}) prop:reader("gm_page", "") prop:reader("gm_status", false) @@ -45,16 +40,12 @@ function GM_Mgr:__init() --创建HTTP服务器 local server = HttpServer(environ.get("QUANTA_GM_HTTP")) - service.modify_host(server:get_port()) self.http_server = server --是否开启GM功能 if environ.status("QUANTA_GM_SERVER") then self.gm_status = true self:register_webgm() end - --关注monitor - monitor:watch_service_ready(self, "monitor") - monitor:watch_service_close(self, "monitor") --定时更新 update_mgr:attach_second5(self) self:on_second5() @@ -80,16 +71,9 @@ function GM_Mgr:on_second5() self.gm_page = import("center/gm_page.lua") end --- 事件请求 -function GM_Mgr:on_register_command(command_list, service_id) - self:rpc_register_command(command_list, service_id) - return SUCCESS -end - function GM_Mgr:register_webgm() self:register_get("/", "on_gm_page", self) self:register_get("/gmlist", "on_gmlist", self) - self:register_get("/monitors", "on_monitors", self) self:register_post("/command", "on_command", self) self:register_post("/message", "on_message", self) end @@ -167,16 +151,6 @@ function GM_Mgr:on_gmlist(url, body, params) return { text = "GM指令", nodes = cmdline:get_displays() } end ---monitor拉取 -function GM_Mgr:on_monitors(url, body, params) - log_debug("[GM_Mgr][on_monitors] body: {}", params) - local nodes = {} - for _, addr in pairs(self.monitors) do - tinsert(nodes, { text = addr, tag = "log" }) - end - return { text = "在线日志", nodes = nodes } -end - --后台GM调用,字符串格式 function GM_Mgr:on_command(url, body) log_debug("[GM_Mgr][on_command] body: {}", body) @@ -193,12 +167,11 @@ end --参数分发预处理 function GM_Mgr:dispatch_pre_command(fmtargs) local result = event_mgr:notify_listener("on_center_command", fmtargs.name, fmtargs.args) - local _, status_ok, args = tunpack(result) + local status_ok, args = tunpack(result) --无额外处理 if not status_ok then return self:dispatch_command(fmtargs.args, fmtargs.type, fmtargs.service) end - return self:dispatch_command(args, fmtargs.type, fmtargs.service) end @@ -228,7 +201,6 @@ function GM_Mgr:dispatch_command(cmd_args, gm_type, service_id) [SYSTEM] = GM_Mgr.exec_system_cmd, [PLAYER] = GM_Mgr.exec_player_cmd, [SERVICE] = GM_Mgr.exec_service_cmd, - [OFFLINE] = GM_Mgr.exec_offline_cmd, [LOCAL] = GM_Mgr.exec_local_cmd, [HASHKEY] = GM_Mgr.exec_hash_cmd, } @@ -279,32 +251,13 @@ end --local command function GM_Mgr:exec_local_cmd(service_id, cmd_name, ...) - local ok, code, res = tunpack(event_mgr:notify_listener(cmd_name, ...)) + local ok, res = tunpack(event_mgr:notify_listener(cmd_name, ...)) if not ok then - return { code = code, msg = "fail" } + return { code = 1, msg = res } end return { code = 0, msg = res } end ---兼容在线和离线的玩家指令 -function GM_Mgr:exec_offline_cmd(service_id, cmd_name, player_id, ...) - log_debug("[GM_Mgr][exec_offline_cmd] cmd_name:{} player_id:{}", cmd_name, player_id) - local ok, codeoe, res = online:call_lobby(player_id, "rpc_command_execute", cmd_name, player_id, ...) - if not ok then - log_err("[GM_Mgr][exec_offline_cmd] rpc_command_execute failed! cmd_name={} player_id={}", cmd_name, player_id) - return { code = 1, msg = codeoe } - end - if codeoe == PLAYER_NOT_EXIST then - ok, codeoe, res = router_mgr:call_lobby_hash(player_id, "rpc_command_execute", cmd_name, player_id, ...) - if not ok then - log_err("[GM_Mgr][exec_offline_cmd] rpc_command_execute failed! player_id:{}, cmd_name={}", player_id, cmd_name) - return { code = 1, msg = codeoe } - end - return { code = codeoe, msg = res } - end - return { code = codeoe, msg = res } -end - --player command function GM_Mgr:exec_player_cmd(service_id, cmd_name, player_id, ...) if player_id == 0 then @@ -325,4 +278,4 @@ end quanta.gm_mgr = GM_Mgr() -return GM_Mgr \ No newline at end of file +return GM_Mgr diff --git a/server/test.lua b/server/test.lua index 02e8a194..ad7ec64e 100644 --- a/server/test.lua +++ b/server/test.lua @@ -25,12 +25,12 @@ quanta.startup(function()--初始化test import("test/worker_test.lua") import("test/lock_test.lua") import("test/detour_test.lua") - import("test/bitarray_test.lua") + import("test/bitset_test.lua") import("test/lmdb_test.lua") import("test/unqlite_test.lua") import("test/sqlite_test.lua") import("test/ssl_test.lua") import("test/xml_test.lua") ]] - import("test/xml_test.lua") + import("test/bitset_test.lua") end) diff --git a/server/test/bitarray_test.lua b/server/test/bitarray_test.lua deleted file mode 100644 index 8a0311ac..00000000 --- a/server/test/bitarray_test.lua +++ /dev/null @@ -1,30 +0,0 @@ ---bitarray_test.lua - -local log_debug = logger.debug - -local array = codec.bitarray(32) -log_debug("array1: {}", array.to_string()) -array.fill(1) -log_debug("array11: {}", array.to_string()) -array.flip(1) -log_debug("array12: {}", array.to_string()) -array.flip_bit(3) -log_debug("array13: {}-{}", array.to_string(), array.get_bit(3)) -array.from_uint32(65535) -log_debug("array2: {}-{}", array.to_string(), array.to_uint32()) -array.rshift(1) -log_debug("array3: {}-{}", array.to_string(), array.to_uint32()) -array.lshift(1) -log_debug("array4: {}-{}", array.to_string(), array.to_uint32()) -array.set_bit(32, 1) -local a2 = array.clone() -log_debug("array5: {}", a2.to_string()) -local a3 = a2.slice(1, 16) -log_debug("array51: {}", a3.to_string()) -local a4 = a2.slice(17) -log_debug("array52: {}", a4.to_string()) -a4.concat(a3) -log_debug("array6: {}", a4.to_string()) -a4.reverse() -log_debug("array7: {}", a4.to_string()) -log_debug("array8: {}-{}", a4.equal(a2), a3.equal(a2)) diff --git a/server/test/bitset_test.lua b/server/test/bitset_test.lua new file mode 100644 index 00000000..93cda0b5 --- /dev/null +++ b/server/test/bitset_test.lua @@ -0,0 +1,19 @@ +--bitset_test.lua + +local log_debug = logger.debug + +local bval = codec.bit32_new() +log_debug("bit32_new: {}", bval) +local fval = codec.bit32_flip(bval, 3) +log_debug("bit32_flip: {}-{}", bval, fval) +log_debug("bit32_get: {}-{}", codec.bit32_get(fval, 3), codec.bit32_get(fval, 2)) + +local bval2 = codec.bit32_new("010000101") +log_debug("bit32_new: {}", bval2) +local sval = codec.bit32_set(bval2, 4, true) +log_debug("bit32_set: {}-{}", bval2, sval) +local sval2 = codec.bit32_set(sval, 2, true) +log_debug("bit32_set: {}-{}", bval2, sval2) +log_debug("bit32_check 4: {}", codec.bit32_check(sval2, 4)) +log_debug("bit32_check 5: {}", codec.bit32_check(sval2, 5)) + diff --git a/server/test/mongo_test.lua b/server/test/mongo_test.lua index 2ba5b813..9da73028 100644 --- a/server/test/mongo_test.lua +++ b/server/test/mongo_test.lua @@ -1,5 +1,6 @@ -- mongo_test.lua local log_debug = logger.debug +local bdate = bson.date local timer_mgr = quanta.get("timer_mgr") @@ -34,6 +35,13 @@ timer_mgr:once(2000, function() icode, ierr = mongo_mgr:drop_indexes("test_mongo_2", "test_uid") log_debug("db drop_indexes code: {}, err = {}", icode, ierr) + icode, ierr = mongo_mgr:create_indexes("test_mongo_3", {{key={"pid",1,"uid",1},name="test_uid", unique = true}}) + log_debug("db create_indexes code: {}, err = {}", icode, ierr) + icode, ierr = mongo_mgr:create_indexes("test_mongo_3", { { key = { ttl = 1 }, expireAfterSeconds = 0, name = "ttl", unique = false } }) + log_debug("db create_indexes code: {}, err = {}", icode, ierr) + icode, ierr = mongo_mgr:insert(primary_id, "test_mongo_3", {pid = 123457, uid = 3, time = quanta.now, ttl = bdate(quanta.now + 3600*8 + 30)}) + log_debug("db insert code: {}, err = {}", icode, ierr) + --[[ fcode, res = mongo_mgr:find("test_mongo_1", {}, {_id = 0}, {pid = 1}) for _, v in pairs(res) do