From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id E17A86FFBB; Fri, 12 Nov 2021 02:59:10 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org E17A86FFBB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1636675151; bh=g+nYKQMnkGvUgiSr/EZ+9nrT5qaep44SYOLLrNM32tU=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=UA320Ta37w1HGaozi3B0fhnuZSKFxDDdcXCrmdymI6V5854QaGjxK3z7OlkurF7+Y x2mmyqj26kf4OElJqL0KEJ+i1foLBFeTp0EPi15F2gqjGYaN5TFvtR6hDLt5EC2H0F Cr2kQUIqh/NMonyIDSpcJaX9ex1WpR8WNjAXK7qU= Received: from smtpng1.i.mail.ru (smtpng1.i.mail.ru [94.100.181.251]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 7F4887064F for ; Fri, 12 Nov 2021 02:54:43 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 7F4887064F Received: by smtpng1.m.smailru.net with esmtpa (envelope-from ) id 1mlJty-0003tY-N1; Fri, 12 Nov 2021 02:54:43 +0300 To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org Date: Fri, 12 Nov 2021 00:54:28 +0100 Message-Id: X-Mailer: git-send-email 2.24.3 (Apple Git-128) In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-7564579A: B8F34718100C35BD X-77F55803: 4F1203BC0FB41BD9731B3922EC063979C43A6585748E9610BDC1ABCFD86A591900894C459B0CD1B954E682928ADDA5DEC957D8D0D267C9537F76FE7EF67E38FF90F08FC34D31E8A7 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7BF6702EC5472AA0FEA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006371B0187663A04449C8638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D8E46DF078726B17E80CFD7C6688B7F01D117882F4460429724CE54428C33FAD305F5C1EE8F4F765FC2EE5AD8F952D28FBA471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F446042972877693876707352033AC447995A7AD18C26CFBAC0749D213D2E47CDBA5A96583BA9C0B312567BB231DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B6300D3B61E77C8D3B089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A213B5FB47DCBC3458834459D11680B50537BF44C8E1EC058A99FFE44F193BD272 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C4173B97CBE165B82D912AB7649887A206BC0994F947283B77A9D420A4CFB5DD3EADA334042612FFCBE9B4A59BAA07B7DF571EC30B17E05690D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA7536C62C4FBC402878410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34A9A0A0BF1A2CAC6289141BC1E2074234DA89024B18C3FBBC8867E15A68FBFDACBBC6E814391C77041D7E09C32AA3244CF1501A8026B296456DF29454B3DDD54C33C9DC155518937F729B2BEF169E0186 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj4t8MBgWr8bI+pRmsDeWCag== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5DA49E8DDF1EFD025F3D72FA32907167633841015FED1DE5223CC9A89AB576DD93FB559BB5D741EB963CF37A108A312F5C27E8A8C3839CE0E267EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH v2 07/11] error: use error_payload in Lua X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Vladislav Shpilevoy via Tarantool-patches Reply-To: Vladislav Shpilevoy Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" In Lua struct error used RTTI to return members of the error depending on its type. If a field was added to error's payload, it wasn't visible. The patch makes Lua use error_payload instead of RTTI. Now if the payload gets a new field, it becomes automatically visible in Lua without need to introduce a new method for it. Part of #5568 --- extra/exports | 3 +- src/box/error.cc | 24 ++------------ src/lib/core/diag.c | 6 ++++ src/lib/core/diag.h | 3 ++ src/lib/core/exception.cc | 8 +---- src/lua/error.lua | 69 +++++++++------------------------------ src/lua/init.lua | 24 -------------- 7 files changed, 29 insertions(+), 108 deletions(-) diff --git a/extra/exports b/extra/exports index 19e23f5db..4ca513680 100644 --- a/extra/exports +++ b/extra/exports @@ -151,12 +151,11 @@ csv_next csv_setopt decimal_from_string decimal_unpack +error_find_field error_ref error_set_prev error_unpack_unsafe error_unref -exception_get_int -exception_get_string fiber_attr_delete fiber_attr_getstacksize fiber_attr_new diff --git a/src/box/error.cc b/src/box/error.cc index 3b5fa1c95..5097a076d 100644 --- a/src/box/error.cc +++ b/src/box/error.cc @@ -158,13 +158,8 @@ const char *rmean_error_strings[RMEAN_ERROR_LAST] = { "ERROR" }; -static struct method_info clienterror_methods[] = { - make_method(&type_ClientError, "code", &ClientError::errcode), - METHODS_SENTINEL -}; - const struct type_info type_ClientError = - make_type("ClientError", &type_Exception, clienterror_methods); + make_type("ClientError", &type_Exception); ClientError::ClientError(const type_info *type, const char *file, unsigned line, uint32_t errcode) @@ -269,16 +264,8 @@ BuildXlogGapError(const char *file, unsigned line, struct rlist on_access_denied = RLIST_HEAD_INITIALIZER(on_access_denied); -static struct method_info accessdeniederror_methods[] = { - make_method(&type_AccessDeniedError, "access_type", &AccessDeniedError::access_type), - make_method(&type_AccessDeniedError, "object_type", &AccessDeniedError::object_type), - make_method(&type_AccessDeniedError, "object_name", &AccessDeniedError::object_name), - METHODS_SENTINEL -}; - const struct type_info type_AccessDeniedError = - make_type("AccessDeniedError", &type_ClientError, - accessdeniederror_methods); + make_type("AccessDeniedError", &type_ClientError); AccessDeniedError::AccessDeniedError(const char *file, unsigned int line, const char *access_type, @@ -318,13 +305,8 @@ BuildAccessDeniedError(const char *file, unsigned int line, } } -static struct method_info customerror_methods[] = { - make_method(&type_CustomError, "custom_type", &CustomError::custom_type), - METHODS_SENTINEL -}; - const struct type_info type_CustomError = - make_type("CustomError", &type_ClientError, customerror_methods); + make_type("CustomError", &type_ClientError); CustomError::CustomError(const char *file, unsigned int line, const char *custom_type, uint32_t errcode) diff --git a/src/lib/core/diag.c b/src/lib/core/diag.c index b6fa1f5bb..b05f2793f 100644 --- a/src/lib/core/diag.c +++ b/src/lib/core/diag.c @@ -61,6 +61,12 @@ error_unref(struct error *e) } } +const struct error_field * +error_find_field(const struct error *e, const char *name) +{ + return error_payload_find(&e->payload, name); +} + int error_set_prev(struct error *e, struct error *prev) { diff --git a/src/lib/core/diag.h b/src/lib/core/diag.h index 933ba3ae3..be81689ce 100644 --- a/src/lib/core/diag.h +++ b/src/lib/core/diag.h @@ -208,6 +208,9 @@ error_move_payload(struct error *e, struct error_payload *src) error_payload_move(&e->payload, src); } +const struct error_field * +error_find_field(const struct error *e, const char *name); + /** * Unlink error from its effect. For instance: * e1 -> e2 -> e3 -> e4 (e1:set_prev(e2); e2:set_prev(e3) ...) diff --git a/src/lib/core/exception.cc b/src/lib/core/exception.cc index 395baff6f..1895c50b8 100644 --- a/src/lib/core/exception.cc +++ b/src/lib/core/exception.cc @@ -85,13 +85,7 @@ exception_get_int(struct error *e, const struct method_info *method) static OutOfMemory out_of_memory(__FILE__, __LINE__, sizeof(OutOfMemory), "malloc", "exception"); -static const struct method_info exception_methods[] = { - make_method(&type_Exception, "message", &Exception::get_errmsg), - make_method(&type_Exception, "log", &Exception::log), - METHODS_SENTINEL -}; -const struct type_info type_Exception = make_type("Exception", NULL, - exception_methods); +const struct type_info type_Exception = make_type("Exception", NULL); void * Exception::operator new(size_t size) diff --git a/src/lua/error.lua b/src/lua/error.lua index fb48a9b18..cd27be97c 100644 --- a/src/lua/error.lua +++ b/src/lua/error.lua @@ -1,6 +1,10 @@ -- error.lua (internal file) local ffi = require('ffi') +local msgpack = require('msgpack') + +local mp_decode = msgpack.decode_unchecked + ffi.cdef[[ struct type_info; @@ -41,11 +45,6 @@ struct error { struct error *_effect; }; -char * -exception_get_string(struct error *e, const struct method_info *method); -int -exception_get_int(struct error *e, const struct method_info *method); - int error_set_prev(struct error *e, struct error *prev); @@ -57,45 +56,10 @@ error_ref(struct error *e); void error_unref(struct error *e); -]] - -local REFLECTION_CACHE = {} -local function reflection_enumerate(err) - local key = tostring(err._type) - local result = REFLECTION_CACHE[key] - if result ~= nil then - return result - end - result = {} - -- See type_foreach_method() in reflection.h - local t = err._type - while t ~= nil do - local m = t.methods - while m.name ~= nil do - result[ffi.string(m.name)] = m - m = m + 1 - end - t = t.parent - end - REFLECTION_CACHE[key] = result - return result -end - -local function reflection_get(err, method) - if method.nargs ~= 0 then - return nil -- NYI - end - if method.rtype == ffi.C.CTYPE_INT then - return tonumber(ffi.C.exception_get_int(err, method)) - elseif method.rtype == ffi.C.CTYPE_CONST_CHAR_PTR then - local str = ffi.C.exception_get_string(err, method) - if str == nil then - return nil - end - return ffi.string(str) - end -end +const struct error_field * +error_find_field(const struct error *e, const char *name); +]] local function error_base_type(err) return ffi.string(err._type.name) @@ -175,11 +139,11 @@ local function error_unpack(err) for key, getter in pairs(error_fields) do result[key] = getter(err) end - for key, getter in pairs(reflection_enumerate(err)) do - local value = reflection_get(err, getter) - if value ~= nil then - result[key] = value - end + local payload = err._payload + local fields = payload._fields + for i = 0, payload._count - 1 do + local f = fields[i] + result[ffi.string(f._name)] = mp_decode(f._data) end return result end @@ -216,12 +180,9 @@ local function error_index(err, key) if getter ~= nil then return getter(err) end - getter = reflection_enumerate(err)[key] - if getter ~= nil and getter.nargs == 0 then - local val = reflection_get(err, getter) - if val ~= nil then - return val - end + local f = ffi.C.error_find_field(err, key) + if f ~= nil then + return mp_decode(f._data) end return error_methods[key] end diff --git a/src/lua/init.lua b/src/lua/init.lua index 9e3c813c3..f808a5c32 100644 --- a/src/lua/init.lua +++ b/src/lua/init.lua @@ -3,37 +3,13 @@ local ffi = require('ffi') ffi.cdef[[ -struct type_info; struct method_info; -enum ctype { - CTYPE_VOID = 0, - CTYPE_INT, - CTYPE_CONST_CHAR_PTR -}; - struct type_info { const char *name; const struct type_info *parent; const struct method_info *methods; }; - -enum { METHOD_ARG_MAX = 8 }; - -struct method_info { - const struct type_info *owner; - const char *name; - enum ctype rtype; - enum ctype atype[METHOD_ARG_MAX]; - int nargs; - bool isconst; - - union { - /* Add extra space to get proper struct size in C */ - void *_spacer[2]; - }; -}; - double tarantool_uptime(void); typedef int32_t pid_t; -- 2.24.3 (Apple Git-128)