Skip to content

Commit 1b5a9ca

Browse files
committed
readview: fix 'garbagecollector'
Added workaround for 'garbagecollector' of readview because for tarantool lua (and lua 5.1) '__gc' metamethod only works for cdata types. See tarantool/tarantool#5770
1 parent 416b880 commit 1b5a9ca

File tree

3 files changed

+73
-9
lines changed

3 files changed

+73
-9
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## Unreleased
9+
10+
### Fixed
11+
* `garbagecollector` not working for crud.readview (#379).
12+
813
## [1.3.0] - 27-09-23
914

1015
### Added

crud/readview.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,17 @@ end
285285

286286
function Readview_obj.create(vshard_router, opts)
287287
local readview = {}
288+
289+
-- For tarantool lua (and lua 5.1) __gc metamethod only works for cdata types.
290+
-- So in order to create a proper GC hook, we need to create cdata with
291+
-- __gc call.
292+
-- __gc call for this cdata will be a __gc call for our readview.
293+
-- https://github.com/tarantool/tarantool/issues/5770
294+
local proxy = newproxy(true)
295+
getmetatable(proxy).__gc = function(_) Readview_obj.__gc(readview) end
296+
readview[proxy] = true
288297
setmetatable(readview, Readview_obj)
298+
289299
readview._name = opts.name
290300
local results, err, err_uuid = vshard_router:map_callrw('_crud.readview_open_on_storage',
291301
{readview._name}, {timeout = opts.timeout})

test/integration/select_readview_test.lua

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local fio = require('fio')
2+
local fiber = require('fiber')
23

34
local t = require('luatest')
45

@@ -176,7 +177,7 @@ pgroup.test_gc_on_storage = function(g)
176177
})
177178
end
178179

179-
pgroup.test_close_gc_on_router = function(g)
180+
pgroup.test_gc_rv_not_referenced_on_router = function(g)
180181
local _, err = g.cluster.main_server.net_box:eval([[
181182
local crud = require('crud')
182183
local foo, err = crud.readview({name = 'foo'})
@@ -187,17 +188,65 @@ pgroup.test_close_gc_on_router = function(g)
187188
collectgarbage("collect")
188189
collectgarbage("collect")
189190
]])
191+
fiber.sleep(1)
190192
t.assert_equals(err, nil)
191193
local res = {}
192-
helpers.call_on_storages(g.cluster, function(server, replicaset, res)
194+
helpers.call_on_storages(g.cluster, function(server)
193195
local instance_res = server.net_box:eval([[
194196
return box.read_view.list()]])
195-
res[replicaset.alias] = instance_res
196-
end, res)
197-
t.assert_equals(res, {["s-1"] = {}, ["s-2"] = {}})
197+
table.insert(res, instance_res)
198+
end, res)
199+
t.assert_equals(res, {{}, {}, {}, {}})
198200

199201
end
200202

203+
pgroup.test_gc_rv_referenced_on_router = function(g)
204+
helpers.insert_objects(g, 'customers', {
205+
{
206+
id = 1, name = "Elizabeth", last_name = "Jackson",
207+
age = 12, city = "New York",
208+
}, {
209+
id = 2, name = "Mary", last_name = "Brown",
210+
age = 46, city = "Los Angeles",
211+
}, {
212+
id = 3, name = "David", last_name = "Smith",
213+
age = 33, city = "Los Angeles",
214+
}, {
215+
id = 4, name = "William", last_name = "White",
216+
age = 81, city = "Chicago",
217+
},
218+
})
219+
220+
local _, err = g.cluster.main_server.net_box:eval([[
221+
local crud = require('crud')
222+
local foo, err = crud.readview({name = 'foo'})
223+
if err ~= nil then
224+
return nil, err
225+
end
226+
collectgarbage("collect")
227+
collectgarbage("collect")
228+
rawset(_G, 'foo', foo)
229+
]])
230+
fiber.sleep(1)
231+
t.assert_equals(err, nil)
232+
local obj, err = g.cluster.main_server.net_box:eval([[
233+
local crud = require('crud')
234+
local foo = rawget(_G, 'foo')
235+
local result, err = foo:select('customers', nil, {fullscan = true})
236+
237+
foo:close()
238+
return result, err
239+
]])
240+
241+
t.assert_equals(err, nil)
242+
t.assert_equals(obj.rows, {
243+
{1, 477, "Elizabeth", "Jackson", 12, "New York"},
244+
{2, 401, "Mary", "Brown", 46, "Los Angeles"},
245+
{3, 2804, "David", "Smith", 33, "Los Angeles"},
246+
{4, 1161, "William", "White", 81, "Chicago"},
247+
})
248+
end
249+
201250
pgroup.test_close = function(g)
202251
local _, err = g.cluster.main_server.net_box:eval([[
203252
local crud = require('crud')
@@ -209,12 +258,12 @@ pgroup.test_close = function(g)
209258
]])
210259
t.assert_equals(err, nil)
211260
local res = {}
212-
helpers.call_on_storages(g.cluster, function(server, replicaset, res)
261+
helpers.call_on_storages(g.cluster, function(server)
213262
local instance_res = server.net_box:eval([[
214263
return box.read_view.list()]])
215-
res[replicaset.alias] = instance_res
216-
end, res)
217-
t.assert_equals(res, {["s-1"] = {}, ["s-2"] = {}})
264+
table.insert(res, instance_res)
265+
end, res)
266+
t.assert_equals(res, {{}, {}, {}, {}})
218267

219268
end
220269

0 commit comments

Comments
 (0)