diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index fea8640a6f4c185f3dff1cccecad9029e4a9f1fc..cc5a3451af97b19a5b3db7031fc05d11a3d68fe6 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -18,6 +18,8 @@ local tuple_encode = box.internal.tuple.encode local tuple_bless = box.internal.tuple.bless local is_tuple = box.tuple.is assert(tuple_encode ~= nil and tuple_bless ~= nil and is_tuple ~= nil) +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_put = buffer.internal.cord_ibuf_put local INT64_MIN = tonumber64('-9223372036854775808') local INT64_MAX = tonumber64('9223372036854775807') @@ -1785,9 +1787,12 @@ base_index_mt.__len = base_index_mt.len -- min and max base_index_mt.min_ffi = function(index, key) check_index_arg(index, 'min') - local pkey, pkey_end = tuple_encode(key) - if builtin.box_index_min(index.space_id, index.id, - pkey, pkey_end, ptuple) ~= 0 then + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) + local nok = builtin.box_index_min(index.space_id, index.id, pkey, pkey_end, + ptuple) ~= 0 + cord_ibuf_put(ibuf) + if nok then box.error() -- error elseif ptuple[0] ~= nil then return tuple_bless(ptuple[0]) @@ -1802,9 +1807,12 @@ base_index_mt.min_luac = function(index, key) end base_index_mt.max_ffi = function(index, key) check_index_arg(index, 'max') - local pkey, pkey_end = tuple_encode(key) - if builtin.box_index_max(index.space_id, index.id, - pkey, pkey_end, ptuple) ~= 0 then + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) + local nok = builtin.box_index_max(index.space_id, index.id, pkey, pkey_end, + ptuple) ~= 0 + cord_ibuf_put(ibuf) + if nok then box.error() -- error elseif ptuple[0] ~= nil then return tuple_bless(ptuple[0]) @@ -1837,10 +1845,12 @@ end -- iteration base_index_mt.pairs_ffi = function(index, key, opts) check_index_arg(index, 'pairs') - local pkey, pkey_end = tuple_encode(key) + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) local itype = check_iterator_type(opts, pkey + 1 >= pkey_end); local keybuf = ffi.string(pkey, pkey_end - pkey) + cord_ibuf_put(ibuf) local pkeybuf = ffi.cast('const char *', keybuf) local cdata = builtin.box_index_iterator(index.space_id, index.id, itype, pkeybuf, pkeybuf + #keybuf); @@ -1864,10 +1874,12 @@ end -- index subtree size base_index_mt.count_ffi = function(index, key, opts) check_index_arg(index, 'count') - local pkey, pkey_end = tuple_encode(key) + local ibuf = cord_ibuf_take() + local pkey, pkey_end = tuple_encode(ibuf, key) local itype = check_iterator_type(opts, pkey + 1 >= pkey_end); local count = builtin.box_index_count(index.space_id, index.id, itype, pkey, pkey_end); + cord_ibuf_put(ibuf) if count == -1 then box.error() end @@ -1882,9 +1894,12 @@ end base_index_mt.get_ffi = function(index, key) check_index_arg(index, 'get') - local key, key_end = tuple_encode(key) - if builtin.box_index_get(index.space_id, index.id, - key, key_end, ptuple) ~= 0 then + local ibuf = cord_ibuf_take() + local key, key_end = tuple_encode(ibuf, key) + local nok = builtin.box_index_get(index.space_id, index.id, key, key_end, + ptuple) ~= 0 + cord_ibuf_put(ibuf) + if nok then return box.error() -- error elseif ptuple[0] ~= nil then return tuple_bless(ptuple[0]) @@ -1915,13 +1930,15 @@ end base_index_mt.select_ffi = function(index, key, opts) check_index_arg(index, 'select') - local key, key_end = tuple_encode(key) + local ibuf = cord_ibuf_take() + local key, key_end = tuple_encode(ibuf, key) local iterator, offset, limit = check_select_opts(opts, key + 1 >= key_end) local port = ffi.cast('struct port *', port_c) - - if builtin.box_select(index.space_id, index.id, - iterator, offset, limit, key, key_end, port) ~= 0 then + local nok = builtin.box_select(index.space_id, index.id, iterator, offset, + limit, key, key_end, port) ~= 0 + cord_ibuf_put(ibuf) + if nok then return box.error() end diff --git a/src/box/lua/tuple.c b/src/box/lua/tuple.c index ffd01d89994a306dac03cef7387efaf7d243f39e..f7198a0251b6d726ddb7ed90a5e0a29aa9b30a9a 100644 --- a/src/box/lua/tuple.c +++ b/src/box/lua/tuple.c @@ -36,6 +36,7 @@ #include "diag.h" /* diag_set() */ #include <small/ibuf.h> #include <small/region.h> +#include "cord_buf.h" #include <fiber.h> #include "box/tuple.h" @@ -280,16 +281,18 @@ luaT_tuple_encode(struct lua_State *L, int idx, size_t *tuple_len_ptr) box_tuple_t * luaT_tuple_new(struct lua_State *L, int idx, box_tuple_format_t *format) { - struct ibuf *ibuf = tarantool_lua_ibuf; - ibuf_reset(ibuf); + struct ibuf *ibuf = cord_ibuf_take(); size_t tuple_len; + box_tuple_t *tuple; char *tuple_data = luaT_tuple_encode_on_lua_ibuf(L, idx, &tuple_len, ibuf); - if (tuple_data == NULL) - return NULL; - box_tuple_t *tuple = box_tuple_new(format, tuple_data, - tuple_data + tuple_len); - ibuf_reinit(ibuf); + if (tuple_data == NULL) { + tuple = NULL; + } else { + tuple = box_tuple_new(format, tuple_data, + tuple_data + tuple_len); + } + cord_ibuf_drop(ibuf); return tuple; } @@ -308,12 +311,11 @@ lbox_tuple_new(lua_State *L) */ box_tuple_format_t *fmt = box_tuple_format_default(); if (argc != 1 || (!lua_istable(L, 1) && !luaT_istuple(L, 1))) { - struct ibuf *buf = tarantool_lua_ibuf; - ibuf_reset(buf); + struct ibuf *buf = cord_ibuf_take(); luaT_tuple_encode_values(L, buf); /* may raise */ struct tuple *tuple = box_tuple_new(fmt, buf->buf, buf->buf + ibuf_used(buf)); - ibuf_reinit(buf); + cord_ibuf_drop(buf); if (tuple == NULL) return luaT_error(L); luaT_pushtuple(L, tuple); @@ -573,8 +575,7 @@ lbox_tuple_transform(struct lua_State *L) return 1; } - struct ibuf *buf = tarantool_lua_ibuf; - ibuf_reset(buf); + struct ibuf *buf = cord_ibuf_take(); struct mpstream stream; mpstream_init(&stream, buf, ibuf_reserve_cb, ibuf_alloc_cb, luamp_error, L); @@ -619,12 +620,11 @@ lbox_tuple_transform(struct lua_State *L) new_tuple = tuple_new(box_tuple_format_default(), new_data, new_data + new_size); region_truncate(region, used); - + cord_ibuf_put(buf); if (new_tuple == NULL) luaT_error(L); luaT_pushtuple(L, new_tuple); - ibuf_reset(buf); return 1; } diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua index 813d66ff04242a2453692cbd5d47157d46ad641c..fa76f4f7f99fe9678ba5d60ab83c7fe1232ec94b 100644 --- a/src/box/lua/tuple.lua +++ b/src/box/lua/tuple.lua @@ -5,6 +5,8 @@ local msgpackffi = require('msgpackffi') local fun = require('fun') local buffer = require('buffer') local internal = require('box.internal') +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_put = buffer.internal.cord_ibuf_put ffi.cdef[[ /** \cond public */ @@ -71,9 +73,7 @@ local encode_fix = msgpackffi.internal.encode_fix local encode_array = msgpackffi.internal.encode_array local encode_r = msgpackffi.internal.encode_r -local tuple_encode = function(obj) - local tmpbuf = buffer.IBUF_SHARED - tmpbuf:reset() +local tuple_encode = function(tmpbuf, obj) if obj == nil then encode_fix(tmpbuf, 0x90, 0) -- empty array elseif is_tuple(obj) then @@ -229,8 +229,10 @@ local function tuple_update(tuple, expr) if type(expr) ~= 'table' then error("Usage: tuple:update({ { op, field, arg}+ })") end - local pexpr, pexpr_end = tuple_encode(expr) + local ibuf = cord_ibuf_take() + local pexpr, pexpr_end = tuple_encode(ibuf, expr) local tuple = builtin.box_tuple_update(tuple, pexpr, pexpr_end) + cord_ibuf_put(ibuf) if tuple == nil then return box.error() end @@ -242,8 +244,10 @@ local function tuple_upsert(tuple, expr) if type(expr) ~= 'table' then error("Usage: tuple:upsert({ { op, field, arg}+ })") end - local pexpr, pexpr_end = tuple_encode(expr) + local ibuf = cord_ibuf_take() + local pexpr, pexpr_end = tuple_encode(ibuf, expr) local tuple = builtin.box_tuple_upsert(tuple, pexpr, pexpr_end) + cord_ibuf_put(ibuf) if tuple == nil then return box.error() end diff --git a/src/exports.h b/src/exports.h index eb72bc928e56fb70a58c00a5aa45046f1d818f4c..ddbe5723062594b5b8658b6c64295ecae2907653 100644 --- a/src/exports.h +++ b/src/exports.h @@ -113,6 +113,9 @@ EXPORT(coio_getaddrinfo) EXPORT(coio_wait) EXPORT(console_get_output_format) EXPORT(console_set_output_format) +EXPORT(cord_ibuf_drop) +EXPORT(cord_ibuf_put) +EXPORT(cord_ibuf_take) EXPORT(cord_slab_cache) EXPORT(crc32_calc) EXPORT(crypto_EVP_MD_CTX_free) @@ -493,7 +496,6 @@ EXPORT(swim_set_codec) EXPORT(swim_set_payload) EXPORT(swim_size) EXPORT(tarantool_exit) -EXPORT(tarantool_lua_ibuf) EXPORT(tarantool_lua_slab_cache) EXPORT(tarantool_uptime) EXPORT(title_get) diff --git a/src/lib/core/CMakeLists.txt b/src/lib/core/CMakeLists.txt index 30cf0dd152ad3eec92a232bc726cfb7e19860a01..2cd4d0b4f39828211b208a5dc79cca8d03c6271a 100644 --- a/src/lib/core/CMakeLists.txt +++ b/src/lib/core/CMakeLists.txt @@ -29,6 +29,7 @@ set(core_sources port.c decimal.c mp_decimal.c + cord_buf.c ) if (TARGET_OS_NETBSD) diff --git a/src/lib/core/cord_buf.c b/src/lib/core/cord_buf.c new file mode 100644 index 0000000000000000000000000000000000000000..cac508c3d515075acce58e0997553ca1ef338ca4 --- /dev/null +++ b/src/lib/core/cord_buf.c @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2010-2021, Tarantool AUTHORS, please see AUTHORS file. + */ +#include "cord_buf.h" +#include "fiber.h" + +#include "small/ibuf.h" + +enum { + /* No any reason why that value. Historical constant. */ + CORD_IBUF_START_CAPACITY = 16384, +}; + +static struct ibuf *cord_buf_global = NULL; + +struct ibuf * +cord_ibuf_take(void) +{ + assert(cord_is_main()); + struct ibuf *buf = cord_buf_global; + if (buf != NULL) { + ibuf_reset(buf); + return buf; + } + buf = malloc(sizeof(*buf)); + if (buf == NULL) + panic("Couldn't allocate thread buffer"); + ibuf_create(buf, &cord()->slabc, CORD_IBUF_START_CAPACITY); + cord_buf_global = buf; + return buf; +} + +void +cord_ibuf_put(struct ibuf *ibuf) +{ + (void)ibuf; + assert(ibuf == cord_buf_global); +} + +void +cord_ibuf_drop(struct ibuf *ibuf) +{ + ibuf_reinit(ibuf); + assert(ibuf == cord_buf_global); +} diff --git a/src/lib/core/cord_buf.h b/src/lib/core/cord_buf.h new file mode 100644 index 0000000000000000000000000000000000000000..59f429c8f9e4d39b9a41f1f30c3e09fa02dd4439 --- /dev/null +++ b/src/lib/core/cord_buf.h @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2010-2021, Tarantool AUTHORS, please see AUTHORS file. + */ +#pragma once + +#if defined(__cplusplus) +extern "C" { +#endif /* defined(__cplusplus) */ + +struct ibuf; + +/** + * Take the global ibuf, or allocate a new one if the stash is empty. + */ +struct ibuf * +cord_ibuf_take(void); + +/** + * Put the global ibuf back. + */ +void +cord_ibuf_put(struct ibuf *ibuf); + +/** + * Put the global ibuf back and free its memory. So only the buffer object + * itself is saved to the stash. Main reason why it is a dedicated function is + * because it is often needed from Lua, and allows not to call :recycle() there, + * which would be an additional FFI call before cord_ibuf_put(). + * + * XXX: recycle of the global buffer is a workaround for the ibuf being used in + * some places working with Lua API, where it wasn't wanted to "reuse" it + * anyhow. Instead, the global buffer is used to protect from the buffer leak in + * case it would be created locally, and then a Lua error would be raised. When + * the buffer is global, it is not a problem, because it is reused/recycled + * later. But it hurts the places, where re-usage could be good. Probably it is + * worth to separate take/put() from new/drop() API. Or delete drop() entirely. + */ +void +cord_ibuf_drop(struct ibuf *ibuf); + +#if defined(__cplusplus) +} +#endif /* defined(__cplusplus) */ diff --git a/src/lua/buffer.lua b/src/lua/buffer.lua index 00846bb20a4049f21980cf900fe9b383874f090f..d5dbedb0aa2effe64cb803395598ca2ec38e7d5b 100644 --- a/src/lua/buffer.lua +++ b/src/lua/buffer.lua @@ -7,7 +7,15 @@ ffi.cdef[[ struct slab_cache; struct slab_cache * tarantool_lua_slab_cache(); -extern struct ibuf *tarantool_lua_ibuf; + +struct ibuf * +cord_ibuf_take(void); + +void +cord_ibuf_put(struct ibuf *ibuf); + +void +cord_ibuf_drop(struct ibuf *ibuf); struct ibuf { @@ -244,9 +252,48 @@ end -- local reg_array = ffi.new('union c_register[?]', 2) +-- +-- Cord buffer is useful for the places, where +-- +-- * Want to reuse the already allocated memory which might be stored in the +-- cord buf. Although sometimes the buffer is recycled, so should not rely on +-- being able to reuse it always. When reused, the win is the biggest - +-- becomes about x20 times faster than a new buffer creation (~5ns vs ~100ns); +-- +-- * Want to avoid allocation of a new ibuf because it produces a new GC object +-- which is additional load for Lua GC. Although according to benches it is +-- not super expensive; +-- +-- * Almost always can put the buffer back manually. Not rely on it being +-- recycled automatically. It is recycled, but still should not rely on that; +-- +-- It is important to wrap the C functions, not expose them directly. Because +-- JIT works a bit better when C functions are called as 'ffi.C.func()' than +-- 'func()' with func being cached. The only pros is to cache 'ffi.C' itself. +-- It is quite strange though how having them wrapped into a Lua function is +-- faster than cached directly as C functions. +-- +local function cord_ibuf_take() + return builtin.cord_ibuf_take() +end + +local function cord_ibuf_put(buf) + return builtin.cord_ibuf_put(buf) +end + +local function cord_ibuf_drop(buf) + return builtin.cord_ibuf_drop(buf) +end + +local internal = { + cord_ibuf_take = cord_ibuf_take, + cord_ibuf_put = cord_ibuf_put, + cord_ibuf_drop = cord_ibuf_drop, +} + return { + internal = internal, ibuf = ibuf_new; - IBUF_SHARED = ffi.C.tarantool_lua_ibuf; READAHEAD = READAHEAD; static_alloc = static_alloc, -- Keep reference. diff --git a/src/lua/iconv.lua b/src/lua/iconv.lua index e68509dec4b5b64b39d9d65592a3e1d08bdb3f90..732b80514f50af2e4ffc2092f9be01b43e2bf800 100644 --- a/src/lua/iconv.lua +++ b/src/lua/iconv.lua @@ -1,6 +1,8 @@ local ffi = require('ffi') local errno = require('errno') local buffer = require('buffer') +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_put = buffer.internal.cord_ibuf_put ffi.cdef[[ typedef struct iconv *iconv_t; @@ -33,10 +35,9 @@ local function iconv_convert(iconv, data) -- prepare at lease BUF_SIZE and at most data_len bytes in shared buffer local output_len = data_len >= BUF_SIZE and data_len or BUF_SIZE - local buf = buffer.IBUF_SHARED; + local buf = cord_ibuf_take(); local buf_ptr = char_ptr_arr_t() local buf_left = size_t_arr_t() - buf:reset() while data_left[0] > 0 do buf_ptr[0] = buf:reserve(output_len) @@ -46,6 +47,7 @@ local function iconv_convert(iconv, data) if res == ffi.cast('size_t', -1) then local err = errno() if err ~= E2BIG then + cord_ibuf_put(buf) ffi.C.tnt_iconv(iconv, nil, nil, nil, nil) if err == EINVAL then error('Invalid multibyte sequence') @@ -62,7 +64,7 @@ local function iconv_convert(iconv, data) -- iconv function sets cd's conversion state to the initial state ffi.C.tnt_iconv(iconv, nil, nil, nil, nil) local result = ffi.string(buf.rpos, buf:size()) - buf:reset() + cord_ibuf_put(buf) return result end diff --git a/src/lua/init.c b/src/lua/init.c index 767abdfc59ed89e76d124c34843326b78dd9955c..89d7f8f73bf44d7ece7804b345ff9b8388769ad0 100644 --- a/src/lua/init.c +++ b/src/lua/init.c @@ -73,8 +73,6 @@ * The single Lua state of the transaction processor (tx) thread. */ struct lua_State *tarantool_L; -static struct ibuf tarantool_lua_ibuf_body; -struct ibuf *tarantool_lua_ibuf = &tarantool_lua_ibuf_body; /** * The fiber running the startup Lua script */ @@ -453,7 +451,6 @@ tarantool_lua_init(const char *tarantool_bin, int argc, char **argv) if (L == NULL) { panic("failed to initialize Lua"); } - ibuf_create(tarantool_lua_ibuf, tarantool_lua_slab_cache(), 16000); luaL_openlibs(L); tarantool_lua_setpaths(L); diff --git a/src/lua/msgpack.c b/src/lua/msgpack.c index 24b0d2ccd60326ec007ff9c802ffcb3f76656663..1e74a6a3cb758d73c63a5fee93e6469bbfcfa4ff 100644 --- a/src/lua/msgpack.c +++ b/src/lua/msgpack.c @@ -46,6 +46,7 @@ #include "lib/uuid/mp_uuid.h" /* mp_decode_uuid() */ #include "lib/core/mp_extension_types.h" +#include "cord_buf.h" #include <fiber.h> void @@ -362,8 +363,7 @@ lua_msgpack_encode(lua_State *L) "must be of type 'struct ibuf'"); } } else { - buf = tarantool_lua_ibuf; - ibuf_reset(buf); + buf = cord_ibuf_take(); } size_t used = ibuf_used(buf); @@ -380,7 +380,7 @@ lua_msgpack_encode(lua_State *L) lua_pushinteger(L, ibuf_used(buf) - used); } else { lua_pushlstring(L, buf->buf, ibuf_used(buf)); - ibuf_reinit(buf); + cord_ibuf_drop(buf); } return 1; } diff --git a/src/lua/msgpackffi.lua b/src/lua/msgpackffi.lua index 2bc37474281243b06f9505ee52a15117e3fd8eaf..6c245d7aa675187ebde92c06b8f432009e00d055 100644 --- a/src/lua/msgpackffi.lua +++ b/src/lua/msgpackffi.lua @@ -10,6 +10,8 @@ local uint16_ptr_t = ffi.typeof('uint16_t *') local uint32_ptr_t = ffi.typeof('uint32_t *') local uint64_ptr_t = ffi.typeof('uint64_t *') local char_ptr_t = ffi.typeof('char *') +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_drop = buffer.internal.cord_ibuf_drop ffi.cdef([[ char * @@ -294,11 +296,10 @@ local function encode_r(buf, obj, level) end local function encode(obj) - local tmpbuf = buffer.IBUF_SHARED - tmpbuf:reset() + local tmpbuf = cord_ibuf_take() encode_r(tmpbuf, obj, 0) local r = ffi.string(tmpbuf.rpos, tmpbuf:size()) - tmpbuf:recycle() + cord_ibuf_drop(tmpbuf) return r end diff --git a/src/lua/socket.lua b/src/lua/socket.lua index 78d91f010eb6cd4e9c786bd744fc8ef311b346ae..7c24b56550528bc41a5ec215dfcd0afecd87c72f 100644 --- a/src/lua/socket.lua +++ b/src/lua/socket.lua @@ -13,6 +13,8 @@ local buffer = require('buffer') local reg1 = buffer.reg1 local reg2 = buffer.reg2 local static_alloc = buffer.static_alloc +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_drop = buffer.internal.cord_ibuf_drop local format = string.format @@ -296,19 +298,15 @@ local function socket_sysread(self, arg1, arg2) error('socket:sysread(): size can not be negative') end - local buf = buffer.IBUF_SHARED - buf:reset() + local buf = cord_ibuf_take() local p = buf:alloc(size) local res = sysread(self, p, size) if res then - local str = ffi.string(p, res) - buf:recycle() - return str - else - buf:recycle() - return res + res = ffi.string(p, res) end + cord_ibuf_drop(buf) + return res end local function socket_nonblock(self, nb) diff --git a/src/lua/swim.lua b/src/lua/swim.lua index 1da55337adab644538b25348955c3315bcc569db..42b0d15ef0578afacf1f3ee0147a248707a6b00d 100644 --- a/src/lua/swim.lua +++ b/src/lua/swim.lua @@ -6,6 +6,8 @@ local crypto = require('crypto') local fiber = require('fiber') local internal = require('swim') local schedule_task = fiber._internal.schedule_task +local cord_ibuf_take = buffer.internal.cord_ibuf_take +local cord_ibuf_put = buffer.internal.cord_ibuf_put ffi.cdef[[ struct swim; @@ -655,14 +657,17 @@ end local function swim_set_payload(s, payload) local func_name = 'swim:set_payload' local ptr = swim_check_instance(s, func_name) - local payload_size = 0 - if payload ~= nil then - local buf = buffer.IBUF_SHARED - buf:reset() - payload_size = msgpack.encode(payload, buf) + local rc + if payload == nil then + rc = capi.swim_set_payload(ptr, nil, 0) + else + local buf = cord_ibuf_take() + local payload_size = msgpack.encode(payload, buf) payload = buf.rpos + rc = capi.swim_set_payload(ptr, payload, payload_size) + cord_ibuf_put(buf) end - if capi.swim_set_payload(ptr, payload, payload_size) ~= 0 then + if rc ~= 0 then return nil, box.error.last() end return true diff --git a/src/lua/utf8.c b/src/lua/utf8.c index 9c678cad46493a07e4a99fdf3685d6ab0055e514..bf9bb98f45326a0eb53f523611b39aaffe2843e9 100644 --- a/src/lua/utf8.c +++ b/src/lua/utf8.c @@ -33,12 +33,11 @@ #include "coll/coll.h" #include "lua/utils.h" #include "lua/utf8.h" +#include "cord_buf.h" #include "diag.h" #include "small/ibuf.h" #include "tt_static.h" -extern struct ibuf *tarantool_lua_ibuf; - /** Collations for cmp/casecmp functions. */ static struct coll *unicode_coll = NULL; static struct coll *unicode_ci_coll = NULL; @@ -52,12 +51,13 @@ utf8_str_to_case(struct lua_State *L, const char *src, int src_bsize, int i = 0; int dst_bsize = src_bsize; (void) i; + struct ibuf *ibuf = cord_ibuf_take(); do { UErrorCode err = U_ZERO_ERROR; - ibuf_reset(tarantool_lua_ibuf); - char *dst = ibuf_alloc(tarantool_lua_ibuf, dst_bsize); + char *dst = ibuf_alloc(ibuf, dst_bsize); if (dst == NULL) { diag_set(OutOfMemory, dst_bsize, "ibuf_alloc", "dst"); + cord_ibuf_put(ibuf); return luaT_error(L); } int real_bsize; @@ -73,11 +73,13 @@ utf8_str_to_case(struct lua_State *L, const char *src, int src_bsize, if (err == U_ZERO_ERROR || err == U_STRING_NOT_TERMINATED_WARNING) { lua_pushlstring(L, dst, real_bsize); + cord_ibuf_put(ibuf); return 1; } else if (err == U_BUFFER_OVERFLOW_ERROR) { assert(real_bsize > dst_bsize); dst_bsize = real_bsize; } else { + cord_ibuf_put(ibuf); lua_pushnil(L); lua_pushstring(L, tt_sprintf("error during ICU case "\ "transform: %s", @@ -249,9 +251,10 @@ utf8_char(struct lua_State *L) return 1; } /* Slow way - use dynamic buffer. */ - ibuf_reset(tarantool_lua_ibuf); - char *str = ibuf_alloc(tarantool_lua_ibuf, top * U8_MAX_LENGTH); + struct ibuf *ibuf = cord_ibuf_take(); + char *str = ibuf_alloc(ibuf, top * U8_MAX_LENGTH); if (str == NULL) { + cord_ibuf_put(ibuf); diag_set(OutOfMemory, top * U8_MAX_LENGTH, "ibuf_alloc", "str"); return luaT_error(L); @@ -261,6 +264,7 @@ utf8_char(struct lua_State *L) U8_APPEND_UNSAFE(str, len, c); } lua_pushlstring(L, str, len); + cord_ibuf_put(ibuf); return 1; } diff --git a/src/lua/utils.h b/src/lua/utils.h index 37531676d18c6af2df060b455157294d6e34bcfe..4a164868bc675c30477dbbde97eb6bad0abb9916 100644 --- a/src/lua/utils.h +++ b/src/lua/utils.h @@ -72,7 +72,6 @@ struct tt_uuid; * snprintf(m_errmsg, sizeof(m_errmsg), "%s", msg ? msg : ""); */ extern struct lua_State *tarantool_L; -extern struct ibuf *tarantool_lua_ibuf; struct tt_uuid * luaL_pushuuid(struct lua_State *L); diff --git a/static-build/test/static-build/exports.test.lua b/static-build/test/static-build/exports.test.lua index 9b9eaa471f43b5cec265a2ba8acd64b9e39479bd..d5dbe7de9d5eb5ea6d7cd00fd9ce84cb103a0347 100755 --- a/static-build/test/static-build/exports.test.lua +++ b/static-build/test/static-build/exports.test.lua @@ -26,6 +26,9 @@ local check_symbols = { 'guava', 'base64_decode', 'base64_encode', + 'cord_ibuf_drop', + 'cord_ibuf_put', + 'cord_ibuf_take', 'SHA1internal', 'random_bytes', 'fiber_time', @@ -42,7 +45,6 @@ local check_symbols = { 'exception_get_int', 'exception_get_string', - 'tarantool_lua_ibuf', 'uuid_nil', 'tt_uuid_create', 'tt_uuid_str', diff --git a/test/unit/luaT_tuple_new.c b/test/unit/luaT_tuple_new.c index 965b2e6e0e67929cfbed86ab17a627ed182f9216..1d7c9072afad6508a88d5f8ea43defc690a6a041 100644 --- a/test/unit/luaT_tuple_new.c +++ b/test/unit/luaT_tuple_new.c @@ -25,8 +25,6 @@ * box/tuple.test.lua. */ -extern struct ibuf *tarantool_lua_ibuf; - uint32_t min_u32(uint32_t a, uint32_t b) { @@ -184,8 +182,6 @@ main() memory_init(); fiber_init(fiber_c_invoke); - ibuf_create(tarantool_lua_ibuf, &cord()->slabc, 16000); - struct lua_State *L = luaL_newstate(); luaL_openlibs(L);