diff --git a/src/box/lua/call.cc b/src/box/lua/call.cc index f28d63e4c6843359242df8006a2aeb1ba2838aac..8207de2be6d887a27337337c1a3531f18c58e823 100644 --- a/src/box/lua/call.cc +++ b/src/box/lua/call.cc @@ -263,26 +263,63 @@ lbox_request_create(struct lua_State *L, enum iproto_request_type type, return request; } -static int -lbox_select(lua_State *L) +static void +port_ffi_add_tuple(struct port *port, struct tuple *tuple) { - if (lua_gettop(L) != 6 || !lua_isnumber(L, 1) || !lua_isnumber(L, 2) || - !lua_isnumber(L, 4) || !lua_isnumber(L, 5) || !lua_isnumber(L, 6)) { - return luaL_error(L, "Usage index:select(key, " - "iterator, offset, limit)"); + struct port_ffi *port_ffi = (struct port_ffi *) port; + if (port_ffi->size >= port_ffi->capacity) { + uint32_t capacity = (port_ffi->capacity > 0) ? + 2 * port_ffi->capacity : 1024; + struct tuple **ret = (struct tuple **) + realloc(port_ffi->ret, sizeof(*ret) * capacity); + assert(ret != NULL); + port_ffi->ret = ret; + port_ffi->capacity = capacity; } + port_ffi->ret[port_ffi->size++] = tuple; +} - RegionGuard region_guard(&fiber()->gc); - struct request *request = lbox_request_create(L, IPROTO_SELECT, - 3, -1); - request->index_id = lua_tointeger(L, 2); - request->iterator = lua_tointeger(L, 4); - request->offset = lua_tointeger(L, 5); - request->limit = lua_tointeger(L, 6); +struct port_vtab port_ffi_vtab = { + port_ffi_add_tuple, + null_port_eof, +}; - lua_newtable(L); - box_process(port_lua_process_create(L), request); - return 1; +void +port_ffi_create(struct port_ffi *port) +{ + memset(port, 0, sizeof(*port)); + port->vtab = &port_ffi_vtab; +} + +void +port_ffi_destroy(struct port_ffi *port) +{ + free(port->ret); + port->capacity = port->size = 0; +} + +int +boxffi_select(struct port *port, uint32_t space_id, uint32_t index_id, + int iterator, uint32_t offset, uint32_t limit, + const char *key, const char *key_end) +{ + struct request request; + request_create(&request, IPROTO_SELECT); + request.space_id = space_id; + request.index_id = index_id; + request.limit = limit; + request.offset = offset; + request.iterator = iterator; + request.key = key; + request.key_end = key_end; + + try { + box_process(port, &request); + return 0; + } catch (Exception *e) { + /* will be hanled by box.raise() in Lua */ + return -1; + } } static int @@ -859,7 +896,6 @@ lbox_unpack(struct lua_State *L) static const struct luaL_reg boxlib[] = { {"process", lbox_process}, - {"_select", lbox_select}, {"_insert", lbox_insert}, {"_replace", lbox_replace}, {"_update", lbox_update}, diff --git a/src/box/lua/call.h b/src/box/lua/call.h index 204c6cd7123322484be5ac822fb86f53620eaf2a..c5ad2c4bab7ff20b10ecb65db2ff0e6302b753c1 100644 --- a/src/box/lua/call.h +++ b/src/box/lua/call.h @@ -29,6 +29,8 @@ * SUCH DAMAGE. */ +#include <stdint.h> + struct txn; struct request; struct port; @@ -40,4 +42,26 @@ struct port; void box_lua_call(struct request *request, struct txn *txn, struct port *port); +extern "C" { +struct port_ffi +{ + struct port_vtab *vtab; + uint32_t size; + uint32_t capacity; + struct tuple **ret; +}; + +void +port_ffi_create(struct port_ffi *port); + +void +port_ffi_destroy(struct port_ffi *port); + +int +boxffi_select(struct port *port, uint32_t space_id, uint32_t index_id, + int iterator, uint32_t offset, uint32_t limit, + const char *key, const char *key_end); + +} /* extern "C" */ + #endif /* INCLUDES_TARANTOOL_MOD_BOX_LUA_CALL_H */ diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua index 0eb94162a4aee06f42dc2add3cf1bb4779d4bcba..e3cff88a570820324fd0a2c654dbc58bb336914f 100644 --- a/src/box/lua/schema.lua +++ b/src/box/lua/schema.lua @@ -12,6 +12,25 @@ ffi.cdef[[ struct iterator * boxffi_index_iterator(uint32_t space_id, uint32_t index_id, int type, const char *key); + + struct port; + struct port_ffi + { + struct port_vtab *vtab; + uint32_t size; + uint32_t capacity; + struct tuple **ret; + }; + + void + port_ffi_create(struct port_ffi *port); + void + port_ffi_destroy(struct port_ffi *port); + + int + boxffi_select(struct port *port, uint32_t space_id, uint32_t index_id, + int iterator, uint32_t offset, uint32_t limit, + const char *key, const char *key_end); ]] local builtin = ffi.C local msgpackffi = require('msgpackffi') @@ -203,6 +222,12 @@ local iterator_cdata_gc = function(iterator_cdata) return iterator_cdata.free(iterator_cdata) end +-- global struct port instance to use by select()/get() +local port = ffi.new('struct port_ffi') +builtin.port_ffi_create(port) +ffi.gc(port, builtin.port_ffi_destroy) +local port_t = ffi.typeof('struct port *') + function box.schema.space.bless(space) local index_mt = {} -- __len and __index @@ -357,12 +382,16 @@ function box.schema.space.bless(space) end index_mt.get = function(index, key) - key = keify(key) - local result = box._select(index.n, index.id, key, box.index.EQ, 0, 2) - if #result == 0 then + local key, key_end = msgpackffi.encode_tuple(key) + port.size = 0; + if builtin.boxffi_select(ffi.cast(port_t, port), index.n, + index.id, box.index.EQ, 0, 2, key, key_end) ~=0 then + return box.raise() + end + if port.size == 0 then return - elseif #result == 1 then - return result[1] + elseif port.size == 1 then + return box.tuple.bless(port.ret[0]) else box.raise(box.error.ER_MORE_THAN_ONE_TUPLE, "More than one tuple found by get()") @@ -374,8 +403,8 @@ function box.schema.space.bless(space) local limit = 4294967295 local iterator = box.index.EQ - key = keify(key) - if #key == 0 then + local key, key_end = msgpackffi.encode_tuple(key) + if key_end == key + 1 then -- empty array iterator = box.index.ALL end @@ -394,7 +423,17 @@ function box.schema.space.bless(space) end end - return box._select(index.n, index.id, key, iterator, offset, limit) + port.size = 0; + if builtin.boxffi_select(ffi.cast(port_t, port), index.n, + index.id, iterator, offset, limit, key, key_end) ~=0 then + return box.raise() + end + + local ret = {} + for i=0,port.size - 1,1 do + table.insert(ret, box.tuple.bless(port.ret[i])) + end + return ret end index_mt.update = function(index, key, ops) return box._update(index.n, index.id, keify(key), ops); @@ -501,4 +540,3 @@ function box.schema.space.bless(space) end end end - diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua index 501e2a7735bf02bf858b214998eebdc083267501..b9b16bd5452bedf3b32927e7af65693df300d6fb 100644 --- a/src/box/lua/tuple.lua +++ b/src/box/lua/tuple.lua @@ -132,8 +132,9 @@ end local tuple_bless = function(tuple) -- update in-place, do not spent time calling tuple_ref + local tuple2 = ffi.gc(ffi.cast(const_struct_tuple_ref_t, tuple), tuple_gc) tuple._refs = tuple._refs + 1 - return ffi.gc(ffi.cast(const_struct_tuple_ref_t, tuple), tuple_gc) + return tuple2 end local tuple_field = function(tuple, field_n) @@ -146,7 +147,6 @@ local tuple_field = function(tuple, field_n) end ffi.metatype('struct tuple', { - __gc = tuple_gc; __len = function(tuple) return builtin.tuple_arity(tuple) end; diff --git a/src/ffisyms.cc b/src/ffisyms.cc index 8ac28fb7fbe6dd91b4e118483ff5386f908886a2..c7e2c190a084e33d6cac9a3264cf9cd372a39125 100644 --- a/src/ffisyms.cc +++ b/src/ffisyms.cc @@ -2,6 +2,7 @@ #include <lib/msgpuck/msgpuck.h> #include <box/tuple.h> #include <box/lua/index.h> +#include <box/lua/call.h> /* * A special hack to cc/ld to keep symbols in an optimized binary. @@ -18,5 +19,8 @@ void *ffi_symbols[] = { (void *) tuple_seek, (void *) tuple_next, (void *) tuple_ref, - (void *) boxffi_index_iterator + (void *) boxffi_index_iterator, + (void *) port_ffi_create, + (void *) port_ffi_destroy, + (void *) boxffi_select }; diff --git a/test/big/lua.result b/test/big/lua.result index f2dbe9483bf9defffc38a4a1af16138aa06c225b..45e66a3caf69fe13d84579dda41108f62b762e80 100644 --- a/test/big/lua.result +++ b/test/big/lua.result @@ -466,7 +466,7 @@ t = {} ... index:iterator('sid_t', { iterator = 'wrong_iterator_type' }) --- -- error: '[string "-- schema.lua (internal file)..."]:248: Wrong iterator type: wrong_iterator_type' +- error: '[string "-- schema.lua (internal file)..."]:273: Wrong iterator type: wrong_iterator_type' ... index = nil --- diff --git a/test/box/misc.result b/test/box/misc.result index 699fb8e706b907e03fe3e7701a3f4d9e8887ca5b..3f0752c55796438c320dbeef3a4921c847afbc85 100644 --- a/test/box/misc.result +++ b/test/box/misc.result @@ -19,7 +19,6 @@ t - - _delete - _insert - _replace - - _select - _update - call_loadproc - cfg