Skip to content

Commit

Permalink
readview: fix 'garbagecollector'
Browse files Browse the repository at this point in the history
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
  • Loading branch information
better0fdead authored and DifferentialOrange committed Oct 4, 2023
1 parent 416b880 commit 994d9dc
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 9 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased

### Fixed
* `crud.readview` resource cleanup on garbage collect (#379).

## [1.3.0] - 27-09-23

### Added
Expand Down
10 changes: 10 additions & 0 deletions crud/readview.lua
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,17 @@ end

function Readview_obj.create(vshard_router, opts)
local readview = {}

-- For tarantool lua (and lua 5.1) __gc metamethod only works for cdata types.
-- So in order to create a proper GC hook, we need to create cdata with
-- __gc call.
-- __gc call for this cdata will be a __gc call for our readview.
-- https://github.com/tarantool/tarantool/issues/5770
local proxy = newproxy(true)
getmetatable(proxy).__gc = function(_) Readview_obj.__gc(readview) end
readview[proxy] = true
setmetatable(readview, Readview_obj)

readview._name = opts.name
local results, err, err_uuid = vshard_router:map_callrw('_crud.readview_open_on_storage',
{readview._name}, {timeout = opts.timeout})
Expand Down
67 changes: 58 additions & 9 deletions test/integration/select_readview_test.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local fio = require('fio')
local fiber = require('fiber')

local t = require('luatest')

Expand Down Expand Up @@ -176,7 +177,7 @@ pgroup.test_gc_on_storage = function(g)
})
end

pgroup.test_close_gc_on_router = function(g)
pgroup.test_gc_rv_not_referenced_on_router = function(g)
local _, err = g.cluster.main_server.net_box:eval([[
local crud = require('crud')
local foo, err = crud.readview({name = 'foo'})
Expand All @@ -187,17 +188,65 @@ pgroup.test_close_gc_on_router = function(g)
collectgarbage("collect")
collectgarbage("collect")
]])
fiber.sleep(1)
t.assert_equals(err, nil)
local res = {}
helpers.call_on_storages(g.cluster, function(server, replicaset, res)
helpers.call_on_storages(g.cluster, function(server)
local instance_res = server.net_box:eval([[
return box.read_view.list()]])
res[replicaset.alias] = instance_res
end, res)
t.assert_equals(res, {["s-1"] = {}, ["s-2"] = {}})
table.insert(res, instance_res)
end, res)
t.assert_equals(res, {{}, {}, {}, {}})

end

pgroup.test_gc_rv_referenced_on_router = function(g)
helpers.insert_objects(g, 'customers', {
{
id = 1, name = "Elizabeth", last_name = "Jackson",
age = 12, city = "New York",
}, {
id = 2, name = "Mary", last_name = "Brown",
age = 46, city = "Los Angeles",
}, {
id = 3, name = "David", last_name = "Smith",
age = 33, city = "Los Angeles",
}, {
id = 4, name = "William", last_name = "White",
age = 81, city = "Chicago",
},
})

local _, err = g.cluster.main_server.net_box:eval([[
local crud = require('crud')
local foo, err = crud.readview({name = 'foo'})
if err ~= nil then
return nil, err
end
collectgarbage("collect")
collectgarbage("collect")
rawset(_G, 'foo', foo)
]])
fiber.sleep(1)
t.assert_equals(err, nil)
local obj, err = g.cluster.main_server.net_box:eval([[
local crud = require('crud')
local foo = rawget(_G, 'foo')
local result, err = foo:select('customers', nil, {fullscan = true})
foo:close()
return result, err
]])

t.assert_equals(err, nil)
t.assert_equals(obj.rows, {
{1, 477, "Elizabeth", "Jackson", 12, "New York"},
{2, 401, "Mary", "Brown", 46, "Los Angeles"},
{3, 2804, "David", "Smith", 33, "Los Angeles"},
{4, 1161, "William", "White", 81, "Chicago"},
})
end

pgroup.test_close = function(g)
local _, err = g.cluster.main_server.net_box:eval([[
local crud = require('crud')
Expand All @@ -209,12 +258,12 @@ pgroup.test_close = function(g)
]])
t.assert_equals(err, nil)
local res = {}
helpers.call_on_storages(g.cluster, function(server, replicaset, res)
helpers.call_on_storages(g.cluster, function(server)
local instance_res = server.net_box:eval([[
return box.read_view.list()]])
res[replicaset.alias] = instance_res
end, res)
t.assert_equals(res, {["s-1"] = {}, ["s-2"] = {}})
table.insert(res, instance_res)
end, res)
t.assert_equals(res, {{}, {}, {}, {}})

end

Expand Down

0 comments on commit 994d9dc

Please sign in to comment.