Allow to invoke insert/update/delete/select/replace
directly on box.space objects.

Add box.space[i]:len(), which returns the
number of tuples in the space.

Add rudimentary index object support.

Add tests.
---
 core/tarantool.m            |    1 +
 core/tarantool_lua.m        |    6 ++-
 mod/box/box.lua             |   27 +++++++++++++-
 mod/box/box.m               |    1 +
 mod/box/box_lua.m           |   84 +++++++++++++++++++++++++++++++++++++++---
 mod/box/index.h             |   18 +++++-----
 mod/box/index.m             |   17 ++++++++-
 mod/box/memcached.m         |    1 +
 test/box/lua.result         |  Bin 8970 -> 10149 bytes
 test/box/lua.test           |   19 ++++++++++
 test/box/reconfigure.result |   20 ++++++++++
 test/box/reconfigure.test   |    5 +++
 test/box/tarantool_good.cfg |    2 +
 13 files changed, 182 insertions(+), 19 deletions(-)

diff --git a/core/tarantool.m b/core/tarantool.m
index ae0daeb..2ec83aa 100644
--- a/core/tarantool.m
+++ b/core/tarantool.m
@@ -572,6 +572,7 @@ main(int argc, char **argv)
 
        tarantool_L = tarantool_lua_init();
        mod_init();
+       tarantool_lua_load_cfg(tarantool_L, &cfg);
        admin_init();
        replication_init();
 
diff --git a/core/tarantool_lua.m b/core/tarantool_lua.m
index b6e8b9c..d19390a 100644
--- a/core/tarantool_lua.m
+++ b/core/tarantool_lua.m
@@ -278,7 +278,6 @@ tarantool_lua_init()
        luaL_register(L, "box", boxlib);
        lua_pop(L, 1);
        lua_register(L, "print", lbox_print);
-       tarantool_lua_load_cfg(L, &cfg);
        L = mod_lua_init(L);
        lua_settop(L, 0); /* clear possible left-overs of init */
        return L;
@@ -402,7 +401,10 @@ void tarantool_lua_load_cfg(struct lua_State *L, struct 
tarantool_cfg *cfg)
 "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");
+"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);
diff --git a/mod/box/box.lua b/mod/box/box.lua
index 68c1e4b..dc19c27 100644
--- a/mod/box/box.lua
+++ b/mod/box/box.lua
@@ -36,7 +36,7 @@ function box.replace(namespace, ...)
                                  unpack(tuple))))
 end
 
--- insert a tuple (produces an error if a tuple already exists
+-- insert a tuple (produces an error if the tuple already exists)
 function box.insert(namespace, ...)
     tuple = {...}
     return select(2,
@@ -58,3 +58,28 @@ function box.update(namespace, key, format, ...)
                                   #ops/2, -- op count
                                   ...)))
 end
+
+function box.on_reload_configuration()
+    index_mt = {}
+    index_mt.len = function(index) return #index.idx end
+    index_mt.__newindex = function(table, index)
+        return error('Attempt to modify a read-only table') end
+    index_mt.__index = index_mt
+    space_mt = {}
+    space_mt.len = function(space) return space.index[0]:len() end
+    space_mt.__newindex = index_mt.__newindex
+    space_mt.select = function(space, ...) return box.select(space.n, ...) end
+    space_mt.insert = function(space, ...) return box.insert(space.n, ...) end
+    space_mt.update = function(space, ...) return box.update(space.n, ...) end
+    space_mt.replace = function(space, ...) return box.replace(space.n, ...) 
end
+    space_mt.delete = function(space, ...) return box.delete(space.n, ...) end
+    space_mt.__index = space_mt
+    for i, space in pairs(box.space) do
+        rawset(space, 'n', i)
+        setmetatable(space, space_mt)
+        for j, index in pairs(space.index) do
+            rawset(index, 'idx', box.index.new(i, j))
+            setmetatable(index, index_mt)
+        end
+    end
+end
diff --git a/mod/box/box.m b/mod/box/box.m
index 45ea593..5f5c0c6 100644
--- a/mod/box/box.m
+++ b/mod/box/box.m
@@ -992,6 +992,7 @@ space_init(void)
                        index->search_pattern = palloc(eter_pool, 
SIZEOF_TREE_INDEX_MEMBER(index));
                        index->unique = cfg_index->unique;
                        index->type = STR2ENUM(index_type, cfg_index->type);
+                       index->n = j;
                        index_init(index, &space[i], cfg_space->estimated_rows);
                }
 
diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m
index 8d60989..c1faca4 100644
--- a/mod/box/box_lua.m
+++ b/mod/box/box_lua.m
@@ -31,7 +31,7 @@
 #include "box_lua.h"
 #include "tarantool.h"
 #include "box.h"
-/* use a full path to avoid clashes with system lua */
+/* use a full path to avoid clashes with system Lua */
 #include "third_party/luajit/src/lua.h"
 #include "third_party/luajit/src/lauxlib.h"
 #include "third_party/luajit/src/lualib.h"
@@ -138,6 +138,68 @@ static const struct luaL_reg lbox_tuple_meta [] = {
 
 /* }}} */
 
+/**
+ * {{{ Lua box.index library: access to spaces and indexes
+ */
+
+static const char *indexlib_name = "box.index";
+
+static struct index *
+lua_checkindex(struct lua_State *L, int i)
+{
+       struct index **index = luaL_checkudata(L, i, indexlib_name);
+       assert(index != NULL);
+       return *index;
+}
+
+static int
+lbox_index_new(struct lua_State *L)
+{
+       int n = luaL_checkint(L, 1); /* get space id */
+       int idx = luaL_checkint(L, 2); /* get index id in */
+       /* locate the appropriate index */
+       if (n >= BOX_NAMESPACE_MAX || !space[n].enabled ||
+           idx >= BOX_INDEX_MAX || space[n].index[idx].key_cardinality == 0)
+               tnt_raise(LoggedError, :ER_NO_SUCH_INDEX, idx, n);
+       /* create a userdata object */
+       void **ptr = lua_newuserdata(L, sizeof(void *));
+       *ptr = &space[n].index[idx];
+       /* set userdata object metatable to indexlib */
+       luaL_getmetatable(L, indexlib_name);
+       lua_setmetatable(L, -2);
+       return 1;
+}
+
+static int
+lbox_index_tostring(struct lua_State *L)
+{
+       struct index *index = lua_checkindex(L, 1);
+       lua_pushfstring(L, "box.space[%d].index[%d]",
+                       index->space->n, index->n);
+       return 1;
+}
+
+static int
+lbox_index_len(struct lua_State *L)
+{
+       struct index *index = lua_checkindex(L, 1);
+       lua_pushinteger(L, index->size(index));
+       return 1;
+}
+
+static const struct luaL_reg lbox_index_meta[] = {
+       {"__tostring", lbox_index_tostring},
+       {"__len", lbox_index_len},
+       {NULL, NULL}
+};
+
+static const struct luaL_reg indexlib [] = {
+       {"new", lbox_index_new},
+       {NULL, NULL}
+};
+
+/* }}} */
+
 /** {{{ Lua I/O: facilities to intercept box output
  * and push into Lua stack and the opposite: append Lua types
  * to fiber IOV.
@@ -191,7 +253,6 @@ void iov_add_ret(struct lua_State *L, int index)
  * and return the number of return values first, and
  * then each return value as a tuple.
  */
-
 void iov_add_multret(struct lua_State *L)
 {
        int nargs = lua_gettop(L);
@@ -364,17 +425,24 @@ void box_lua_call(struct box_txn *txn 
__attribute__((unused)),
 struct lua_State *
 mod_lua_init(struct lua_State *L)
 {
-       /* box */
-       luaL_register(L, "box", boxlib);
        lua_atpanic(L, box_lua_panic);
-       /* box.tuple */
+       /* box, box.tuple */
+       luaL_register(L, "box", boxlib);
        luaL_newmetatable(L, tuplelib_name);
        lua_pushstring(L, tuplelib_name);
        lua_setfield(L, -2, "__metatable");
        luaL_register(L, NULL, lbox_tuple_meta);
        lua_pop(L, 2);
+       /* box.index */
+       luaL_newmetatable(L, indexlib_name);
+       lua_pushstring(L, indexlib_name);
+       lua_setfield(L, -2, "__metatable");
+       luaL_register(L, NULL, lbox_index_meta);
+       luaL_register(L, "box.index", indexlib);
+       lua_pop(L, 2);
        /* Load box.lua */
-       (void) luaL_dostring(L, &_binary_box_lua_start);
+       if (luaL_dostring(L, &_binary_box_lua_start))
+               panic("Error loading box.lua: %s", lua_tostring(L, -1));
        assert(lua_gettop(L) == 0);
        return L;
 }
@@ -383,3 +451,7 @@ void box_lua_init()
 {
        root_L = tarantool_L;
 }
+
+/**
+ * vim: foldmethod=marker
+ */
diff --git a/mod/box/index.h b/mod/box/index.h
index 7cb3aed..cef8588 100644
--- a/mod/box/index.h
+++ b/mod/box/index.h
@@ -76,6 +76,7 @@ struct index {
 
        bool unique;
 
+       size_t (*size)(struct index *index);
        struct box_tuple *(*find) (struct index * index, void *key);    /* only 
for unique lookups */
        struct box_tuple *(*find_by_tuple) (struct index * index, struct 
box_tuple * pattern);
        void (*remove) (struct index * index, struct box_tuple *);
@@ -95,15 +96,14 @@ struct index {
        struct space *space;
 
        struct {
-               struct {
-                       u32 fieldno;
-                       enum field_data_type type;
-               } *key_field;
-               u32 key_cardinality;
-
-               u32 *field_cmp_order;
-               u32 field_cmp_order_cnt;
-       };
+               u32 fieldno;
+               enum field_data_type type;
+       } *key_field;
+       u32 *field_cmp_order;
+       u32 field_cmp_order_cnt;
+       u32 key_cardinality;
+       /* relative offset of the index in the namespace */
+       u32 n;
 
        struct tree_index_member *search_pattern;
 
diff --git a/mod/box/index.m b/mod/box/index.m
index 9c9f37f..007f4ef 100644
--- a/mod/box/index.m
+++ b/mod/box/index.m
@@ -153,7 +153,11 @@ tree_index_member_compare(struct tree_index_member 
*member_a, struct tree_index_
        return 0;
 }
 
-
+static size_t
+index_tree_size(struct index *index)
+{
+       return index->idx.tree->size;
+}
 
 static struct box_tuple *
 index_find_hash_by_tuple(struct index *self, struct box_tuple *tuple)
@@ -165,6 +169,13 @@ index_find_hash_by_tuple(struct index *self, struct 
box_tuple *tuple)
        return self->find(self, key);
 }
 
+size_t
+index_hash_size(struct index *index)
+{
+       /* All kh_* structures have the same member layout */
+       return index->idx.hash->size;
+}
+
 static struct box_tuple *
 index_find_hash_num(struct index *self, void *key)
 {
@@ -573,6 +584,7 @@ index_hash_num(struct index *index, struct space *space, 
size_t estimated_rows)
 {
        index->type = HASH;
        index->space = space;
+       index->size = index_hash_size;
        index->find = index_find_hash_num;
        index->find_by_tuple = index_find_hash_by_tuple;
        index->remove = index_remove_hash_num;
@@ -593,6 +605,7 @@ index_hash_num64(struct index *index, struct space *space, 
size_t estimated_rows
 {
        index->type = HASH;
        index->space = space;
+       index->size = index_hash_size;
        index->find = index_find_hash_num64;
        index->find_by_tuple = index_find_hash_by_tuple;
        index->remove = index_remove_hash_num64;
@@ -613,6 +626,7 @@ index_hash_str(struct index *index, struct space *space, 
size_t estimated_rows)
 {
        index->type = HASH;
        index->space = space;
+       index->size = index_hash_size;
        index->find = index_find_hash_str;
        index->find_by_tuple = index_find_hash_by_tuple;
        index->remove = index_remove_hash_str;
@@ -634,6 +648,7 @@ index_tree(struct index *index, struct space *space,
 {
        index->type = TREE;
        index->space = space;
+       index->size = index_tree_size;
        index->find = index_find_tree;
        index->find_by_tuple = index_find_tree_by_tuple;
        index->remove = index_remove_tree_str;
diff --git a/mod/box/memcached.m b/mod/box/memcached.m
index 4be8722..0ac2752 100644
--- a/mod/box/memcached.m
+++ b/mod/box/memcached.m
@@ -453,6 +453,7 @@ memcached_space_init()
        memc_index->unique = true;
        memc_index->type = HASH;
        memc_index->enabled = true;
+       memc_index->n = 0;
        index_init(memc_index, memc_ns, 0);
 }
 
diff --git a/test/box/lua.result b/test/box/lua.result
index 
58c93387846484f9e6042aa9364b152ee56b7b53..389af7efd8d38919318fb6d5add7ee45cfb161f0
 100644
GIT binary patch
delta 947
zcma)*u}|AT6vmYnp~`9!q@p65&_0OhCBn9nbc@ubQae<FZdE0OknMX(EzDhXK8tif
zVPNXi==N@%JFs=`QvMM3Zj9JYz(+$6o8P<l{l0hap1-~S`SJUo*YUs$uxtQ0;Pasy
z^!i1>*}lMtdvrhGtQYnZ;mMG*@%ic^#Rw&iFSqI;qc|)y2}^+oMVv+B-_~NtVifZ1
zQ|WC@U96L5sUI@WkC1kuot8Vm&i<}d7Umv4*?3fX5hY&UW^U>-JZccn4~PvUph(n@
z$Cf%RStFJl`X~U00}Lcm8~R*AEJeurO;R>o*DV{fsJ0EArr|hF*+3z<=mOc{kXu2$
z17Qpldm%%b<{+ONwC|)XWSyyB)pw(!&z23XDSSHWoUq&4bMvC~Lu;&_y@f8;w5|W^
zW<YL8hxt8}XD&}Cub!IgE6192;*dQ`LshHrSwFkazN0bny7~6mt9DeSVyP3e)_kZz
zJ5{_=FRM%2Gm87IW(IR>fNIyYHm?EQ$vQTO#8_tQ^97@b!x0w|CF<Yvl@GTvdL!A~
mZZOG!dJ+rFn?VXo_lWpk(bjObo|sFU{8SCKWUejWCAb1yEfyO9

delta 159
zcmZ4L-{m&ph)HQdN@7VWFPDOXu0m3Ng<e5XesXGYF+w0YEgiwh%qvbUDw!<7sBK)D
zSCE*TjgU%7%}GTzs2C`XY%Wmo<~Bwr8Lrg4#H5_m6e|V8$=pgho7v?!S<u8L`z!qg
E08eu-_5c6?

diff --git a/test/box/lua.test b/test/box/lua.test
index 668c216..f159150 100644
--- a/test/box/lua.test
+++ b/test/box/lua.test
@@ -110,3 +110,22 @@ exec admin "lua for k,v in pairs(box.space[0]) do if 
type(v) ~= 'table' then pri
 # must be read-only
 exec admin "lua box.cfg.nosuchoption = 1"
 exec admin "lua box.space[300] = 1"
+
+exec admin "lua box.index.new('abc', 'cde')"
+exec admin "lua box.index.new(1, 2)"
+exec admin "lua box.index.new(0, 1)"
+exec admin "lua box.index.new(0, 0)"
+exec admin "lua #box.index.new(0,0)"
+exec admin "lua #box.space[0].index[0].idx"
+exec admin "lua box.insert(0, 'test')"
+exec admin "lua box.insert(0, 'abcd')"
+exec admin "lua #box.index.new(0,0)"
+exec admin "lua #box.space[0].index[0].idx"
+exec admin "lua box.delete(0, 'test')"
+exec admin "lua #box.index.new(0,0)"
+exec admin "lua box.delete(0, 'abcd')"
+exec admin "lua #box.space[0].index[0].idx"
+exec admin "lua #box.index.new(0,0)"
+exec admin "lua box.space[0]:insert('test', 'hello world')"
+exec admin "lua box.space[0]:update('test', '=p', 1, 'bye, world')"
+exec admin "lua box.space[0]:delete('test')"
diff --git a/test/box/reconfigure.result b/test/box/reconfigure.result
index 8c11829..71a03e4 100644
--- a/test/box/reconfigure.result
+++ b/test/box/reconfigure.result
@@ -1,3 +1,7 @@
+lua box.cfg.too_long_threshold
+---
+ - 0.5
+...
 reload configuration
 ---
 fail:
@@ -14,6 +18,10 @@ fail:
  - Could not accept read only 'space[0].index[0].key_field[0].fieldno' option
  - Could not accept read only 'space[0].index[0].key_field[0].type' option
 ...
+lua box.cfg.too_long_threshold
+---
+ - 0.5
+...
 reload configuration
 ---
 fail:
@@ -41,11 +49,19 @@ reload configuration
 ---
 ok
 ...
+lua box.cfg.too_long_threshold
+---
+ - 2
+...
 reload configuration
 ---
 fail:
  - gram_yyerror: syntax error, unexpected $end, expecting KEY_P or NULL_P or 
'[' at line 1
 ...
+lua box.cfg.too_long_threshold
+---
+ - 2
+...
 reload configuration
 ---
 fail:
@@ -55,6 +71,10 @@ reload configuration
 ---
 ok
 ...
+lua box.cfg.too_long_threshold
+---
+ - 0.5
+...
 #
 # A test case for http://bugs.launchpad.net/bugs/712447:
 # Valgrind reports use of not initialized memory after 'reload
diff --git a/test/box/reconfigure.test b/test/box/reconfigure.test
index f21546d..4ca5874 100644
--- a/test/box/reconfigure.test
+++ b/test/box/reconfigure.test
@@ -1,7 +1,9 @@
 # encoding: tarantool
 #
+exec admin "lua box.cfg.too_long_threshold"
 # bad1
 server.reconfigure("box/tarantool_bad1.cfg")
+exec admin "lua box.cfg.too_long_threshold"
 # bad2
 server.reconfigure("box/tarantool_bad2.cfg")
 # bad3
@@ -12,8 +14,10 @@ server.reconfigure("box/tarantool_bad4.cfg")
 server.reconfigure("box/tarantool_bad5.cfg")
 # good
 server.reconfigure("box/tarantool_good.cfg")
+exec admin "lua box.cfg.too_long_threshold"
 # empty
 server.reconfigure("box/tarantool_empty.cfg")
+exec admin "lua box.cfg.too_long_threshold"
 
 # no config
 server.reconfigure(None)
@@ -21,6 +25,7 @@ server.reconfigure(None)
 # cleanup
 # restore default
 server.reconfigure(self.suite_ini["config"])
+exec admin "lua box.cfg.too_long_threshold"
 
 print """#
 # A test case for http://bugs.launchpad.net/bugs/712447:
diff --git a/test/box/tarantool_good.cfg b/test/box/tarantool_good.cfg
index 0ec29f2..9826f7c 100644
--- a/test/box/tarantool_good.cfg
+++ b/test/box/tarantool_good.cfg
@@ -9,6 +9,8 @@ secondary_port = 33014
 admin_port = 33015
 
 rows_per_wal = 50
+# This is one of the few modifiable settings, change it
+too_long_threshold=2
 
 space[0].enabled = 1
 space[0].index[0].type = "HASH"
-- 
1.7.0.4


_______________________________________________
Mailing list: https://launchpad.net/~tarantool-developers
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~tarantool-developers
More help   : https://help.launchpad.net/ListHelp

Reply via email to