[tarantool-patches] [PATCH 07/10] swim: pairs() function to iterate over member table

Vladislav Shpilevoy v.shpilevoy at tarantool.org
Wed May 15 22:36:44 MSK 2019


The last patch in the series of Lua bindings exposure exposes
iterators API to be able to iterate over a member table in a
'for' loop like it would just a Lua table.

Part of #3234
---
 src/lua/swim.lua        | 34 ++++++++++++++++++
 test/swim/swim.result   | 78 +++++++++++++++++++++++++++++++++++++++++
 test/swim/swim.test.lua | 15 ++++++++
 3 files changed, 127 insertions(+)

diff --git a/src/lua/swim.lua b/src/lua/swim.lua
index e40edda18..6e55ffeba 100644
--- a/src/lua/swim.lua
+++ b/src/lua/swim.lua
@@ -557,6 +557,39 @@ local function swim_set_payload(s, payload)
     return true
 end
 
+--
+-- Lua pairs() or similar function should return 3 values:
+-- iterator function, iterator object, a key before first. This is
+-- iterator function. On each iteration it returns UUID as a key,
+-- member object as a value.
+--
+local function swim_pairs_next(ctx)
+    if ctx.swim.ptr == nil then
+        return swim_error_deleted()
+    end
+    local iterator = ctx.iterator
+    local m = capi.swim_iterator_next(iterator)
+    if m ~= nil then
+        m = swim_member_wrap(m)
+        return m:uuid(), m
+    end
+    capi.swim_iterator_close(ffi.gc(iterator, nil))
+    ctx.iterator = nil
+end
+
+--
+-- Pairs() to use in 'for' cycles.
+--
+local function swim_pairs(s)
+    local ptr = swim_check_instance(s, 'swim:pairs')
+    local iterator = capi.swim_iterator_open(ptr)
+    if iterator == nil then
+        return nil, box.error.last()
+    end
+    ffi.gc(iterator, capi.swim_iterator_close)
+    return swim_pairs_next, {swim = s, iterator = iterator}, nil
+end
+
 --
 -- Normal metatable of a configured SWIM instance.
 --
@@ -574,6 +607,7 @@ local swim_mt = {
         member_by_uuid = swim_member_by_uuid,
         set_payload_raw = swim_set_payload_raw,
         set_payload = swim_set_payload,
+        pairs = swim_pairs,
     },
     __serialize = swim_serialize
 }
diff --git a/test/swim/swim.result b/test/swim/swim.result
index 4cf5c7f90..d0838af48 100644
--- a/test/swim/swim.result
+++ b/test/swim/swim.result
@@ -728,6 +728,84 @@ s1:delete()
 s2:delete()
 ---
 ...
+--
+-- Iterators.
+--
+function iterate() local t = {} for k, v in s:pairs() do table.insert(t, {k, v}) end return t end
+---
+...
+s = swim.new()
+---
+...
+iterate()
+---
+- error: '[string "function iterate() local t = {} for k, v in s..."]:1: attempt to
+    call method ''pairs'' (a nil value)'
+...
+s:cfg({uuid = uuid(1), uri = uri(), gc_mode = 'off'})
+---
+- true
+...
+s.pairs()
+---
+- error: 'builtin/swim.lua:<line>: swim:pairs: first argument is not a SWIM instance'
+...
+iterate()
+---
+- - - 00000000-0000-1000-8000-000000000001
+    - uri: 127.0.0.1:<port>
+      status: alive
+      incarnation: 1
+      uuid: 00000000-0000-1000-8000-000000000001
+      payload_size: 0
+...
+s:add_member({uuid = uuid(2), uri = uri()})
+---
+- true
+...
+iterate()
+---
+- - - 00000000-0000-1000-8000-000000000002
+    - uri: 127.0.0.1:<port>
+      status: alive
+      incarnation: 0
+      uuid: 00000000-0000-1000-8000-000000000002
+      payload_size: 0
+  - - 00000000-0000-1000-8000-000000000001
+    - uri: 127.0.0.1:<port>
+      status: alive
+      incarnation: 1
+      uuid: 00000000-0000-1000-8000-000000000001
+      payload_size: 0
+...
+s:add_member({uuid = uuid(3), uri = uri()})
+---
+- true
+...
+iterate()
+---
+- - - 00000000-0000-1000-8000-000000000001
+    - uri: 127.0.0.1:<port>
+      status: alive
+      incarnation: 1
+      uuid: 00000000-0000-1000-8000-000000000001
+      payload_size: 0
+  - - 00000000-0000-1000-8000-000000000003
+    - uri: 127.0.0.1:<port>
+      status: alive
+      incarnation: 0
+      uuid: 00000000-0000-1000-8000-000000000003
+      payload_size: 0
+  - - 00000000-0000-1000-8000-000000000002
+    - uri: 127.0.0.1:<port>
+      status: alive
+      incarnation: 0
+      uuid: 00000000-0000-1000-8000-000000000002
+      payload_size: 0
+...
+s:delete()
+---
+...
 test_run:cmd("clear filter")
 ---
 - true
diff --git a/test/swim/swim.test.lua b/test/swim/swim.test.lua
index 8e7b426fe..9f237a540 100644
--- a/test/swim/swim.test.lua
+++ b/test/swim/swim.test.lua
@@ -244,4 +244,19 @@ s1_view:incarnation()
 s1:delete()
 s2:delete()
 
+--
+-- Iterators.
+--
+function iterate() local t = {} for k, v in s:pairs() do table.insert(t, {k, v}) end return t end
+s = swim.new()
+iterate()
+s:cfg({uuid = uuid(1), uri = uri(), gc_mode = 'off'})
+s.pairs()
+iterate()
+s:add_member({uuid = uuid(2), uri = uri()})
+iterate()
+s:add_member({uuid = uuid(3), uri = uri()})
+iterate()
+s:delete()
+
 test_run:cmd("clear filter")
-- 
2.20.1 (Apple Git-117)





More information about the Tarantool-patches mailing list