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 903FC6F3E5; Sat, 6 Nov 2021 02:59:51 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 903FC6F3E5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1636156791; bh=3NCOUtep609mxrg7dwkQ0cJ6PQVnClyOC42erRHHN88=; 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=i6ErEdc4M6SrsZt7+RYQQu19Pa4OrDJsn+S0weutCMeUn9Wx0dPD2M8mOErD+c+DY Ed+jQFhcaY8wkuGn6OVIJ3y/G/b5xAZROl6UfDbpXHEIyUU2ViJKk2n67e0HDw3a/C oMsu8VkCvs9xjkMNiG9z94GbzEbrqreUn377O96Y= Received: from smtpng3.i.mail.ru (smtpng3.i.mail.ru [94.100.177.149]) (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 EC7BE6F853 for ; Sat, 6 Nov 2021 02:56:49 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org EC7BE6F853 Received: by smtpng3.m.smailru.net with esmtpa (envelope-from ) id 1mj94i-0006s6-Rz; Sat, 06 Nov 2021 02:56:49 +0300 To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org, vdavydov@tarantool.org Date: Sat, 6 Nov 2021 00:56:37 +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: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD9F9D976862A30D4FE632BB689A9E051E5AE7CA2CEDFBAA161182A05F538085040659A807DB7FC459E1B2963D58E294EF81ABD48A4F5C8A03D3DDA79C85BF7D9DB X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7DB6A86BDF2D5A895EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006371895637A5F0B45FF8638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D88FE5CC0F72FB697CB146ED9BA6B14BBF117882F4460429724CE54428C33FAD305F5C1EE8F4F765FC2EE5AD8F952D28FBA471835C12D1D9774AD6D5ED66289B52BA9C0B312567BB23117882F446042972877693876707352033AC447995A7AD18CB629EEF1311BF91D2E47CDBA5A96583BA9C0B312567BB231DD303D21008E29813377AFFFEAFD269A417C69337E82CC2E827F84554CEF50127C277FBC8AE2E8BA83251EDC214901ED5E8D9A59859A8B62CFFCC7B69C47339089D37D7C0E48F6C5571747095F342E88FB05168BE4CE3AF X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A213B5FB47DCBC3458834459D11680B505F04FA6A3376657102D2F14855188ED73 X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C4173B97CBE165B82D912AB7649887A206BC0994F947283B77A9D420A4CFB5DD3E2308976EFCDF984963171F5B0540C20782D2BC4330F81D66D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA75C69C5C0DDE134364410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3468964757141B82E0410C54B3FDA0ECC45A7001CB13E3199C7E1E867C8F083DE0CAD0E4FB11FC07D31D7E09C32AA3244C374CF09BF47F62FDDB1EB293B0FC64668580396430872480FACE5A9C96DEB163 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2bioj75A/c671lqUNLv7qyxyJdA== X-Mailru-Sender: 689FA8AB762F7393C37E3C1AEC41BA5D4A160F40210ABD2ADDB3E315945041D73841015FED1DE5223CC9A89AB576DD93FB559BB5D741EB963CF37A108A312F5C27E8A8C3839CE0E267EA787935ED9F1B X-Mras: Ok Subject: [Tarantool-patches] [PATCH 6/9] 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..4e9cea2eb 100644 --- a/extra/exports +++ b/extra/exports @@ -151,12 +151,11 @@ csv_next csv_setopt decimal_from_string decimal_unpack +error_field_find 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 be3b3b6f5..e0a1894e1 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..f48ea231f 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_field_find(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 40d934c19..c754fc737 100644 --- a/src/lib/core/diag.h +++ b/src/lib/core/diag.h @@ -196,6 +196,9 @@ error_move_payload(struct error *e, struct error_payload *src) error_payload_move(&e->payload, src); } +const struct error_field * +error_field_find(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 a5d1d2a43..c339de7d4 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_field_find(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_field_find(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)