From: Vladislav Shpilevoy via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: tarantool-patches@dev.tarantool.org, sergepetrenko@tarantool.org,
vdavydov@tarantool.org
Subject: [Tarantool-patches] [PATCH 6/9] error: use error_payload in Lua
Date: Sat, 6 Nov 2021 00:56:37 +0100 [thread overview]
Message-ID: <f217c0a93bdd0e0a1c4a68d40b8482b1b79174d8.1636156453.git.v.shpilevoy@tarantool.org> (raw)
In-Reply-To: <cover.1636156453.git.v.shpilevoy@tarantool.org>
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
---
| 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(-)
--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)
next prev parent reply other threads:[~2021-11-05 23:59 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-05 23:56 [Tarantool-patches] [PATCH 0/9] ER_READONLY reason Vladislav Shpilevoy via Tarantool-patches
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 1/9] diag: return created error from diag_set() Vladislav Shpilevoy via Tarantool-patches
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 2/9] error: introduce error_payload Vladislav Shpilevoy via Tarantool-patches
2021-11-08 15:14 ` Serge Petrenko via Tarantool-patches
2021-11-11 23:50 ` Vladislav Shpilevoy via Tarantool-patches
2021-11-12 6:29 ` Serge Petrenko via Tarantool-patches
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 3/9] error: move code to struct error from ClientError Vladislav Shpilevoy via Tarantool-patches
2021-11-08 15:15 ` Serge Petrenko via Tarantool-patches
2021-11-11 23:50 ` Vladislav Shpilevoy via Tarantool-patches
2021-11-12 6:31 ` Serge Petrenko via Tarantool-patches
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 4/9] error: use error_payload to store optional members Vladislav Shpilevoy via Tarantool-patches
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 5/9] error: use error_payload in MessagePack codecs Vladislav Shpilevoy via Tarantool-patches
2021-11-05 23:56 ` Vladislav Shpilevoy via Tarantool-patches [this message]
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 7/9] luatest: copy config in cluster:build_server() Vladislav Shpilevoy via Tarantool-patches
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 8/9] luatest: add new helpers for 'server' object Vladislav Shpilevoy via Tarantool-patches
2021-11-08 15:16 ` Serge Petrenko via Tarantool-patches
2021-11-11 23:51 ` Vladislav Shpilevoy via Tarantool-patches
2021-11-05 23:56 ` [Tarantool-patches] [PATCH 9/9] box: enrich ER_READONLY with new details Vladislav Shpilevoy via Tarantool-patches
2021-11-06 19:30 ` Cyrill Gorcunov via Tarantool-patches
2021-11-07 16:45 ` Vladislav Shpilevoy via Tarantool-patches
2021-11-07 20:19 ` Cyrill Gorcunov via Tarantool-patches
2021-11-08 15:18 ` Serge Petrenko via Tarantool-patches
2021-11-11 23:52 ` Vladislav Shpilevoy via Tarantool-patches
2021-11-08 14:25 ` [Tarantool-patches] [PATCH 0/9] ER_READONLY reason Vladimir Davydov via Tarantool-patches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f217c0a93bdd0e0a1c4a68d40b8482b1b79174d8.1636156453.git.v.shpilevoy@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=sergepetrenko@tarantool.org \
--cc=v.shpilevoy@tarantool.org \
--cc=vdavydov@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH 6/9] error: use error_payload in Lua' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox