diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc8a9e86c87a000eb08fbb29e2d8e10c0923ab7a..f4b27c6cd65692daefd12ca0ec80fd4c6bfd9b8b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -132,6 +132,7 @@ set (common_sources lua/slab.m lua/uuid.m lua/lua_ipc.m + lua/space.m ) if (ENABLE_TRACE) diff --git a/src/box/box.lua b/src/box/box.lua index 2f68c47aa841c94a1b694fe96d50c675ffb4f146..238aee1925e61f03b217b8755964a74989895dd1 100644 --- a/src/box/box.lua +++ b/src/box/box.lua @@ -173,7 +173,7 @@ function box.counter.dec(space, ...) end end -function box.on_reload_configuration() +function box.bless_space(space) local index_mt = {} -- __len and __index index_mt.len = function(index) return #index.idx end @@ -254,18 +254,20 @@ function box.on_reload_configuration() end space_mt.pairs = function(space) return space.index[0]:pairs() end space_mt.__index = space_mt - for i, space in pairs(box.space) do - rawset(space, 'n', i) - setmetatable(space, space_mt) - if type(space.index) == 'table' and space.enabled then - for j, index in pairs(space.index) do - rawset(index, 'idx', box.index.new(i, j)) - setmetatable(index, index_mt) - end + + setmetatable(space, space_mt) + if type(space.index) == 'table' and space.enabled then + for j, index in pairs(space.index) do + rawset(index, 'idx', box.index.new(space.n, j)) + setmetatable(index, index_mt) end end end +-- User can redefine the hook +function box.on_reload_configuration() +end + require("bit") -- vim: set et ts=4 sts diff --git a/src/box/index.h b/src/box/index.h index f77bb465ddc068f81a889943b050c567d3bf4f88..fae5231dc7981f489c0f5799739388d49706476c 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -77,6 +77,7 @@ struct key_def { */ int max_fieldno; bool is_unique; + enum index_type type; }; /** Descriptor of index features. */ diff --git a/src/box/space.m b/src/box/space.m index 5a08e1b2e9dd0865504896bd644f8ced17ad5f55..5903926f2c6a44100e89321dbeba8790ad5a7cc3 100644 --- a/src/box/space.m +++ b/src/box/space.m @@ -216,6 +216,12 @@ key_init(struct key_def *def, struct tarantool_cfg_space_index *cfg_index) { def->max_fieldno = 0; def->part_count = 0; + if (strcmp(cfg_index->type, "HASH") == 0) + def->type = HASH; + else if (strcmp(cfg_index->type, "TREE") == 0) + def->type = TREE; + else + panic("Wrong index type: %s", cfg_index->type); /* Calculate key part count and maximal field number. */ for (int k = 0; cfg_index->key_field[k] != NULL; ++k) { diff --git a/src/lua/init.m b/src/lua/init.m index 527c67ce984a7ac9c82261af88eef413fb7b93c9..e1b7beae3e0255247e80861562f5da2ea87eee59 100644 --- a/src/lua/init.m +++ b/src/lua/init.m @@ -48,6 +48,7 @@ #include "lua/slab.h" #include "lua/stat.h" #include "lua/uuid.h" +#include "space.h" #include TARANTOOL_CONFIG @@ -1374,14 +1375,13 @@ tarantool_lua_load_cfg(struct lua_State *L, struct tarantool_cfg *cfg) luaL_addstring(&b, "box.cfg = {}\n" "setmetatable(box.cfg, {})\n" - "box.space = {}\n" - "setmetatable(box.space, getmetatable(box.cfg))\n" - "getmetatable(box.space).__index = " + "getmetatable(box.cfg).__index = " "function(table, index)\n" " table[index] = {}\n" " setmetatable(table[index], getmetatable(table))\n" " return rawget(table, index)\n" - "end\n"); + "end\n" + ); while ((key = tarantool_cfg_iterator_next(i, cfg, &value)) != NULL) { if (value == NULL) continue; @@ -1390,44 +1390,33 @@ tarantool_lua_load_cfg(struct lua_State *L, struct tarantool_cfg *cfg) lua_pushfstring(L, "box.cfg.%s = %s%s%s\n", key, quote, value, quote); luaL_addvalue(&b); - } else if (strncmp(key, "space", strlen("space")) == 0) { - lua_pushfstring(L, "box.%s = %s%s%s\n", - key, quote, value, quote); - luaL_addvalue(&b); } free(value); } - if (cfg->memcached_port) { - lua_pushfstring(L, - "box.space[%d].enabled = true\n" - "box.space[%d].cardinality = 4\n" - "box.space[%d].estimated_rows = 0\n" - "box.space[%d].index[0].unique = true\n" - "box.space[%d].index[0].type = 'HASH'\n" - "box.space[%d].index[0].key_field[0].field_no = 0\n" - "box.space[%d].index[0].key_field[0].field_type = 'STRING'\n", - cfg->memcached_space, cfg->memcached_space, - cfg->memcached_space, cfg->memcached_space, - cfg->memcached_space, cfg->memcached_space, - cfg->memcached_space); - luaL_addvalue(&b); - } + luaL_addstring(&b, "getmetatable(box.cfg).__newindex = " "function(table, index)\n" " error('Attempt to modify a read-only table')\n" "end\n" "getmetatable(box.cfg).__index = nil\n" - "if type(box.on_reload_configuration) == 'function' " - "then\n" - " box.on_reload_configuration()\n" - "end\n"); + ); luaL_pushresult(&b); if (luaL_loadstring(L, lua_tostring(L, -1)) != 0 || lua_pcall(L, 0, 0, 0) != 0) { panic("%s", lua_tostring(L, -1)); } - lua_pop(L, 1); + lua_pop(L, 1); /* cleanup stack */ + + lbox_space_init(L); + + /* on_reload_configuration hook */ + lua_getfield(L, LUA_GLOBALSINDEX, "box"); + lua_pushstring(L, "on_reload_configuration"); + lua_gettable(L, -2); + if (lua_isfunction(L, -1)) + lua_call(L, 0, 0); + lua_pop(L, 1); /* cleanup stack */ } /** diff --git a/src/lua/space.h b/src/lua/space.h new file mode 100644 index 0000000000000000000000000000000000000000..a6ee38d2a449cb8aaa658b3ebe2f4ff106c4653e --- /dev/null +++ b/src/lua/space.h @@ -0,0 +1,40 @@ +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef INCLUDES_TARANTOOL_LUA_SPACE_H +#define INCLUDES_TARANTOOL_LUA_SPACE_H + + +struct lua_State; +struct space; + +int lbox_pushspace(struct lua_State *L, struct space *space); +void lbox_space_init(struct lua_State *L); + +#endif /* INCLUDES_TARANTOOL_LUA_SPACE_H */ diff --git a/src/lua/space.m b/src/lua/space.m new file mode 100644 index 0000000000000000000000000000000000000000..c3526535c759e263de0935e665fae7213ee1fcd9 --- /dev/null +++ b/src/lua/space.m @@ -0,0 +1,166 @@ +/* + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "space.h" +#include "../box/space.h" +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include <say.h> + + +int +lbox_pushspace(struct lua_State *L, struct space *space) +{ + lua_newtable(L); + + /* space.cardinality */ + lua_pushstring(L, "cardinality"); + lua_pushnumber(L, space->arity); + lua_settable(L, -3); + + /* space.n */ + lua_pushstring(L, "n"); + lua_pushnumber(L, space->no); + lua_settable(L, -3); + + /* all exists spaces are enabled */ + lua_pushstring(L, "enabled"); + lua_pushboolean(L, 1); + lua_settable(L, -3); + + /* legacy field */ + lua_pushstring(L, "estimated_rows"); + lua_pushnumber(L, 0); + lua_settable(L, -3); + + /* space.index */ + lua_pushstring(L, "index"); + lua_newtable(L); + + + for(int i = 0; i < space->key_count; i++) { + lua_pushnumber(L, i); + lua_newtable(L); /* space.index[i] */ + + lua_pushstring(L, "idx"); + lua_pushfstring(L, "index %d in space %d", i, space->no); + lua_settable(L, -3); + + lua_pushstring(L, "unique"); + lua_pushboolean(L, space->key_defs[i].is_unique); + lua_settable(L, -3); + + lua_pushstring(L, "type"); + switch(space->key_defs[i].type) { + case HASH: + lua_pushstring(L, "HASH"); + break; + case TREE: + lua_pushstring(L, "TREE"); + break; + default: + panic("unknown index type %d", + space->key_defs[i].parts[0].type); + } + lua_settable(L, -3); + + lua_pushstring(L, "key_field"); + lua_newtable(L); + + for (int j = 0; j < space->key_defs[i].part_count; j++) { + lua_pushnumber(L, j); + lua_newtable(L); + + lua_pushstring(L, "type"); + switch(space->key_defs[i].parts[j].type) { + case NUM: + lua_pushstring(L, "NUM"); + break; + case NUM64: + lua_pushstring(L, "NUM64"); + break; + case STRING: + lua_pushstring(L, "STR"); + break; + default: + lua_pushstring(L, "UNKNOWN"); + break; + } + lua_settable(L, -3); + + lua_pushstring(L, "fieldno"); + lua_pushnumber(L, space->key_defs[i].parts[j].fieldno); + lua_settable(L, -3); + + lua_settable(L, -3); + } + + lua_settable(L, -3); /* space[i].key_field */ + + lua_settable(L, -3); /* space[i] */ + } + + lua_settable(L, -3); /* push space.index */ + + + /* on_reload_configuration hook */ + lua_getfield(L, LUA_GLOBALSINDEX, "box"); + lua_pushstring(L, "bless_space"); + lua_gettable(L, -2); + + if (!lua_isfunction(L, -1)) + panic("box.bless_space isn't a function"); + + lua_pushvalue(L, -3); /* box, bless, space */ + lua_call(L, 1, 0); + lua_pop(L, 1); /* cleanup stack */ + + return 1; +} + +static void +lbox_add_space(struct space *space, struct lua_State *L) +{ + lua_pushnumber(L, space->no); + lbox_pushspace(L, space); + lua_settable(L, -3); +} + +void +lbox_space_init(struct lua_State *L) +{ + lua_getfield(L, LUA_GLOBALSINDEX, "box"); + lua_pushstring(L, "space"); + lua_newtable(L); + space_foreach((void *)lbox_add_space, L); /* fill box.space */ + lua_settable(L, -3); + lua_pop(L, 1); + assert(lua_gettop(L) == 0); +} diff --git a/src/memcached.m b/src/memcached.m index 166148745d9c6f355aa50fe26c1de3e66b7e2bfa..0c77fdecef937bd4234c282e26c6622515d71630 100644 --- a/src/memcached.m +++ b/src/memcached.m @@ -469,6 +469,7 @@ memcached_space_init() struct key_def *key_def = malloc(sizeof(struct key_def)); key_def->part_count = 1; key_def->is_unique = true; + key_def->type = HASH; key_def->parts = malloc(sizeof(struct key_part)); key_def->cmp_order = malloc(sizeof(u32)); diff --git a/src/tarantool.m b/src/tarantool.m index e04d82251f490b4b90118ad236146c42ead3c5a6..c0ee8387ccf07b49f2576c71e856c21e9ae4078a 100644 --- a/src/tarantool.m +++ b/src/tarantool.m @@ -860,8 +860,8 @@ main(int argc, char **argv) @try { tarantool_L = tarantool_lua_init(); mod_init(); - tarantool_lua_load_cfg(tarantool_L, &cfg); memcached_init(cfg.bind_ipaddr, cfg.memcached_port); + tarantool_lua_load_cfg(tarantool_L, &cfg); /* * init iproto before admin and after memcached: * recovery is finished on bind to the primary port, diff --git a/test/box/admin.test b/test/box/admin.test index b1877799ffc2bc744f81e69ee0a54690c9408a76..eb9f210869e20a0aea46a57d111b29da685e667b 100644 --- a/test/box/admin.test +++ b/test/box/admin.test @@ -25,4 +25,5 @@ exec admin "show fiber" exec admin "show slab" exec admin "show palloc" sys.stdout.clear_all_filters() + # vim: syntax=python diff --git a/test/box/lua.result b/test/box/lua.result index e57c46d84d83a338f3194d038f052c2da151955d..4e07b733394e67fba4f128c75fa68ca443c1924a 100644 --- a/test/box/lua.result +++ b/test/box/lua.result @@ -20,9 +20,10 @@ lua for n in pairs(box) do print(' - box.', n) end - box.replace - box.space - box.cfg + - box.on_reload_configuration - box.select_range - box.insert - - box.on_reload_configuration + - box.bless_space - box.counter - box.info - box.auto_increment @@ -401,8 +402,8 @@ lua for k,v in pairs(box.space[0]) do if type(v) ~= 'table' then print(' - ', k, --- - cardinality: -1 - estimated_rows: 0 - - enabled: true - n: 0 + - enabled: true ... reload configuration --- @@ -449,16 +450,15 @@ lua for k,v in pairs(box.space[0]) do if type(v) ~= 'table' then print(' - ', k, --- - cardinality: -1 - estimated_rows: 0 - - enabled: true - n: 0 + - enabled: true ... lua box.cfg.nosuchoption = 1 --- -error: '[string "box.cfg = {}..."]:52: Attempt to modify a read-only table' +error: '[string "box.cfg = {}..."]:43: Attempt to modify a read-only table' ... lua box.space[300] = 1 --- -error: '[string "box.cfg = {}..."]:52: Attempt to modify a read-only table' ... lua box.index.new('abc', 'cde') --- @@ -699,12 +699,11 @@ lua box.fiber.resume(f, 'hello', 'world') ... lua box.fiber.resume(f, 'wide') --- - - world - - wide +error: 'fiber.resume(): the fiber is dead' ... lua box.fiber.resume(f) --- - - true +error: 'fiber.resume(): the fiber is dead' ... lua function y() print('started') box.fiber.detach() while true do box.replace(0, 'test', os.time()) box.fiber.sleep(0.001) end end --- diff --git a/test/box/space.result b/test/box/space.result new file mode 100644 index 0000000000000000000000000000000000000000..4d48f37e129d6f7a4a64187a4f186a7952535470 --- /dev/null +++ b/test/box/space.result @@ -0,0 +1,17 @@ +lua type(box) +--- + - table +... +lua type(box.space) +--- + - table +... +lua box.cfg.memcached_space +--- + - 23 +... +lua for i, v in pairs(box.space[0].index[0].key_field[0]) do print(i, ': ', v) end +--- +type: NUM +fieldno: 0 +... diff --git a/test/box/space.test b/test/box/space.test new file mode 100644 index 0000000000000000000000000000000000000000..a421d2685268a19bfd5d8c34231f3bd7a7512afb --- /dev/null +++ b/test/box/space.test @@ -0,0 +1,5 @@ +# encoding: tarantool +exec admin "lua type(box)" +exec admin "lua type(box.space)" +exec admin "lua box.cfg.memcached_space" +exec admin "lua for i, v in pairs(box.space[0].index[0].key_field[0]) do print(i, ': ', v) end" diff --git a/test/run b/test/run deleted file mode 120000 index 68f68dd76759c0c540d91e2d612c5458f09a06d5..0000000000000000000000000000000000000000 --- a/test/run +++ /dev/null @@ -1 +0,0 @@ -./run.sh \ No newline at end of file diff --git a/test/run b/test/run new file mode 100755 index 0000000000000000000000000000000000000000..351474a9b40d24ae694e79c1b824330164d0140b --- /dev/null +++ b/test/run @@ -0,0 +1,13 @@ +#!/bin/sh + +/usr/bin/env python <<__EOB__ +import sys +if sys.hexversion < 0x02060000 or sys.hexversion >= 0x03000000: + sys.stderr.write("ERROR: test harness must use python >= 2.6 but not 3.x\n") + sys.exit(1) +else: + sys.exit(0) +__EOB__ + +[ $? -eq 0 ] && ./test-run.py $* + diff --git a/test/tarantool b/test/tarantool deleted file mode 120000 index eb4a53a7491315cdba3dd460a8b76de5e57f39d7..0000000000000000000000000000000000000000 --- a/test/tarantool +++ /dev/null @@ -1 +0,0 @@ -../client/tarantool/tarantool \ No newline at end of file