[Tarantool-patches] [PATCH V5 6/6] error: add error MsgPack encoding
Vladislav Shpilevoy
v.shpilevoy at tarantool.org
Sat Apr 18 23:39:52 MSK 2020
Thanks for the patch!
On 18/04/2020 17:29, Leonid Vasiliev wrote:
> Co-authored-by: Vladislav Shpilevoy<v.shpilevoy at tarantool.org>
>
> Closes #4398
>
> @TarantoolBot document
> Title: msgpack format for MP_ERROR
>
> For sent an error over IProto MP_ERROR(0x03) subtype
> has been added to MsgPack MP_EXT.
> Now, if session setting 'error_marshaling_enabled'
> is true error will be encoded as:
> ```
> +--------+----------+========+
> | MP_EXT | MP_ERROR | MP_MAP |
> +--------+----------+========+
> ```
>
> MP_ERROR: <MP_MAP> {
> MP_ERROR_STACK: <MP_ARRAY> {
> <MP_MAP> {
> MP_ERROR_TYPE: <MP_STR>,
> MP_ERROR_FILE: <MP_STR>,
> MP_ERROR_LINE: <MP_UINT>,
> MP_ERROR_REASON: <MP_STR>,
> MP_ERROR_ERRNO: <MP_STR>,
> MP_ERROR_FIELDS: <MP_MAP> {
> <MP_STR>: ...,
> <MP_STR>: ...,
> ...
> },
> },
> }
> }
>
> MP_ERROR_STACK = 0x00
>
> At the map passes all necessary error details (depending
> from the error type) to create a copy of the error
> on the client side.
> The necessary fields:
> MP_ERROR_TYPE = 0x00 - error type(string).
> MP_ERROR_FILE = 0x01 - file name from trace.
> MP_ERROR_LINE = 0x02 - line of the file from trace.
> MP_ERROR_REASON = 0x03 - error message.
> MP_ERROR_ERRNO = 0x04 - saved errno.
> MP_ERROR_FIELDS = 0x05 - additional fields passes at MAP (MP_ERROR_FIELDS).
> Now additional fields may content:
> - ClientError code
> - Custom type
> - Access Denied object type
> - Access Denied object name
> - Access Denied access type
I rewrote the commit message, force pushed. Also I added
MP_ERROR_CODE to the root map. Because I realized a code is
available for every error via public box_error_code()
function in C.
Also I renamed REASON to MESSAGE. Reason is a legacy name
used only in Lua and only in error constructor. It is
visible as <error_object>.message after error creation.
====================
@TarantoolBot document
Title: Error objects encoding in MessagePack
Until now an error sent over IProto, or serialized into
MessagePack was turned into a string consisting of the error
message. As a result, all other error object attributes were lost,
including type of the object. On client side seeing a string it
was not possible to tell whether the string is a real string, or
it is a serialized error.
To deal with that the error objects encoding is reworked from the
scratch. Now, when session setting `error_marshaling_enabled` is
true, all fibers of that session will encode error objects as a
new MP_EXT type - MP_ERROR (0x03).
```
+--------+----------+========+
| MP_EXT | MP_ERROR | MP_MAP |
+--------+----------+========+
MP_ERROR: <MP_MAP> {
MP_ERROR_STACK: <MP_ARRAY> [
<MP_MAP> {
MP_ERROR_TYPE: <MP_STR>,
MP_ERROR_FILE: <MP_STR>,
MP_ERROR_LINE: <MP_UINT>,
MP_ERROR_MESSAGE: <MP_STR>,
MP_ERROR_ERRNO: <MP_UINT>,
MP_ERROR_CODE: <MP_UINT>,
MP_ERROR_FIELDS: <MP_MAP> {
<MP_STR>: ...,
<MP_STR>: ...,
...
},
...
},
...
]
}
```
On the top level there is a single key: `MP_ERROR_STACK = 0x00`.
More keys can be added in future, and a client should ignore all
unknown keys to keep compatibility with new versions.
Every error in the stack is a map with the following keys:
* `MP_ERROR_TYPE = 0x00` - error type. This is what is visible in
`<error_object>.base_type` field;
* `MP_ERROR_FILE = 0x01` - file name from `<error_object>.trace`;
* `MP_ERROR_LINE = 0x02` - line from `<error_object>.trace`;
* `MP_ERROR_MESSAGE = 0x03` - error message from
`<error_object>.message`;
* `MP_ERROR_ERRNO = 0x04` - errno saved at the moment of the error
creation. Visible in `<error_object>.errno`;
* `MP_ERROR_CODE = 0x05` - error code. Visible in
`<error_object>.code` and in C function `box_error_code()`.
* `MP_ERROR_FIELDS = 0x06` - additional fields depending on error
type. For example, AccessDenied error type stores here fields
`access_type`, `object_type`, `object_name`. Connector's code
should ignore unknown keys met here, and be ready, that for some
existing errors new fields can be added, old can be dropped.
====================
> ---
> src/box/CMakeLists.txt | 1 +
> src/box/lua/init.c | 56 ++++
> src/box/lua/tuple.c | 16 -
> src/box/mp_error.cc | 552 +++++++++++++++++++++++++++++++++++
> src/box/mp_error.h | 60 ++++
> src/lib/core/mp_extension_types.h | 1 +
> src/lua/error.c | 2 -
> src/lua/error.h | 3 +-
> src/lua/msgpack.c | 3 +
> src/lua/utils.c | 8 +-
> test/box-tap/extended_error.test.lua | 136 +++++++++
> 11 files changed, 817 insertions(+), 21 deletions(-)
> create mode 100644 src/box/mp_error.cc
> create mode 100644 src/box/mp_error.h
> create mode 100755 test/box-tap/extended_error.test.lua
>
> diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
> index 6688303..81f6400 100644
> --- a/src/box/CMakeLists.txt
> +++ b/src/box/CMakeLists.txt
> @@ -136,6 +136,7 @@ add_library(box STATIC
> wal.c
> call.c
> merger.c
> + mp_error.cc
I moved it to box_error library.
====================
diff --git a/src/box/CMakeLists.txt b/src/box/CMakeLists.txt
index 81f64001a..c82ceb56c 100644
--- a/src/box/CMakeLists.txt
+++ b/src/box/CMakeLists.txt
@@ -26,7 +26,7 @@ set_property(DIRECTORY PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${lua_sources})
include_directories(${ZSTD_INCLUDE_DIRS})
include_directories(${CMAKE_BINARY_DIR}/src/box/sql)
-add_library(box_error STATIC error.cc errcode.c vclock.c)
+add_library(box_error STATIC error.cc errcode.c vclock.c mp_error.cc)
-target_link_libraries(box_error core stat)
+target_link_libraries(box_error core stat mpstream)
add_library(vclock STATIC vclock.c)
target_link_libraries(vclock core)
add_library(xrow STATIC xrow.c iproto_constants.c)
target_link_libraries(xrow server core small vclock misc box_error
- scramble mpstream ${MSGPUCK_LIBRARIES})
+ scramble ${MSGPUCK_LIBRARIES})
@@ -136,7 +136,6 @@ add_library(box STATIC
wal.c
call.c
merger.c
- mp_error.cc
${lua_sources}
lua/init.c
lua/call.c
====================
I reviewed rest of the code and it looks mostly fine except
things I mentioned above and which I fixed silently. See my diff
below. It is already applied and force pushed.
====================
diff --git a/src/box/mp_error.cc b/src/box/mp_error.cc
index 348b7a70b..86cb8dc23 100644
--- a/src/box/mp_error.cc
+++ b/src/box/mp_error.cc
@@ -39,20 +39,23 @@
* MP_ERROR format:
*
* MP_ERROR: <MP_MAP> {
- * MP_ERROR_STACK: <MP_ARRAY> {
+ * MP_ERROR_STACK: <MP_ARRAY> [
* <MP_MAP> {
- * MP_ERROR_TYPE: <MP_STR>,
- * MP_ERROR_FILE: <MP_STR>,
- * MP_ERROR_LINE: <MP_UINT>,
- * MP_ERROR_REASON: <MP_STR>,
- * MP_ERROR_ERRNO: <MP_STR>,
+ * MP_ERROR_TYPE: <MP_STR>,
+ * MP_ERROR_FILE: <MP_STR>,
+ * MP_ERROR_LINE: <MP_UINT>,
+ * MP_ERROR_MESSAGE: <MP_STR>,
+ * MP_ERROR_ERRNO: <MP_UINT>,
+ * MP_ERROR_CODE: <MP_UINT>,
* MP_ERROR_FIELDS: <MP_MAP> {
* <MP_STR>: ...,
* <MP_STR>: ...,
* ...
* },
+ * ...
* },
- * }
+ * ...
+ * ]
* }
*/
@@ -64,24 +67,26 @@ enum {
};
/**
- * Keys used for error encode/decode to MP_ERROR.
+ * Keys of individual error in the stack.
*/
enum {
- /* Error type */
+ /** Error type. */
MP_ERROR_TYPE = 0x00,
- /* File name from trace */
+ /** File name from trace. */
MP_ERROR_FILE = 0x01,
- /* Line from trace */
+ /** Line from trace. */
MP_ERROR_LINE = 0x02,
- /* Error message */
- MP_ERROR_REASON = 0x03,
- /* Saved errno */
+ /** Error message. */
+ MP_ERROR_MESSAGE = 0x03,
+ /** Errno at the moment of error creation. */
MP_ERROR_ERRNO = 0x04,
+ /** Error code. */
+ MP_ERROR_CODE = 0x05,
/*
- * Key uses for error type-specific fields which
- * presents here as map: string key - value.
+ * Type-specific fields stored as a map
+ * {string key = value}.
*/
- MP_ERROR_FIELDS = 0x05
+ MP_ERROR_FIELDS = 0x06
};
/**
@@ -89,15 +94,15 @@ enum {
* during decoding MP_ERROR.
*/
struct mp_error {
- uint32_t error_code;
+ uint32_t code;
uint32_t line;
uint32_t saved_errno;
- const char *error_type;
+ const char *type;
const char *file;
- const char *reason;
+ const char *message;
const char *custom_type;
- const char *ad_obj_type;
- const char *ad_obj_name;
+ const char *ad_object_type;
+ const char *ad_object_name;
const char *ad_access_type;
};
@@ -110,21 +115,18 @@ mp_error_create(struct mp_error *mp_error)
static uint32_t
encode_error_size(const struct error *error)
{
- uint32_t errcode = 0;
+ uint32_t errcode = box_error_code(error);
- bool is_client = false;
bool is_custom = false;
bool is_access_denied = false;
- if (strcmp(error->type->name, "ClientError") == 0) {
- is_client = true;
- } else if (strcmp(error->type->name, "CustomError") == 0) {
+ if (strcmp(error->type->name, "CustomError") == 0) {
is_custom = true;
} else if (strcmp(error->type->name, "AccessDeniedError") == 0) {
is_access_denied = true;
}
- uint32_t details_num = 5;
+ uint32_t details_num = 6;
uint32_t data_size = 0;
data_size += mp_sizeof_uint(MP_ERROR_TYPE);
@@ -133,40 +135,29 @@ encode_error_size(const struct error *error)
data_size += mp_sizeof_uint(error->line);
data_size += mp_sizeof_uint(MP_ERROR_FILE);
data_size += mp_sizeof_str(strlen(error->file));
- data_size += mp_sizeof_uint(MP_ERROR_REASON);
+ data_size += mp_sizeof_uint(MP_ERROR_MESSAGE);
data_size += mp_sizeof_str(strlen(error->errmsg));
data_size += mp_sizeof_uint(MP_ERROR_ERRNO);
data_size += mp_sizeof_uint(error->saved_errno);
+ data_size += mp_sizeof_uint(MP_ERROR_CODE);
+ data_size += mp_sizeof_uint(errcode);
- if (is_client) {
+ if (is_access_denied) {
++details_num;
data_size += mp_sizeof_uint(MP_ERROR_FIELDS);
- errcode = box_error_code(error);
- data_size += mp_sizeof_map(1);
- data_size += mp_sizeof_str(strlen("code"));
- data_size += mp_sizeof_uint(errcode);
- } else if (is_access_denied) {
- ++details_num;
- data_size += mp_sizeof_uint(MP_ERROR_FIELDS);
- errcode = box_error_code(error);
- data_size += mp_sizeof_map(4);
- data_size += mp_sizeof_str(strlen("code"));
- data_size += mp_sizeof_uint(errcode);
+ data_size += mp_sizeof_map(3);
AccessDeniedError *ad_err = type_cast(AccessDeniedError, error);
- data_size += mp_sizeof_str(strlen("AD_OBJ_TYPE"));
+ data_size += mp_sizeof_str(strlen("object_type"));
data_size += mp_sizeof_str(strlen(ad_err->object_type()));
- data_size += mp_sizeof_str(strlen("AD_OBJ_NAME"));
+ data_size += mp_sizeof_str(strlen("object_name"));
data_size += mp_sizeof_str(strlen(ad_err->object_name()));
- data_size += mp_sizeof_str(strlen("AD_ACCESS_TYPE"));
+ data_size += mp_sizeof_str(strlen("access_type"));
data_size += mp_sizeof_str(strlen(ad_err->access_type()));
} else if (is_custom) {
++details_num;
data_size += mp_sizeof_uint(MP_ERROR_FIELDS);
- errcode = box_error_code(error);
- data_size += mp_sizeof_map(2);
- data_size += mp_sizeof_str(strlen("code"));
- data_size += mp_sizeof_uint(errcode);
- data_size += mp_sizeof_str(strlen("custom"));
+ data_size += mp_sizeof_map(1);
+ data_size += mp_sizeof_str(strlen("custom_type"));
data_size +=
mp_sizeof_str(strlen(box_error_custom_type(error)));
}
@@ -179,23 +170,19 @@ encode_error_size(const struct error *error)
static void
encode_error(const struct error *error, char **data)
{
- uint32_t errcode = 0;
+ uint32_t errcode = box_error_code(error);
- bool is_client = false;
bool is_custom = false;
bool is_access_denied = false;
- if (strcmp(error->type->name, "ClientError") == 0) {
- is_client = true;
- } else if (strcmp(error->type->name, "CustomError") == 0) {
+ if (strcmp(error->type->name, "CustomError") == 0) {
is_custom = true;
} else if (strcmp(error->type->name, "AccessDeniedError") == 0) {
is_access_denied = true;
}
- uint32_t details_num = 5;
-
- if (is_client || is_access_denied || is_custom)
+ uint32_t details_num = 6;
+ if (is_access_denied || is_custom)
++details_num;
*data = mp_encode_map(*data, details_num);
@@ -206,43 +193,34 @@ encode_error(const struct error *error, char **data)
*data = mp_encode_uint(*data, error->line);
*data = mp_encode_uint(*data, MP_ERROR_FILE);
*data = mp_encode_str(*data, error->file, strlen(error->file));
- *data = mp_encode_uint(*data, MP_ERROR_REASON);
+ *data = mp_encode_uint(*data, MP_ERROR_MESSAGE);
*data = mp_encode_str(*data, error->errmsg, strlen(error->errmsg));
*data = mp_encode_uint(*data, MP_ERROR_ERRNO);
*data = mp_encode_uint(*data, error->saved_errno);
+ *data = mp_encode_uint(*data, MP_ERROR_CODE);
+ *data = mp_encode_uint(*data, errcode);
- if (is_client) {
- *data = mp_encode_uint(*data, MP_ERROR_FIELDS);
- errcode = box_error_code(error);
- *data = mp_encode_map(*data, 1);
- *data = mp_encode_str(*data, "code",strlen("code"));
- *data = mp_encode_uint(*data, errcode);
- } else if (is_access_denied) {
+ if (is_access_denied) {
*data = mp_encode_uint(*data, MP_ERROR_FIELDS);
- errcode = box_error_code(error);
- *data = mp_encode_map(*data, 4);
- *data = mp_encode_str(*data, "code",strlen("code"));
- *data = mp_encode_uint(*data, errcode);
+ *data = mp_encode_map(*data, 3);
AccessDeniedError *ad_err = type_cast(AccessDeniedError, error);
- *data = mp_encode_str(*data, "AD_OBJ_TYPE",
- strlen("AD_OBJ_TYPE"));
+ *data = mp_encode_str(*data, "object_type",
+ strlen("object_type"));
*data = mp_encode_str(*data, ad_err->object_type(),
strlen(ad_err->object_type()));
- *data = mp_encode_str(*data, "AD_OBJ_NAME",
- strlen("AD_OBJ_NAME"));
+ *data = mp_encode_str(*data, "object_name",
+ strlen("object_name"));
*data = mp_encode_str(*data, ad_err->object_name(),
strlen(ad_err->object_name()));
- *data = mp_encode_str(*data, "AD_ACCESS_TYPE",
- strlen("AD_ACCESS_TYPE"));
+ *data = mp_encode_str(*data, "access_type",
+ strlen("access_type"));
*data = mp_encode_str(*data, ad_err->access_type(),
strlen(ad_err->access_type()));
} else if (is_custom) {
*data = mp_encode_uint(*data, MP_ERROR_FIELDS);
- errcode = box_error_code(error);
- *data = mp_encode_map(*data, 2);
- *data = mp_encode_str(*data, "code",strlen("code"));
- *data = mp_encode_uint(*data, errcode);
- *data = mp_encode_str(*data, "custom", strlen("custom"));
+ *data = mp_encode_map(*data, 1);
+ *data = mp_encode_str(*data, "custom_type",
+ strlen("custom_type"));
const char *custom = box_error_custom_type(error);
*data = mp_encode_str(*data, custom, strlen(custom));
}
@@ -252,75 +230,69 @@ static struct error *
build_error_xc(struct mp_error *mp_error)
{
/*
- * To create an error the "raw" constructor using
+ * To create an error the "raw" constructor is used
* because OOM error must be thrown in OOM case.
* Builders returns a pointer to the static OOM error
* in OOM case.
*/
struct error *err = NULL;
- if (strcmp(mp_error->error_type, "ClientError") == 0) {
+ if (strcmp(mp_error->type, "ClientError") == 0) {
ClientError *e = new ClientError(mp_error->file, mp_error->line,
ER_UNKNOWN);
- e->m_errcode = mp_error->error_code;
+ e->m_errcode = mp_error->code;
err = e;
- } else if (strcmp(mp_error->error_type, "CustomError") == 0) {
+ } else if (strcmp(mp_error->type, "CustomError") == 0) {
err = new CustomError(mp_error->file, mp_error->line,
- mp_error->custom_type,
- mp_error->error_code);
- } else if (strcmp(mp_error->error_type, "AccessDeniedError") == 0) {
+ mp_error->custom_type, mp_error->code);
+ } else if (strcmp(mp_error->type, "AccessDeniedError") == 0) {
err = new AccessDeniedError(mp_error->file, mp_error->line,
mp_error->ad_access_type,
- mp_error->ad_obj_type,
- mp_error->ad_obj_name, "", false);
- } else if (strcmp(mp_error->error_type, "XlogError") == 0) {
+ mp_error->ad_object_type,
+ mp_error->ad_object_name, "",
+ false);
+ } else if (strcmp(mp_error->type, "XlogError") == 0) {
err = new XlogError(&type_XlogError, mp_error->file,
mp_error->line);
- error_format_msg(err, "%s", mp_error->reason);
- } else if (strcmp(mp_error->error_type, "XlogGapError") == 0) {
+ } else if (strcmp(mp_error->type, "XlogGapError") == 0) {
err = new XlogGapError(mp_error->file, mp_error->line,
- mp_error->reason);
- } else if (strcmp(mp_error->error_type, "SystemError") == 0) {
+ mp_error->message);
+ } else if (strcmp(mp_error->type, "SystemError") == 0) {
err = new SystemError(mp_error->file, mp_error->line,
- "%s", mp_error->reason);
- } else if (strcmp(mp_error->error_type, "SocketError") == 0) {
+ "%s", mp_error->message);
+ } else if (strcmp(mp_error->type, "SocketError") == 0) {
err = new SocketError(mp_error->file, mp_error->line, "", "");
- error_format_msg(err, "%s", mp_error->reason);
- } else if (strcmp(mp_error->error_type, "OutOfMemory") == 0) {
+ error_format_msg(err, "%s", mp_error->message);
+ } else if (strcmp(mp_error->type, "OutOfMemory") == 0) {
err = new OutOfMemory(mp_error->file, mp_error->line,
0, "", "");
- error_format_msg(err, "%s", mp_error->reason);
- } else if (strcmp(mp_error->error_type, "TimedOut") == 0) {
+ } else if (strcmp(mp_error->type, "TimedOut") == 0) {
err = new TimedOut(mp_error->file, mp_error->line);
- } else if (strcmp(mp_error->error_type, "ChannelIsClosed") == 0) {
+ } else if (strcmp(mp_error->type, "ChannelIsClosed") == 0) {
err = new ChannelIsClosed(mp_error->file, mp_error->line);
- } else if (strcmp(mp_error->error_type, "FiberIsCancelled") == 0) {
+ } else if (strcmp(mp_error->type, "FiberIsCancelled") == 0) {
err = new FiberIsCancelled(mp_error->file, mp_error->line);
- } else if (strcmp(mp_error->error_type, "LuajitError") == 0) {
+ } else if (strcmp(mp_error->type, "LuajitError") == 0) {
err = new LuajitError(mp_error->file, mp_error->line,
- mp_error->reason);
- } else if (strcmp(mp_error->error_type, "IllegalParams") == 0) {
+ mp_error->message);
+ } else if (strcmp(mp_error->type, "IllegalParams") == 0) {
err = new IllegalParams(mp_error->file, mp_error->line,
- "%s", mp_error->reason);
- } else if (strcmp(mp_error->error_type, "CollationError") == 0) {
+ "%s", mp_error->message);
+ } else if (strcmp(mp_error->type, "CollationError") == 0) {
err = new CollationError(mp_error->file, mp_error->line,
- "%s", mp_error->reason);
- } else if (strcmp(mp_error->error_type, "SwimError") == 0) {
+ "%s", mp_error->message);
+ } else if (strcmp(mp_error->type, "SwimError") == 0) {
err = new SwimError(mp_error->file, mp_error->line,
- "%s", mp_error->reason);
- } else if (strcmp(mp_error->error_type, "CryptoError") == 0) {
+ "%s", mp_error->message);
+ } else if (strcmp(mp_error->type, "CryptoError") == 0) {
err = new CryptoError(mp_error->file, mp_error->line,
- "%s", mp_error->reason);
+ "%s", mp_error->message);
} else {
err = new ClientError(mp_error->file, mp_error->line,
ER_UNKNOWN);
}
-
- if (err) {
- err->saved_errno = mp_error->saved_errno;
- error_format_msg(err, "%s", mp_error->reason);
- }
-
+ err->saved_errno = mp_error->saved_errno;
+ error_format_msg(err, "%s", mp_error->message);
return err;
}
@@ -337,6 +309,25 @@ region_strdup(struct region *region, const char *str, uint32_t len)
return res;
}
+static inline const char *
+decode_and_copy_str(struct region *region, const char **data)
+{
+ if (mp_typeof(**data) != MP_STR) {
+ diag_set(ClientError, ER_INVALID_MSGPACK,
+ "Invalid MP_ERROR MsgPack format");
+ return NULL;
+ }
+ uint32_t str_len;
+ const char *str = mp_decode_str(data, &str_len);
+ return region_strdup(region, str, str_len);;
+}
+
+static inline bool
+str_nonterm_is_eq(const char *l, const char *r, uint32_t r_len)
+{
+ return r_len == strlen(l) && memcmp(l, r, r_len) == 0;
+}
+
static int
decode_additional_fields(const char **data, struct region *region,
struct mp_error *mp_err)
@@ -344,47 +335,28 @@ decode_additional_fields(const char **data, struct region *region,
uint32_t map_sz = mp_decode_map(data);
const char *key;
uint32_t key_len;
- const char *str;
- uint32_t str_len;
for (uint32_t i = 0; i < map_sz; ++i) {
if (mp_typeof(**data) != MP_STR)
return -1;
key = mp_decode_str(data, &key_len);
-
- if (strncmp(key, "code", key_len) == 0) {
- if (mp_typeof(**data) != MP_UINT)
- return -1;
- mp_err->error_code = mp_decode_uint(data);
- } else if (strncmp(key, "AD_OBJ_TYPE", key_len) == 0) {
- if (mp_typeof(**data) != MP_STR)
+ if (str_nonterm_is_eq("object_type", key, key_len)) {
+ mp_err->ad_object_type =
+ decode_and_copy_str(region, data);
+ if (mp_err->ad_object_type == NULL)
return -1;
- str = mp_decode_str(data, &str_len);
- mp_err->ad_obj_type = region_strdup(region, str,
- str_len);
- if (mp_err->ad_obj_type == NULL)
+ } else if (str_nonterm_is_eq("object_name", key, key_len)) {
+ mp_err->ad_object_name =
+ decode_and_copy_str(region, data);
+ if (mp_err->ad_object_name == NULL)
return -1;
- } else if (strncmp(key, "AD_OBJ_NAME", key_len) == 0) {
- if (mp_typeof(**data) != MP_STR)
- return -1;
- str = mp_decode_str(data, &str_len);
- mp_err->ad_obj_name = region_strdup(region, str,
- str_len);
- if (mp_err->ad_obj_name == NULL)
- return -1;
- } else if (strncmp(key, "AD_ACCESS_TYPE", key_len) == 0) {
- if (mp_typeof(**data) != MP_STR)
- return -1;
- str = mp_decode_str(data, &str_len);
- mp_err->ad_access_type = region_strdup(region, str,
- str_len);
+ } else if (str_nonterm_is_eq("access_type", key, key_len)) {
+ mp_err->ad_access_type =
+ decode_and_copy_str(region, data);
if (mp_err->ad_access_type == NULL)
return -1;
- } else if (strncmp(key, "custom", key_len) == 0) {
- if (mp_typeof(**data) != MP_STR)
- return -1;
- str = mp_decode_str(data, &str_len);
- mp_err->custom_type = region_strdup(region, str,
- str_len);
+ } else if (str_nonterm_is_eq("custom_type", key, key_len)) {
+ mp_err->custom_type =
+ decode_and_copy_str(region, data);
if (mp_err->custom_type == NULL)
return -1;
} else {
@@ -397,43 +369,30 @@ decode_additional_fields(const char **data, struct region *region,
static struct error *
decode_error(const char **data)
{
- if (mp_typeof(**data) != MP_MAP) {
- diag_set(ClientError, ER_INVALID_MSGPACK,
- "Invalid MP_ERROR format");
- return NULL;
- }
-
struct mp_error mp_err;
mp_error_create(&mp_err);
struct region *region = &fiber()->gc;
uint32_t region_svp = region_used(region);
- uint32_t map_size = mp_decode_map(data);
-
struct error *err = NULL;
+ uint32_t map_size;
+
+ if (mp_typeof(**data) != MP_MAP)
+ goto error;
+
+ map_size = mp_decode_map(data);
for (uint32_t i = 0; i < map_size; ++i) {
- if (mp_typeof(**data) != MP_UINT) {
- diag_set(ClientError, ER_INVALID_MSGPACK,
- "Invalid MP_ERROR MsgPack format");
- goto finish;
- }
+ if (mp_typeof(**data) != MP_UINT)
+ goto error;
uint64_t key = mp_decode_uint(data);
- const char *str;
- uint32_t str_len;
switch(key) {
case MP_ERROR_TYPE:
- if (mp_typeof(**data) != MP_STR)
- goto error;
- str = mp_decode_str(data, &str_len);
- mp_err.error_type = region_strdup(region, str, str_len);
- if (mp_err.error_type == NULL)
+ mp_err.type = decode_and_copy_str(region, data);
+ if (mp_err.type == NULL)
goto finish;
break;
case MP_ERROR_FILE:
- if (mp_typeof(**data) != MP_STR)
- goto error;
- str = mp_decode_str(data, &str_len);
- mp_err.file = region_strdup(region, str, str_len);
+ mp_err.file = decode_and_copy_str(region, data);
if (mp_err.file == NULL)
goto finish;
break;
@@ -442,12 +401,9 @@ decode_error(const char **data)
goto error;
mp_err.line = mp_decode_uint(data);
break;
- case MP_ERROR_REASON:
- if (mp_typeof(**data) != MP_STR)
- goto error;
- str = mp_decode_str(data, &str_len);
- mp_err.reason = region_strdup(region, str, str_len);
- if (mp_err.reason == NULL)
+ case MP_ERROR_MESSAGE:
+ mp_err.message = decode_and_copy_str(region, data);
+ if (mp_err.message == NULL)
goto finish;
break;
case MP_ERROR_ERRNO:
@@ -455,10 +411,15 @@ decode_error(const char **data)
goto error;
mp_err.saved_errno = mp_decode_uint(data);
break;
- case MP_ERROR_FIELDS:
- if (decode_additional_fields(data, region, &mp_err) != 0) {
+ case MP_ERROR_CODE:
+ if (mp_typeof(**data) != MP_UINT)
goto error;
- }
+ mp_err.code = mp_decode_uint(data);
+ break;
+ case MP_ERROR_FIELDS:
+ if (decode_additional_fields(data, region,
+ &mp_err) != 0)
+ goto finish;
break;
default:
mp_next(data);
@@ -468,7 +429,7 @@ decode_error(const char **data)
try {
err = build_error_xc(&mp_err);
} catch (OutOfMemory *e) {
- diag_set_error(&fiber()->diag, e);
+ assert(err == NULL && !diag_is_empty(diag_get()));
}
finish:
region_truncate(region, region_svp);
@@ -522,8 +483,7 @@ error_unpack(const char **data, uint32_t len)
}
uint64_t key = mp_decode_uint(data);
switch(key) {
- case MP_ERROR_STACK:
- {
+ case MP_ERROR_STACK: {
uint32_t stack_sz = mp_decode_array(data);
struct error *effect = NULL;
for (uint32_t i = 0; i < stack_sz; i++) {
diff --git a/src/lua/error.h b/src/lua/error.h
index 4e4dc048b..efaaa63fd 100644
--- a/src/lua/error.h
+++ b/src/lua/error.h
@@ -37,6 +37,7 @@
extern "C" {
#endif /* defined(__cplusplus) */
+
/** \cond public */
struct error;
diff --git a/src/lua/msgpack.c b/src/lua/msgpack.c
index 91560eff0..f2ae2d8c3 100644
--- a/src/lua/msgpack.c
+++ b/src/lua/msgpack.c
@@ -239,7 +239,6 @@ luamp_encode(struct lua_State *L, struct luaL_serializer *cfg,
return top_type;
}
-
void
luamp_decode(struct lua_State *L, struct luaL_serializer *cfg,
const char **data)
More information about the Tarantool-patches
mailing list