Skip to content

Commit 47e50cd

Browse files
committed
Split most box_protocol content and add TODOs
1 parent feaf36e commit 47e50cd

File tree

13 files changed

+2465
-2243
lines changed

13 files changed

+2465
-2243
lines changed

doc/dev_guide/internals/box_protocol.rst

+22-1,147
Large diffs are not rendered by default.

doc/dev_guide/internals/file_formats.rst

+43-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
.. _internals-data_persistence:
22

3-
--------------------------------------------------------------------------------
43
File formats
5-
--------------------------------------------------------------------------------
4+
============
65

76
.. _internals-wal:
87

9-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
108
Data persistence and the WAL file format
11-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9+
----------------------------------------
1210

1311
To maintain data persistence, Tarantool writes each data change request (insert,
1412
update, delete, replace, upsert) into a write-ahead log (WAL) file in the
@@ -114,9 +112,8 @@ a secondary key, the record in the .xlog file will contain the primary key.
114112

115113
.. _internals-snapshot:
116114

117-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118115
The snapshot file format
119-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
116+
------------------------
120117

121118
The format of a snapshot .snap file is nearly the same as the format of a WAL .xlog file.
122119
However, the snapshot header differs: it contains the instance's global unique identifier
@@ -131,3 +128,43 @@ and ``_cluster`` -- will be at the start of the .snap file, before the records o
131128
any spaces that were created by users.
132129

133130
Secondarily, the .snap file's records are ordered by primary key within space id.
131+
132+
.. _box_protocol-xlog:
133+
134+
Example
135+
-------
136+
137+
The header of a ``.snap`` or ``.xlog`` file looks like:
138+
139+
.. code-block:: none
140+
141+
<type>\n SNAP\n or XLOG\n
142+
<version>\n currently 0.13\n
143+
Server: <server_uuid>\n where UUID is a 36-byte string
144+
VClock: <vclock_map>\n e.g. {1: 0}\n
145+
\n
146+
147+
After the file header come the data tuples.
148+
Tuples begin with a row marker ``0xd5ba0bab`` and
149+
the last tuple may be followed by an EOF marker
150+
``0xd510aded``.
151+
Thus, between the file header and the EOF marker, there
152+
may be data tuples that have this form:
153+
154+
.. code-block:: none
155+
156+
0 3 4 17
157+
+-------------+========+============+===========+=========+
158+
| | | | | |
159+
| 0xd5ba0bab | LENGTH | CRC32 PREV | CRC32 CUR | PADDING |
160+
| | | | | |
161+
+-------------+========+============+===========+=========+
162+
MP_FIXEXT2 MP_INT MP_INT MP_INT ---
163+
164+
+============+ +===================================+
165+
| | | |
166+
| HEADER | | BODY |
167+
| | | |
168+
+============+ +===================================+
169+
MP_MAP MP_MAP
170+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
Authentication
2+
==============
3+
4+
.. _box_protocol-authentication:
5+
6+
Greeting message
7+
----------------
8+
9+
When a client connects to the server instance, the instance responds with
10+
a 128-byte text greeting message, not in MsgPack format: |br|
11+
64-byte Greeting text line 1 |br|
12+
64-byte Greeting text line 2 |br|
13+
44-byte base64-encoded salt |br|
14+
20-byte NULL
15+
16+
The greeting contains two 64-byte lines of ASCII text.
17+
Each line ends with a newline character (:code:`\n`). The first line contains
18+
the instance version and protocol type. The second line contains up to 44 bytes
19+
of base64-encoded random string, to use in the authentication packet, and ends
20+
with up to 23 spaces.
21+
22+
Part of the greeting is a base64-encoded session salt -
23+
a random string which can be used for authentication. The maximum length of an encoded
24+
salt (44 bytes) is more than the amount necessary to create the authentication
25+
message. An excess is reserved for future authentication
26+
schemas.
27+
28+
Authentication is optional -- if it is skipped, then the session user is ``'guest'``
29+
(the ``'guest'`` user does not need a password).
30+
31+
If authentication is not skipped, then at any time an authentication packet
32+
can be prepared using the greeting, the user's name and password,
33+
and `sha-1 <https://en.wikipedia.org/wiki/SHA-1>`_ functions, as follows.
34+
35+
.. code-block:: none
36+
37+
PREPARE SCRAMBLE:
38+
39+
size_of_encoded_salt_in_greeting = 44;
40+
size_of_salt_after_base64_decode = 32;
41+
/* sha1() will only use the first 20 bytes */
42+
size_of_any_sha1_digest = 20;
43+
size_of_scramble = 20;
44+
45+
prepare 'chap-sha1' scramble:
46+
47+
salt = base64_decode(encoded_salt);
48+
step_1 = sha1(password);
49+
step_2 = sha1(step_1);
50+
step_3 = sha1(first_20_bytes_of_salt, step_2);
51+
scramble = xor(step_1, step_3);
52+
return scramble;

doc/dev_guide/internals/iproto/format.rst

+131
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ For example, in a successful response to ``box.space:select()``,
106106
the Response-Code-Indicator value will be 0 = ``IPROTO_OK`` and the
107107
array will have all the tuples of the result.
108108

109+
Read the source code file `net_box.c <https://github.com/tarantool/tarantool/blob/master/src/box/lua/net_box.c>`_
110+
where the function "decode_metadata_optional" is an example of how Tarantool
111+
itself decodes extra items.
112+
109113
Body
110114
~~~~
111115

@@ -114,3 +118,130 @@ be absent or be an empty map. Both these states will be interpreted equally.
114118
Responses will contain the ``<body>`` anyway even for an
115119
:ref:`IPROTO_PING <box_protocol-ping>` request.
116120

121+
122+
.. cssclass:: highlight
123+
.. parsed-literal::
124+
125+
# <size>
126+
msgpack(:samp:`{{MP_UINT unsigned integer = size(<header>) + size(<body>)}}`)
127+
# <header>
128+
msgpack({
129+
Response-Code-Indicator: IPROTO_OK,
130+
IPROTO_SYNC: :samp:`{{MP_UINT unsigned integer, may be 64-bit}}`,
131+
IPROTO_SCHEMA_VERSION: :samp:`{{MP_UINT unsigned integer}}`
132+
})
133+
# <body>
134+
msgpack({
135+
IPROTO_DATA: :samp:`{{any type}}`
136+
})
137+
138+
- For :ref:`IPROTO_PING <box_protocol-ping>` the body will be an empty map.
139+
140+
141+
IPROTO_DATA is what we get with net_box and :ref:`Module buffer <buffer-module>`
142+
so if we were using net_box we could decode with
143+
:ref:`msgpack.decode_unchecked() <msgpack-decode_unchecked_string>`,
144+
or we could convert to a string with :samp:`ffi.string({pointer},{length})`.
145+
The :ref:`pickle.unpack() <pickle-unpack>` function might also be helpful.
146+
147+
Response body
148+
~~~~~~~~~~~~~
149+
150+
After the :ref:`header <box_protocol-header>`, for a response,
151+
there will be a body.
152+
If there was no error, it will contain IPROTO_OK (0x00).
153+
If there was an error, it will contain an error code other than IPROTO_OK.
154+
Responses to SQL statements are slightly different and will be described
155+
in the later section,
156+
:ref:`Binary protocol -- responses for SQL <box_protocol-sql_protocol>`.
157+
158+
For IPROTO_OK, the header Response-Code-Indicator will be 0 and the body is a 1-item map.
159+
160+
.. cssclass:: highlight
161+
.. parsed-literal::
162+
163+
# <size>
164+
msgpack(:samp:`{{MP_UINT unsigned integer = size(<header>) + size(<body>)}}`)
165+
# <header>
166+
msgpack({
167+
Response-Code-Indicator: IPROTO_OK,
168+
IPROTO_SYNC: :samp:`{{MP_UINT unsigned integer, may be 64-bit}}`,
169+
IPROTO_SCHEMA_VERSION: :samp:`{{MP_UINT unsigned integer}}`
170+
})
171+
# <body>
172+
msgpack({
173+
IPROTO_DATA: :samp:`{{any type}}`
174+
})
175+
176+
Responses for SQL
177+
-----------------
178+
179+
After the :ref:`header <box_protocol-header>`, for a response to an SQL statement,
180+
there will be a body that is slightly different from the body for
181+
:ref:`Binary protocol -- responses if no error and no SQL <box_protocol-responses>`.
182+
183+
If the SQL request is not SELECT or VALUES or PRAGMA, then the response body
184+
contains only IPROTO_SQL_INFO (0x42). Usually IPROTO_SQL_INFO is a map with only
185+
one item -- SQL_INFO_ROW_COUNT (0x00) -- which is the number of changed rows.
186+
187+
.. _box_protocol-responses_error:
188+
189+
Responses for errors
190+
--------------------
191+
192+
For a response other than IPROTO_OK, the header Response-Code-Indicator will be
193+
``0x8XXX`` and the body will be a 1-item map.
194+
195+
.. cssclass:: highlight
196+
.. parsed-literal::
197+
198+
# <size>
199+
msgpack(32)
200+
# <header>
201+
msgpack({
202+
Response-Code-Indicator: :samp:`{{0x8XXX}}`,
203+
IPROTO_SYNC: :samp:`{{MP_UINT unsigned integer, may be 64-bit}}`,
204+
IPROTO_SCHEMA_VERSION: :samp:`{{MP_UINT unsigned integer}}`
205+
})
206+
# <body>
207+
msgpack({
208+
IPROTO_ERROR: :samp:`{{MP_STRING string}}`
209+
})
210+
211+
where ``0x8XXX`` is the indicator for an error and ``XXX`` is a value in
212+
`src/box/errcode.h <https://github.com/tarantool/tarantool/blob/master/src/box/errcode.h>`_.
213+
``src/box/errcode.h`` also has some convenience macros which define hexadecimal
214+
constants for return codes.
215+
216+
Example: in version 2.4.0 and earlier,
217+
if this is the fifth message and the request is to create a duplicate
218+
space with
219+
``conn:eval([[box.schema.space.create('_space');]])``
220+
the unsuccessful response will look like this:
221+
222+
.. code-block:: none
223+
224+
# <size>
225+
msgpack(32)
226+
# <header>
227+
msgpack({
228+
Response-Code-Indicator: 0x800a,
229+
IPROTO_SYNC: 5,
230+
IPROTO_SCHEMA_VERSION: 0x78
231+
})
232+
# <body>
233+
msgpack({
234+
IPROTO_ERROR: "Space '_space' already exists"
235+
})
236+
237+
Later in :ref:`Binary protocol -- illustration <box_protocol-illustration>`
238+
we will show actual byte codes of the response to the IPROTO_EVAL message.
239+
240+
Looking in errcode.h we find that error code 0x0a (decimal 10) is
241+
ER_SPACE_EXISTS, and the string associated with ER_SPACE_EXISTS is
242+
"Space '%s' already exists".
243+
244+
Since version :doc:`2.4.1 </release/2.4.1>`, responses for errors have extra information
245+
following what was described above. This extra information is given via
246+
MP_ERROR extension type. See details in :ref:`MessagePack extensions
247+
<msgpack_ext-error>` section.

doc/dev_guide/internals/iproto/keys.rst

+43-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,20 @@ This section describes all the iproto keys used to pass request arguments.
3535
used with SQL within IPROTO_EXECUTE:
3636
IPROTO_OPTIONS=0x2b
3737
IPROTO_METADATA=0x32
38+
* :samp:`IPROTO_METADATA: {array of column maps}` = array of column maps, with each column map containing
39+
at least IPROTO_FIELD_NAME (0x00) and MP_STR, and IPROTO_FIELD_TYPE (0x01) and MP_STR.
40+
Additionally, if ``sql_full_metadata`` in the
41+
:ref:`_session_settings <box_space-session_settings>` system space
42+
is TRUE, then the array will have these additional column maps
43+
which correspond to components described in the
44+
:ref:`box.execute() <box-sql_if_full_metadata>` section:
45+
46+
.. code-block:: none
47+
48+
IPROTO_FIELD_COLL (0x02) and MP_STR
49+
IPROTO_FIELD_IS_NULLABLE (0x03) and MP_BOOL
50+
IPROTO_FIELD_IS_AUTOINCREMENT (0x04) and MP_BOOL
51+
IPROTO_FIELD_SPAN (0x05) and MP_STR or MP_NIL
3852
IPROTO_BIND_METADATA=0x33
3953
IPROTO_BIND_COUNT=0x34
4054
IPROTO_SQL_TEXT=0x40
@@ -44,6 +58,23 @@ This section describes all the iproto keys used to pass request arguments.
4458
4559
"No error" constant
4660
IPROTO_OK=0x00
61+
For IPROTO_OK, the header Response-Code-Indicator will be 0 and the body is a 1-item map.
62+
63+
.. cssclass:: highlight
64+
.. parsed-literal::
65+
66+
# <size>
67+
msgpack(:samp:`{{MP_UINT unsigned integer = size(<header>) + size(<body>)}}`)
68+
# <header>
69+
msgpack({
70+
Response-Code-Indicator: IPROTO_OK,
71+
IPROTO_SYNC: :samp:`{{MP_UINT unsigned integer, may be 64-bit}}`,
72+
IPROTO_SCHEMA_VERSION: :samp:`{{MP_UINT unsigned integer}}`
73+
})
74+
# <body>
75+
msgpack({
76+
IPROTO_DATA: :samp:`{{any type}}`
77+
})
4778
4879
box.session.sync(), like a clock, must be same for response and request
4980
IPROTO_SYNC=0x01
@@ -83,7 +114,7 @@ This section describes all the iproto keys used to pass request arguments.
83114
IPROTO_TIMESTAMP=0x04 Float 64 MP_DOUBLE 8-byte timestamp
84115
IPROTO_SCHEMA_VERSION=0x05
85116
Stream transactions
86-
IPROTO_STREAM_ID=0x0a
117+
IPROTO_STREAM_ID=0x0a Дать ссылку на подраздел про стримы
87118
IPROTO_TXN_ISOLATION=0x59
88119
IPROTO_FUNCTION_NAME=0x22
89120
user name
@@ -105,6 +136,9 @@ This section describes all the iproto keys used to pass request arguments.
105136
IPROTO_ERROR_24=0x31
106137
107138
IPROTO_CHUNK=0x80
139+
If the response is out-of-band, due to use of
140+
:ref:`box.session.push() <box_session-push>`,
141+
then the header Response-Code-Indicator will be IPROTO_CHUNK instead of IPROTO_OK.
108142

109143
IPROTO_TIMEOUT=0x56
110144

@@ -119,3 +153,11 @@ This section describes all the iproto keys used to pass request arguments.
119153

120154
IPROTO_EVENT_KEY=0x57
121155
IPROTO_EVENT_DATA=0x58
156+
157+
IPROTO_SQL_INFO (0x42)
158+
Usually IPROTO_SQL_INFO is a map with only one item -- SQL_INFO_ROW_COUNT (0x00) -- which is the number of changed rows
159+
The IPROTO_SQL_INFO map may contain a second item -- :samp:`SQL_INFO_AUTO_INCREMENT_IDS
160+
(0x01)` -- which is the new primary-key value (or values) for an INSERT in a table
161+
defined with PRIMARY KEY AUTOINCREMENT.
162+
SQL_INFO_ROW_COUNT (0x00)
163+
SQL_INFO_AUTO_INCREMENT_IDS (0x01)

0 commit comments

Comments
 (0)