Формат запросов и ответов
Типы, упоминаемые в этом документе, – это типы MessagePack. Их определения см. в разделе типы MessagePack MP_*.
Запросы и ответы имеют схожую структуру. Они содержат три секции: размер, заголовок и тело.
В один пакет можно поместить более одного запроса.
Размер представлен типом MP_UINT – беззнаковым целым числом, обычно 32-битным. Это размер заголовка плюс размер тела. Может быть полезно сравнить его с количеством оставшихся байтов в пакете.
Заголовок представлен типом MP_MAP. Он может содержать в любом порядке:
- И запрос, и ответ используют ключ IPROTO_REQUEST_TYPE. Он обозначает тип пакета.
- Запрос и соответствующий ему ответ имеют одинаковый номер синхронизации (IPROTO_SYNC).
- IPROTO_SCHEMA_VERSION – необязательный ключ, указывающий на наличие существенных изменений в схеме.
- В интерактивных транзакциях каждый поток идентифицируется уникальным IPROTO_STREAM_ID.
При репликации синхронных транзакций заголовок также содержит ключ IPROTO_FLAGS.
Чтобы увидеть, как Tarantool кодирует заголовок, см. файл xrow.c,
функция xrow_header_encode.
Чтобы увидеть, как Tarantool декодирует заголовок, см. файл net_box.c,
функция netbox_decode_data.
Например, в успешном ответе на box.space:select() значение
IPROTO_REQUEST_TYPE равно 0 = IPROTO_OK, а массив содержит все кортежи
результата.
См. исходный код файла net_box.c,
где функция decode_metadata_optional демонстрирует, как Tarantool
декодирует дополнительные элементы.
Тело представлено типом MP_MAP. Максимальная длина тела пакета iproto составляет 2 ГиБ.
Тело содержит детали запроса или ответа. В запросе оно может также отсутствовать или быть пустой картой. Оба этих состояния интерпретируются одинаково. Ответы содержат тело в любом случае, даже на запрос IPROTO_PING, где оно представляет собой пустую карту MP_MAP.
Многие ответы содержат карту IPROTO_DATA:
Для большинства запросов доступа к данным (IPROTO_SELECT, IPROTO_INSERT, IPROTO_DELETE и т. д.) тело представляет собой карту IPROTO_DATA с массивом кортежей, содержащих массив полей.
IPROTO_DATA – это то, что получается при использовании net_box и
модуля buffer, поэтому при работе через net_box
декодирование можно выполнить с помощью
msgpack.decode_unchecked(), либо
преобразовать в строку с помощью
ffi.string({pointer},{length}). Также
может быть полезна функция pickle.unpack().
Вместо IPROTO_OK заголовок ответа с ошибкой
содержит IPROTO_REQUEST_TYPE =
IPROTO_TYPE_ERROR. Код имеет вид
0x8XXX, где XXX – код ошибки, значение из
src/box/errcode.h.
В src/box/errcode.h также определены вспомогательные макросы, задающие
шестнадцатеричные константы для кодов возврата.
Тело ответа с ошибкой представляет собой карту, содержащую два ключа: IPROTO_ERROR и IPROTO_ERROR_24. В то время как IPROTO_ERROR содержит значение типа MP_MAP, IPROTO_ERROR_24 содержит строку. Эти два ключа предусмотрены для совместимости с клиентами разных версий Tarantool.
До версии Tarantool 2.4.1 ключ IPROTO_ERROR содержал строку и был идентичен текущему ключу IPROTO_ERROR_24.
Рассмотрим пример. Это пятое сообщение, а запрос заключался в создании
дублирующего спейса с помощью
conn:eval([[box.schema.space.create('_space');]]). Неуспешный ответ
выглядит так:
В руководстве Понимание бинарного протокола показаны фактические байтовые коды ответа на сообщение IPROTO_EVAL.
В файле
errcode.h
можно обнаружить, что код ошибки 0x0a (десятичное 10) – это
ER_SPACE_EXISTS, а строка, связанная с ER_SPACE_EXISTS, – "Space
'%s' already exists".
Начиная с версии 2.4.1, ответы с ошибками содержат дополнительную информацию помимо описанной выше. Эта дополнительная информация передается через тип расширения MP_ERROR. Подробнее см. в разделе Расширения MessagePack.