[Tarantool-patches] [PATCH v2 4/5] iproto: Add session settings for IPROTO
Leonid Vasiliev
lvasiliev at tarantool.org
Fri Apr 10 11:10:42 MSK 2020
IPROTO session settings for error transmission in various formats
depending on session settings have been added.
This is required for backward compatibility.
@TarantoolBot document
Title: Add session_setting
iproto_error_format setting has been added to _session_settings
Used to set the error transmission format in the session.
Old format: transmits as string at IPROTO_BODY
New format: transmits as error object at IPROTO_BODY
Needed for #4398
---
src/box/iproto.cc | 97 ++++++++++++++++++++++++++++++++++++++++++++++
src/box/lua/net_box.lua | 12 ++++++
src/box/session.cc | 3 ++
src/box/session.h | 3 ++
src/box/session_settings.h | 1 +
src/lua/utils.h | 20 ++++++++++
6 files changed, 136 insertions(+)
diff --git a/src/box/iproto.cc b/src/box/iproto.cc
index 9dad43b..92be645 100644
--- a/src/box/iproto.cc
+++ b/src/box/iproto.cc
@@ -55,6 +55,7 @@
#include "call.h"
#include "tuple_convert.h"
#include "session.h"
+#include "session_settings.h"
#include "xrow.h"
#include "schema.h" /* schema_version */
#include "replication.h" /* instance_uuid */
@@ -2183,6 +2184,100 @@ iproto_session_push(struct session *session, uint64_t sync, struct port *port)
/** }}} */
+enum {
+ IPROTO_SESSION_SETTING_ERR_FORMAT = 0,
+ iproto_session_setting_MAX,
+};
+
+static const char *iproto_session_setting_strs[iproto_session_setting_MAX] = {
+ "iproto_error_format",
+};
+
+static int iproto_session_field_type[] = {
+ /** IPROTO_SESSION_SETTING_ERR_FORMAT */
+ FIELD_TYPE_UNSIGNED,
+};
+
+static void
+iproto_session_setting_get(int id, const char **mp_pair,
+ const char **mp_pair_end)
+{
+ if (id < 0 || id >= iproto_session_setting_MAX) {
+ diag_set(ClientError, ER_ILLEGAL_PARAMS,
+ "unknown session setting");
+ return;
+ }
+ struct session *session = current_session();
+
+ const char *name = iproto_session_setting_strs[id];
+ size_t name_len = strlen(name);
+
+ /* Now we have only one iproto session setting. */
+ size_t size = mp_sizeof_array(2) + mp_sizeof_str(name_len)
+ + mp_sizeof_uint(session->serializer_ctx.err_format_ver);
+
+ char *pos = (char*)static_alloc(size);
+ assert(pos != NULL);
+ char *pos_end = mp_encode_array(pos, 2);
+ pos_end = mp_encode_str(pos_end, name, name_len);
+ pos_end = mp_encode_uint(pos_end,
+ session->serializer_ctx.err_format_ver);
+ *mp_pair = pos;
+ *mp_pair_end = pos_end;
+}
+
+static int
+iproto_session_setting_set(int id, const char *mp_value)
+{
+ if (id < 0 || id >= iproto_session_setting_MAX) {
+ diag_set(ClientError, ER_ILLEGAL_PARAMS,
+ "unknown session setting");
+ return -1;
+ }
+ /*Current IPROTO session settings are used only for BINARY session */
+ if (current_session()->type != SESSION_TYPE_BINARY)
+ return -1;
+
+ enum mp_type mtype = mp_typeof(*mp_value);
+ int stype = iproto_session_field_type[id];
+ switch(stype) {
+ case FIELD_TYPE_UNSIGNED: {
+ if (mtype != MP_UINT)
+ break;
+ int val = mp_decode_uint(&mp_value);
+ switch (id) {
+ case IPROTO_SESSION_SETTING_ERR_FORMAT:
+ if (val >= ERR_FORMAT_UNK)
+ break;
+ current_session()->serializer_ctx.err_format_ver = val;
+ return 0;
+ default:
+ diag_set(ClientError, ER_SESSION_SETTING_INVALID_VALUE,
+ iproto_session_setting_strs[id],
+ field_type_strs[stype]);
+ return -1;
+ }
+ break;
+ }
+ default:
+ unreachable();
+ }
+ diag_set(ClientError, ER_SESSION_SETTING_INVALID_VALUE,
+ iproto_session_setting_strs[id], field_type_strs[stype]);
+ return -1;
+}
+
+void
+iproto_session_settings_init()
+{
+ struct session_setting_module *module =
+ &session_setting_modules[SESSION_SETTING_IPROTO];
+ module->settings = iproto_session_setting_strs;
+ module->setting_count = iproto_session_setting_MAX;
+ module->get = iproto_session_setting_get;
+ module->set = iproto_session_setting_set;
+}
+
/** Initialize the iproto subsystem and start network io thread */
void
iproto_init()
@@ -2201,6 +2296,8 @@ iproto_init()
/* .sync = */ iproto_session_sync,
};
session_vtab_registry[SESSION_TYPE_BINARY] = iproto_session_vtab;
+
+ iproto_session_settings_init();
}
/** Available iproto configuration changes. */
diff --git a/src/box/lua/net_box.lua b/src/box/lua/net_box.lua
index 1e0cd7a..c8f76b0 100644
--- a/src/box/lua/net_box.lua
+++ b/src/box/lua/net_box.lua
@@ -1047,6 +1047,18 @@ local function new_sm(host, port, opts, connection, greeting)
if opts.wait_connected ~= false then
remote._transport.wait_state('active', tonumber(opts.wait_connected))
end
+
+ -- Set extended error format for session.
+ if opts.error_extended then
+ local ext_err_supported = version_at_least(remote.peer_version_id, 2, 4, 1)
+ if not ext_err_supported then
+ box.error(box.error.PROC_LUA,
+ "Server doesn't support extended error format")
+ end
+ remote.space._session_settings:update('iproto_error_format',
+ {{'=', 2, 1}})
+ end
+
return remote
end
diff --git a/src/box/session.cc b/src/box/session.cc
index 8813182..0cd8675 100644
--- a/src/box/session.cc
+++ b/src/box/session.cc
@@ -144,6 +144,9 @@ session_create(enum session_type type)
session->sql_default_engine = SQL_STORAGE_ENGINE_MEMTX;
session->sql_stmts = NULL;
+ /* Set default Lua serializer context */
+ session->serializer_ctx.err_format_ver = ERR_FORMAT_DEF;
+
/* For on_connect triggers. */
credentials_create(&session->credentials, guest_user);
struct mh_i64ptr_node_t node;
diff --git a/src/box/session.h b/src/box/session.h
index 6dfc7cb..a8903aa 100644
--- a/src/box/session.h
+++ b/src/box/session.h
@@ -36,6 +36,7 @@
#include "fiber.h"
#include "user.h"
#include "authentication.h"
+#include "lua/utils.h"
#if defined(__cplusplus)
extern "C" {
@@ -110,6 +111,8 @@ struct session {
struct credentials credentials;
/** Trigger for fiber on_stop to cleanup created on-demand session */
struct trigger fiber_on_stop;
+ /** Session Lua serializer context */
+ struct luaL_serializer_ctx serializer_ctx;
};
struct session_vtab {
diff --git a/src/box/session_settings.h b/src/box/session_settings.h
index 25490a7..c139d30 100644
--- a/src/box/session_settings.h
+++ b/src/box/session_settings.h
@@ -41,6 +41,7 @@
* type list is used by setting iterators.
*/
enum session_setting_type {
+ SESSION_SETTING_IPROTO,
SESSION_SETTING_SQL,
session_setting_type_MAX,
};
diff --git a/src/lua/utils.h b/src/lua/utils.h
index 0b36727..5875ba3 100644
--- a/src/lua/utils.h
+++ b/src/lua/utils.h
@@ -266,6 +266,26 @@ struct luaL_serializer {
struct rlist on_update;
};
+/**
+ * An error serialization formats
+ */
+enum error_formats {
+ /** Default(old) format */
+ ERR_FORMAT_DEF,
+ /** Extended format */
+ ERR_FORMAT_EX,
+ /** The max version of error format */
+ ERR_FORMAT_UNK
+};
+
+/**
+ * A serializer context (additional settings for a serializer)
+ */
+struct luaL_serializer_ctx {
+ /** Version of a format for an error transmission */
+ uint8_t err_format_ver;
+};
+
extern int luaL_nil_ref;
extern int luaL_map_metatable_ref;
extern int luaL_array_metatable_ref;
--
2.7.4
More information about the Tarantool-patches
mailing list