Top.Mail.Ru
Модуль buffer | Tarantool
 

Модуль buffer

Модуль 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

buffer_object:capacity()

Вернуть мощность buffer_object’а.

возвращает:epos - buf
buffer_object:checksize(size)

Проверить, доступно ли size байтов для чтения из buffer_object’а.

Параметры:
  • size (number) – память в байтах для проверки
возвращает:

rpos

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().