Модуль buffer
Модуль buffer
возвращает буфер, допускающий динамическое изменение размера, который используется только в качестве опции для методов модуля net.box или модуля msgpack.
Как правило, модуль net.box
возвращает Lua-таблицу. Если используется опция buffer
, то методы модуля net.box
возвращают неформатированную строку строку MsgPack. Это экономит время работы на сервере, если в клиентском приложении есть собственная процедура декодирования MsgPack-строк.
Буфер использует четыре указателя для управления его мощностью:
buf
– указатель на начало буфераrpos
– указатель на начало участка памяти, доступного для чтения данных («read position»)wpos
– указатель на конец участка памяти для чтения и начало участка для записи данных («write position»)epos
– указатель на конец участка для записи данных («end position»)
-
buffer.
ibuf
()¶ Создать новый буфер.
Пример:
В этом примере мы покажем, что использование буфера позволит вам сохранить данные в том же формате, в котором они пришли с сервера. Так что если получить данные с сервера нужно только для отправки куда-то дальше, то с буфером это будет гораздо быстрее.
box.cfg{listen = 3301} buffer = require('buffer') net_box = require('net.box') msgpack = require('msgpack') box.schema.space.create('tester') box.space.tester:create_index('primary') box.space.tester:insert({1, 'ABCDE', 12345}) box.schema.user.create('usr1', {password = 'pwd1'}) box.schema.user.grant('usr1', 'read,write,execute', 'space', 'tester') ibuf = buffer.ibuf() conn = net_box.connect('usr1:pwd1@localhost:3301') conn.space.tester:select({}, {buffer=ibuf}) msgpack.decode_unchecked(ibuf.rpos)
Результат последнего запроса выглядит следующим образом:
tarantool> msgpack.decode_unchecked(ibuf.rpos) --- - {48: [['ABCDE', 12345]]} - 'cdata<char *>: 0x7f97ba10c041' ...
Примечание
До версии 1.7.7 Tarantool в данном случае следует использовать функцию
msgpack.ibuf_decode(ibuf.rpos)
. Начиная с версии 1.7.7 Tarantool ,ibuf_decode
объявлена устаревшей.
-
object
buffer_object
¶ -
buffer_object:
alloc
(size)¶ Аллоцировать
size
байтов дляbuffer_object
’а.Параметры: - size (
number
) – количество байтов для аллоцирования
возвращает: wpos
- size (
-
buffer_object:
capacity
()¶ Вернуть мощность
buffer_object
’а.возвращает: epos - buf
-
buffer_object:
checksize
(size)¶ Проверить, доступно ли
size
байтов для чтения изbuffer_object
’а.Параметры: - size (
number
) – память в байтах для проверки
возвращает: rpos
- size (
-
buffer_object:
pos
()¶ Вернуть размер участка, занятого данными.
возвращает: rpos - buf
-
buffer_object:
read
(size)¶ Прочитать
size
байтов из буфера.
-
buffer_object:
recycle
()¶ Очистить слоты памяти, выделенные для
buffer_object
’а.tarantool> ibuf:recycle() --- ... tarantool> ibuf.buf, ibuf.rpos, ibuf.wpos, ibuf.epos --- - 'cdata<char *>: NULL' - 'cdata<char *>: NULL' - 'cdata<char *>: NULL' - 'cdata<char *>: NULL' ...
-
buffer_object:
reset
()¶ Очистить слоты памяти, использованные
buffer_object
’ом. Этот метод позволяет сохранить буфер, но убрать из него все данные. Это полезно, если вы собираетесь использовать буфер дальше.tarantool> ibuf:reset() --- ... tarantool> ibuf.buf, ibuf.rpos, ibuf.wpos, ibuf.epos --- - 'cdata<char *>: 0x010cc28030' - 'cdata<char *>: 0x010cc28030' - 'cdata<char *>: 0x010cc28030' - 'cdata<char *>: 0x010cc2c000' ...
-
buffer_object:
reserve
(size)¶ Зарезервировать память для
buffer_object
. Проверить, достаточно ли памяти, чтобы записатьsize
байтов послеwpos
. Если нет,epos
будет сдвигаться, покаsize
байтов не будет доступно.
-
buffer_object:
size
()¶ Вернуть участок, доступный для чтения данных.
возвращает: wpos - rpos
-
buffer_object:
unused
()¶ Вернуть участок, доступный для записи данных.
возвращает: epos - wpos
-
Модуль buffer и skip_header
В примере из предыдущего раздела
tarantool> msgpack.decode_unchecked(ibuf.rpos)
---
- {48: [['ABCDE', 12345]]}
- 'cdata<char *>: 0x7f97ba10c041'
...
было показано, что обычно net.box ответ включает в себя заголовок – 48 (в шестнадцатиричной системе – 30), который является ключом для IPROTO_DATA. Но в некоторых ситуациях, например, при передаче буфера в функцию C, которая ожидает массив байт MsgPack без заголовка, заголовок можно пропустить. Это делается путем указания skip_header=true
в качестве опции conn.space.space-name:select{…} или conn.space.space-name:insert{…} или conn.space.space-name:replace{…} или conn.space.space-name:update{…} или conn.space.space-name:upsert{…} или conn.space.space-name:delete{…}. По умолчанию skip_header=false
.
Ниже приведен конец того же примера, но с использованием skip_header=true
.
ibuf = buffer.ibuf()
conn = net_box.connect('usr1:pwd1@localhost:3301')
conn.space.tester:select({}, {buffer=ibuf, skip_header=true})
msgpack.decode_unchecked(ibuf.rpos)
Результат последнего запроса выглядит следующим образом:
tarantool> msgpack.decode_unchecked(ibuf.rpos)
---
- {48: [['ABCDE', 12345]]}
- 'cdata<char *>: 0x7f97ba10c041'
...
Заметьте, что заголовок IPROTO_DATA (48) ушел.
Результат остается внутри массива, что видно из того, что он заключен в квадратные скобки. Пропустить заголовок массива можно и функцией msgpack.decode_array_header()
.