Top.Mail.Ru
Module buffer | Tarantool
 

Module buffer

Module buffer

The buffer module returns a dynamically resizable buffer which is solely for optional use by methods of the net.box module or the msgpack module.

Ordinarily the net.box methods return a Lua table. If a buffer option is used, then the net.box methods return a raw MsgPack string. This saves time on the server, if the client application has its own routine for decoding raw MsgPack strings.

The buffer uses four pointers to manage its capacity:

  • buf – a pointer to the beginning of the buffer
  • rpos – a pointer to the beginning of the range; available for reading data (“read position”)
  • wpos – a pointer to the end of the range; available for reading data, and to the beginning of the range for writing new data (“write position”)
  • epos – a pointer to the end of the range; available for writing new data (“end position”)
buffer.ibuf()

Create a new buffer.

Example:

In this example we will show that using buffer allows you to keep the data in the format that you get from the server. So if you get the data only for sending it somewhere else, buffer fastens this a lot.

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)

The result of the final request looks like this:

tarantool> msgpack.decode_unchecked(ibuf.rpos)
---
- {48: [['ABCDE', 12345]]}
- 'cdata<char *>: 0x7f97ba10c041'
...

Note

Before Tarantool version 1.7.7, the function to use for this case is msgpack.ibuf_decode(ibuf.rpos). Starting with Tarantool version 1.7.7, ibuf_decode is deprecated.

object buffer_object
buffer_object:alloc(size)

Allocate size bytes for buffer_object.

Parameters:
  • size (number) – memory in bytes to allocate
Return:

wpos

buffer_object:capacity()

Return the capacity of the buffer_object.

Return:epos - buf
buffer_object:checksize(size)

Check if size bytes are available for reading in buffer_object.

Parameters:
  • size (number) – memory in bytes to check
Return:

rpos

buffer_object:pos()

Return the size of the range occupied by data.

Return:rpos - buf
buffer_object:read(size)

Read size bytes from buffer.

buffer_object:recycle()

Clear the memory slots allocated by 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()

Clear the memory slots used by buffer_object. This method allows to keep the buffer but remove data from it. It is useful when you want to use the buffer further.

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)

Reserve memory for buffer_object. Check if there is enough memory to write size bytes after wpos. If not, epos shifts until size bytes will be available.

buffer_object:size()

Return a range, available for reading data.

Return:wpos - rpos
buffer_object:unused()

Return a range for writing data.

Return:epos - wpos

Module buffer and skip_header

The example in the previous section

tarantool> msgpack.decode_unchecked(ibuf.rpos)
---
- {48: [['ABCDE', 12345]]}
- 'cdata<char *>: 0x7f97ba10c041'
...

showed that, ordinarily, the response from net.box includes a header – 48 (hexadecimal 30) that is the key for IPROTO_DATA. But in some situations, for example when passing the buffer to a C function that expects a MsgPack byte array without a header, the header can be skipped. This is done by specifying skip_header=true as an option to conn.space.space-name:select{…} or conn.space.space-name:insert{…} or conn.space.space-name:replace{…} or conn.space.space-name:update{…} or conn.space.space-name:upsert{…} or conn.space.space-name:delete{…}. The default is skip_header=false.

Now here is the end of the same example, except that skip_header=true is used.

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)

The result of the final request looks like this:

tarantool> msgpack.decode_unchecked(ibuf.rpos)
---
- [['ABCDE', 12345]]
- 'cdata<char *>: 0x7f8fd102803f'
...

Notice that the IPROTO_DATA header (48) is gone.

The result is still inside an array, as is clear from the fact that it is shown inside square brackets. It is possible to skip the array header too, with msgpack.decode_array_header().