Skip to content

Commit

Permalink
box: support space and index names in IPROTO requests
Browse files Browse the repository at this point in the history
Add support for accepting IPROTO requests with space or index name instead
of identifier (name is preferred over identifier to disambiguate missing
identifiers from zero identifiers): mark space identifier request
key as present upon encountering space name, and delay resolution of
identifier until request gets to transaction thread.

Add support for sending DML requests from net.box connection objects with
disabled schema fetching by manually specifying space or index name or
identifier: when schema fetching is disabled, the space and index tables of
connections return wrapper tables that store necessary context (space or
index name or identifier, determined by type, connection object and space
for indexes) for performing requests. The space and index tables cache the
wrapper table they return.

Closes tarantool#8146

@TarantoolBot document
Title: Space and index name in IPROTO requests

Refer to design document for details:
https://www.notion.so/tarantool/Schemafull-IPROTO-cc315ad6bdd641dea66ad854992d8cbf?pvs=4#f4d4b3fa2b3646f1949319866428b6c0
  • Loading branch information
CuriousGeorgiy committed Apr 24, 2023
1 parent 0b7e5e8 commit 4016f22
Show file tree
Hide file tree
Showing 17 changed files with 452 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## feature/box

* Added support for accepting IPROTO requests with a space or index name instead
of an identifier (gh-8146).
45 changes: 45 additions & 0 deletions src/box/iproto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2138,6 +2138,47 @@ tx_process_rollback(struct cmsg *m)
tx_end_msg(msg, &header);
}

/*
* In case the request does not contain a space or identifier but contains a
* corresponding name, tries to resolve the name.
* A space identifier is mandatory for a DML request, so in case the space
* identifier is not present in the request and we fail to get an identifier
* from the space name, we must return with an
* error, setting a missing request field diagnostic, just as it was done in
* `xrow_decode_dml` before space names in IPROTO requests were introduced.
*/
static int
tx_resolve_space_and_index_name(struct request *dml)
{
struct space *space = NULL;
if (dml->space_name != NULL) {
space = space_by_name(dml->space_name, dml->space_name_len);
if (space == NULL) {
diag_set(ClientError, ER_NO_SUCH_SPACE,
tt_cstr(dml->space_name, dml->space_name_len));
return -1;
}
dml->space_id = space->def->id;
}
if ((dml->type == IPROTO_SELECT || dml->type == IPROTO_UPDATE ||
dml->type == IPROTO_DELETE) && dml->index_name != NULL) {
if (space == NULL)
space = space_cache_find(dml->space_id);
if (space == NULL)
return -1;
struct index *idx = space_index_by_name(space, dml->index_name,
dml->index_name_len);
if (idx == NULL) {
diag_set(ClientError, ER_NO_SUCH_INDEX_NAME,
tt_cstr(dml->index_name, dml->index_name_len),
space->def->name);
return -1;
}
dml->index_id = idx->dense_id;
}
return 0;
}

static void
tx_process1(struct cmsg *m)
{
Expand All @@ -2149,6 +2190,8 @@ tx_process1(struct cmsg *m)
struct obuf_svp svp;
struct obuf *out;
tx_inject_delay();
if (tx_resolve_space_and_index_name(&msg->dml) != 0)
goto error;
if (box_process1(&msg->dml, &tuple) != 0)
goto error;
out = msg->connection->tx.p_obuf;
Expand Down Expand Up @@ -2185,6 +2228,8 @@ tx_process_select(struct cmsg *m)
goto error;

tx_inject_delay();
if (tx_resolve_space_and_index_name(&msg->dml) != 0)
goto error;
packed_pos = req->after_position;
packed_pos_end = req->after_position_end;
if (packed_pos != NULL) {
Expand Down
2 changes: 2 additions & 0 deletions src/box/iproto_constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ const unsigned char iproto_key_type[IPROTO_KEY_MAX] =
/* 0x59 */ MP_UINT, /* IPROTO_TXN_ISOLATION */
/* 0x5a */ MP_UINT, /* IPROTO_VCLOCK_SYNC */
/* 0x5b */ MP_STR, /* IPROTO_AUTH_TYPE */
/* 0x5c */ MP_STR, /* IPROTO_SPACE_NAME */
/* 0x5d */ MP_STR, /* IPROTO_INDEX_NAME */
/* }}} */
};

Expand Down
12 changes: 12 additions & 0 deletions src/box/iproto_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,18 @@ enum iproto_key {
* authentication method.
*/
IPROTO_AUTH_TYPE = 0x5b,
/**
* Space name used instead of identifier (IPROTO_SPACE_ID) in DML
* requests. Preferred when identifier is present (i.e., the identifier
* is ignored).
*/
IPROTO_SPACE_NAME = 0x5c,
/**
* Index name used instead of identifier (IPROTO_INDEX_ID) in
* IPROTO_SELECT, IPROTO_UPDATE, and IPROTO_DELETE requests. Preferred
* when identifier is present (i.e., the identifier is ignored).
*/
IPROTO_INDEX_NAME = 0x5d,
/*
* Be careful to not extend iproto_key values over 0x7f.
* iproto_keys are encoded in msgpack as positive fixnum, which ends at
Expand Down
2 changes: 2 additions & 0 deletions src/box/iproto_features.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,6 @@ iproto_features_init(void)
IPROTO_FEATURE_WATCHERS);
iproto_features_set(&IPROTO_CURRENT_FEATURES,
IPROTO_FEATURE_PAGINATION);
iproto_features_set(&IPROTO_CURRENT_FEATURES,
IPROTO_FEATURE_SPACE_AND_INDEX_NAMES);
}
10 changes: 9 additions & 1 deletion src/box/iproto_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ enum iproto_feature_id {
* request fields and IPROTO_POSITION response field.
*/
IPROTO_FEATURE_PAGINATION = 4,
/**
* Using space [index] names instead of identifiers support:
* IPROTO_SPACE_NAME and IPROTO_INDEX_NAME fields in IPROTO_SELECT,
* IPROTO_UPDATE and IPROTO_DELETE request body;
* IPROTO_SPACE_NAME field in IPROTO_INSERT, IPROTO_REPLACE,
* IPROTO_UPDATE and IPROTO_UPSERT request body.
*/
IPROTO_FEATURE_SPACE_AND_INDEX_NAMES = 5,
iproto_feature_id_MAX,
};

Expand All @@ -69,7 +77,7 @@ struct iproto_features {
* `box.iproto.protocol_version` needs to be updated correspondingly.
*/
enum {
IPROTO_CURRENT_VERSION = 4,
IPROTO_CURRENT_VERSION = 5,
};

/**
Expand Down
3 changes: 3 additions & 0 deletions src/box/lua/iproto.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ push_iproto_key_enum(struct lua_State *L)
{"EVENT_DATA", IPROTO_EVENT_DATA},
{"TXN_ISOLATION", IPROTO_TXN_ISOLATION},
{"VCLOCK_SYNC", IPROTO_VCLOCK_SYNC},
{"SPACE_NAME", IPROTO_SPACE_NAME},
{"INDEX_NAME", IPROTO_INDEX_NAME},
};
push_iproto_constant_subnamespace(L, "key", keys, lengthof(keys));
for (size_t i = 0; i < lengthof(keys); ++i) {
Expand Down Expand Up @@ -293,6 +295,7 @@ push_iproto_protocol_features(struct lua_State *L)
{"error_extension", IPROTO_FEATURE_ERROR_EXTENSION},
{"watchers", IPROTO_FEATURE_WATCHERS},
{"pagination", IPROTO_FEATURE_PAGINATION},
{"space_and_index_names", IPROTO_FEATURE_SPACE_AND_INDEX_NAMES},
};

lua_createtable(L, 0, lengthof(features));
Expand Down
82 changes: 49 additions & 33 deletions src/box/lua/net_box.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ enum {
/**
* IPROTO protocol version supported by the netbox connector.
*/
NETBOX_IPROTO_VERSION = 4,
NETBOX_IPROTO_VERSION = 5,
};

/**
Expand Down Expand Up @@ -797,6 +797,44 @@ netbox_encode_eval(lua_State *L, int idx, struct mpstream *stream,
netbox_end_encode(stream, svp);
}

/*
* Depending on the type of the argument (see also net.box space metatable)
* encode either a space identifier or a space name.
*/
static void
netbox_encode_space_id_or_name(lua_State *L, int idx, struct mpstream *stream)
{
if (lua_type(L, idx) == LUA_TNUMBER) {
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
} else {
size_t len;
const char *space_name = lua_tolstring(L, idx, &len);
mpstream_encode_uint(stream, IPROTO_SPACE_NAME);
mpstream_encode_strn(stream, space_name, len);
}
}

/*
* Depending on the type of the argument (see also net.box index metatable)
* encode either a index identifier or an index name.
*/
static void
netbox_encode_index_id_or_name(lua_State *L, int idx, struct mpstream *stream)
{
if (lua_type(L, idx) == LUA_TNUMBER) {
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, space_id);
} else {
size_t len;
const char *space_name = lua_tolstring(L, idx, &len);
mpstream_encode_uint(stream, IPROTO_INDEX_NAME);
mpstream_encode_strn(stream, space_name, len);
}
}

/* Encode select request. */
static void
netbox_encode_select(lua_State *L, int idx, struct mpstream *stream,
Expand All @@ -817,19 +855,13 @@ netbox_encode_select(lua_State *L, int idx, struct mpstream *stream,
if (fetch_pos)
map_size++;
mpstream_encode_map(stream, map_size);
uint32_t space_id = lua_tonumber(L, idx);
uint32_t index_id = lua_tonumber(L, idx + 1);
int iterator = lua_tointeger(L, idx + 2);
uint32_t offset = lua_tonumber(L, idx + 3);
uint32_t limit = lua_tonumber(L, idx + 4);

/* encode space_id */
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode index_id */
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, index_id);
netbox_encode_index_id_or_name(L, idx + 1, stream);

/* encode iterator */
mpstream_encode_uint(stream, IPROTO_ITERATOR);
Expand Down Expand Up @@ -881,10 +913,7 @@ netbox_encode_insert_or_replace(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 2);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode args */
mpstream_encode_uint(stream, IPROTO_TUPLE);
Expand Down Expand Up @@ -919,15 +948,9 @@ netbox_encode_delete(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 3);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode space_id */
uint32_t index_id = lua_tonumber(L, idx + 1);
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, index_id);
netbox_encode_index_id_or_name(L, idx + 1, stream);

/* encode key */
mpstream_encode_uint(stream, IPROTO_KEY);
Expand All @@ -946,15 +969,9 @@ netbox_encode_update(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 5);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode index_id */
uint32_t index_id = lua_tonumber(L, idx + 1);
mpstream_encode_uint(stream, IPROTO_INDEX_ID);
mpstream_encode_uint(stream, index_id);
netbox_encode_index_id_or_name(L, idx + 1, stream);

/* encode index_id */
mpstream_encode_uint(stream, IPROTO_INDEX_BASE);
Expand All @@ -981,10 +998,7 @@ netbox_encode_upsert(lua_State *L, int idx, struct mpstream *stream,

mpstream_encode_map(stream, 4);

/* encode space_id */
uint32_t space_id = lua_tonumber(L, idx);
mpstream_encode_uint(stream, IPROTO_SPACE_ID);
mpstream_encode_uint(stream, space_id);
netbox_encode_space_id_or_name(L, idx, stream);

/* encode index_base */
mpstream_encode_uint(stream, IPROTO_INDEX_BASE);
Expand Down Expand Up @@ -3000,6 +3014,8 @@ luaopen_net_box(struct lua_State *L)
IPROTO_FEATURE_WATCHERS);
iproto_features_set(&NETBOX_IPROTO_FEATURES,
IPROTO_FEATURE_PAGINATION);
iproto_features_set(&NETBOX_IPROTO_FEATURES,
IPROTO_FEATURE_SPACE_AND_INDEX_NAMES);

lua_pushcfunction(L, luaT_netbox_request_iterator_next);
luaT_netbox_request_iterator_next_ref = luaL_ref(L, LUA_REGISTRYINDEX);
Expand Down

0 comments on commit 4016f22

Please sign in to comment.