Request and response format
The types referred to in this document are MessagePack types. For their definitions, see the MP_* MessagePack types section.
Requests and responses have similar structure. They contain three sections: size, header, and body.
It is legal to put more than one request in a packet.
The size is an MP_UINT – unsigned integer, usually 32-bit. It is the size of the header plus the size of the body. It may be useful to compare it with the number of bytes remaining in the packet.
The header is an MP_MAP. It may contain, in any order:
- Both the request and response use the IPROTO_REQUEST_TYPE key. It denotes the type of the packet.
- The request and the matching response have the same sync number (IPROTO_SYNC).
- IPROTO_SCHEMA_VERSION is an optional key that indicates whether there was a major change in the schema.
- In interactive transactions, every stream is identified by a unique IPROTO_STREAM_ID.
In case of replicating synchronous transactions, the header also contains the IPROTO_FLAGS key.
To see how Tarantool encodes the header, have a look at file
xrow.c,
function xrow_header_encode
.
To see how Tarantool decodes the header, have a look at file
net_box.c,
function netbox_decode_data
.
For example, in a successful response to box.space:select()
,
the IPROTO_REQUEST_TYPE value is 0 = IPROTO_OK
and the
array has all the tuples of the result.
Read the source code file net_box.c
where the function decode_metadata_optional
is an example of how Tarantool
itself decodes extra items.
The body is an MP_MAP. Maximal iproto package body length is 2 GiB.
The body has the details of the request or response. In a request, it can also be absent or be an empty map. Both these states are interpreted equally. Responses contain the body anyway even for an IPROTO_PING request, where it is an empty MP_MAP.
A lot of responses contain the IPROTO_DATA map:
For most data-access requests (IPROTO_SELECT, IPROTO_INSERT, IPROTO_DELETE, etc.) the body is an IPROTO_DATA map with an array of tuples that contain an array of fields.
IPROTO_DATA is what we get with net_box and Module buffer
so if we were using net_box we could decode with
msgpack.decode_unchecked(),
or we could convert to a string with ffi.string(pointer,length)
.
The pickle.unpack() function might also be helpful.
Note
For SQL-specific requests and responses, the body is a bit different. Learn more about this type of packets.
Instead of IPROTO_OK, an error response header
has IPROTO_REQUEST_TYPE = IPROTO_TYPE_ERROR.
Its code is 0x8XXX
, where XXX
is the error code – a value in
src/box/errcode.h.
src/box/errcode.h
also has some convenience macros which define hexadecimal
constants for return codes.
The error response body is a map that contains two keys: IPROTO_ERROR and IPROTO_ERROR_24. While IPROTO_ERROR contains an MP_MAP value, IPROTO_ERROR_24 contains a string. The two keys are provided to accommodate clients with older and newer Tarantool versions.
Before Tarantool v. 2.4.1, the key IPROTO_ERROR contained a string and was identical to the current IPROTO_ERROR_24 key.
Let’s consider an example. This is the fifth message, and the request was to create a duplicate
space with conn:eval([[box.schema.space.create('_space');]])
.
The unsuccessful response looks like this:
The tutorial Understanding the binary protocol shows actual byte codes of the response to the IPROTO_EVAL message.
Looking in errcode.h,
we find that the error code 0x0a
(decimal 10) is
ER_SPACE_EXISTS, and the string associated with ER_SPACE_EXISTS is
“Space ‘%s’ already exists”.
Since version 2.4.1, responses for errors have extra information following what was described above. This extra information is given via the MP_ERROR extension type. See details in the MessagePack extensions section.