Skip to content

Commit

Permalink
net.box: add info about sequence to remote space object
Browse files Browse the repository at this point in the history
A remote space object presented by a net.box connection mimics the API
of a local space object presented by box.space. Currently, it misses
information about sequences. Let's add it.

Note, we have to handle the case when the recently introduced
_vspace_sequence system space view is missing on the remote host.
To check that this works correctly, we reuse the 2.10.4 test data
created by commit 1c33484 ("box: add auth_history and
last_modified fields to _user space"). We also add the 'gen.lua'
that can be used to regenerated the data.

Closes tarantool#7858

NO_DOC=bug fix
  • Loading branch information
locker committed Jan 13, 2023
1 parent 06ee113 commit 457b293
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 19 deletions.
4 changes: 4 additions & 0 deletions changelogs/unreleased/gh-7858-net-box-space-sequence.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
## bugfix/core

* Added information about the sequence used by a remote space to net.box
connection (gh-7858).
37 changes: 25 additions & 12 deletions src/box/lua/net_box.c
Original file line number Diff line number Diff line change
Expand Up @@ -2685,8 +2685,8 @@ netbox_transport_fetch_schema(struct netbox_transport *transport,
transport->state = NETBOX_FETCH_SCHEMA;
netbox_transport_on_state_change(transport, L);
uint32_t peer_version_id = transport->greeting.version_id;
/* _vcollation view was added in 2.2.0-389-g3e3ef182f */
bool peer_has_vcollation = peer_version_id >= version_id(2, 2, 1);
bool peer_has_vspace_sequence = peer_version_id >= version_id(2, 10, 5);
restart:
lua_newtable(L);
int schema_table_idx = lua_gettop(L);
Expand All @@ -2700,30 +2700,38 @@ netbox_transport_fetch_schema(struct netbox_transport *transport,
if (peer_has_vcollation)
netbox_encode_select_all(L, &transport->send_buf,
vcollation_sync, BOX_VCOLLATION_ID);
uint64_t vspace_sequence_sync = transport->next_sync++;
if (peer_has_vspace_sequence)
netbox_encode_select_all(L, &transport->send_buf,
vspace_sequence_sync,
BOX_VSPACE_SEQUENCE_ID);
bool got_vspace = false;
bool got_vindex = false;
bool got_vcollation = false;
bool got_vspace_sequence = false;
schema_version = 0;
do {
struct xrow_header hdr;
if (netbox_transport_send_and_recv(transport, &hdr) != 0)
luaT_error(L);
if (hdr.sync != vspace_sync &&
hdr.sync != vindex_sync &&
hdr.sync != vcollation_sync) {
hdr.sync != vcollation_sync &&
hdr.sync != vspace_sequence_sync) {
netbox_transport_dispatch_response(transport, L, &hdr);
continue;
}
if (iproto_type_is_error(hdr.type)) {
uint32_t errcode = hdr.type & (IPROTO_TYPE_ERROR - 1);
if (errcode == ER_NO_SUCH_SPACE &&
hdr.sync == vcollation_sync) {
/*
* No _vcollation space
* (server has old schema version).
*/
peer_has_vcollation = false;
continue;
if (errcode == ER_NO_SUCH_SPACE) {
/* Server may have old dd version. */
if (hdr.sync == vcollation_sync) {
peer_has_vcollation = false;
continue;
} else if (hdr.sync == vspace_sequence_sync) {
peer_has_vspace_sequence = false;
continue;
}
}
xrow_decode_error(&hdr);
luaT_error(L);
Expand All @@ -2750,22 +2758,27 @@ netbox_transport_fetch_schema(struct netbox_transport *transport,
} else if (hdr.sync == vcollation_sync) {
key = BOX_VCOLLATION_ID;
got_vcollation = true;
} else if (hdr.sync == vspace_sequence_sync) {
key = BOX_VSPACE_SEQUENCE_ID;
got_vspace_sequence = true;
} else {
unreachable();
}
netbox_decode_table(L, &data, data_end, /*return_raw=*/false,
tuple_format_runtime);
lua_rawseti(L, schema_table_idx, key);
} while (!(got_vspace && got_vindex &&
(got_vcollation || !peer_has_vcollation)));
(got_vcollation || !peer_has_vcollation) &&
(got_vspace_sequence || !peer_has_vspace_sequence)));
/* Invoke the 'did_fetch_schema' callback. */
lua_rawgeti(L, LUA_REGISTRYINDEX, transport->opts.callback_ref);
lua_pushliteral(L, "did_fetch_schema");
lua_pushinteger(L, schema_version);
lua_rawgeti(L, schema_table_idx, BOX_VSPACE_ID);
lua_rawgeti(L, schema_table_idx, BOX_VINDEX_ID);
lua_rawgeti(L, schema_table_idx, BOX_VCOLLATION_ID);
lua_call(L, 5, 0);
lua_rawgeti(L, schema_table_idx, BOX_VSPACE_SEQUENCE_ID);
lua_call(L, 6, 0);
/* Pop the schema table. */
lua_pop(L, 1);
return schema_version;
Expand Down
20 changes: 19 additions & 1 deletion src/box/lua/net_box.lua
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ function remote_methods:wait_state(state, timeout)
end

function remote_methods:_install_schema(schema_version, spaces, indices,
collations)
collations, space_sequences)
local sl, space_mt, index_mt = {}, self._space_mt, self._index_mt
for _, space in pairs(spaces) do
local name = space[3]
Expand Down Expand Up @@ -977,6 +977,13 @@ function remote_methods:_install_schema(schema_version, spaces, indices,
sl[name] = s
end

local seql = {}
if space_sequences ~= nil then
for _, seq in ipairs(space_sequences) do
seql[seq[1]] = seq
end
end

for _, index in pairs(indices) do
local idx = {
space = index[1],
Expand Down Expand Up @@ -1033,6 +1040,17 @@ function remote_methods:_install_schema(schema_version, spaces, indices,
idx.unique = not not index[OPTS].unique
end

if idx.id == 0 then
local seq = seql[idx.space]
if seq ~= nil then
idx.sequence_id = seq[2]
idx.sequence_fieldno = seq[4] + 1
if seq[5] ~= '' then
idx.sequence_path = seq[5]
end
end
end

if sl[idx.space] ~= nil then
sl[idx.space].index[idx.id] = idx
sl[idx.space].index[idx.name] = idx
Expand Down
114 changes: 114 additions & 0 deletions test/box-luatest/gh_7858_net_box_space_sequence_test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
local server = require('luatest.server')
local t = require('luatest')

local g = t.group('gh_7858_net_box_space_sequence')

g.before_all(function(cg)
cg.server = server:new({alias = 'default'})
cg.server:start()
end)

g.after_all(function(cg)
cg.server:drop()
end)

g.after_test('test_net_box_space_sequence', function(cg)
cg.server:exec(function()
if box.space.test1 ~= nil then
box.space.test1:drop()
end
if box.space.test2 ~= nil then
box.space.test2:drop()
end
if box.space.test3 ~= nil then
box.space.test3:drop()
end
if box.sequence.test ~= nil then
box.sequence.test:drop()
end
end)
end)

g.test_net_box_space_sequence = function(cg)
cg.server:exec(function()
local t = require('luatest')
local net = require('net.box')
box.schema.sequence.create('test')
box.schema.create_space('test1')
box.space.test1:create_index('pk')
box.space.test1:create_index('sk', {parts = {2, 'unsigned'}})
box.schema.create_space('test2')
box.space.test2:create_index('pk', {sequence = true})
box.space.test2:create_index('sk', {parts = {2, 'unsigned'}})
box.schema.create_space('test3')
box.space.test3:create_index('pk', {
parts = {{'[2].foo.bar', 'unsigned'}},
sequence = box.sequence.test.id,
})
box.space.test3:create_index('sk', {parts = {1, 'unsigned'}})
local conn = net.connect(box.cfg.listen)
t.assert_equals(conn.space.test1.index.pk.sequence_id, nil)
t.assert_equals(conn.space.test1.index.pk.sequence_fieldno, nil)
t.assert_equals(conn.space.test1.index.pk.sequence_path, nil)
t.assert_equals(conn.space.test1.index.sk.sequence_id, nil)
t.assert_equals(conn.space.test1.index.sk.sequence_fieldno, nil)
t.assert_equals(conn.space.test1.index.sk.sequence_path, nil)
t.assert_equals(conn.space.test2.index.pk.sequence_id,
box.sequence.test2_seq.id)
t.assert_equals(conn.space.test2.index.pk.sequence_fieldno, 1)
t.assert_equals(conn.space.test2.index.pk.sequence_path, nil)
t.assert_equals(conn.space.test2.index.sk.sequence_id, nil)
t.assert_equals(conn.space.test2.index.sk.sequence_fieldno, nil)
t.assert_equals(conn.space.test2.index.sk.sequence_path, nil)
t.assert_equals(conn.space.test3.index.pk.sequence_id,
box.sequence.test.id)
t.assert_equals(conn.space.test3.index.pk.sequence_fieldno, 2)
t.assert_equals(conn.space.test3.index.pk.sequence_path, '.foo.bar')
t.assert_equals(conn.space.test3.index.sk.sequence_id, nil)
t.assert_equals(conn.space.test3.index.sk.sequence_fieldno, nil)
t.assert_equals(conn.space.test3.index.sk.sequence_path, nil)
conn:close()
end)
end

local g_old_schema = t.group('gh_7858_net_box_space_sequence.old_schema')

g_old_schema.before_test('test_net_box_space_sequence', function(cg)
t.tarantool.skip_if_not_debug()
cg.server = server:new({
alias = 'default',
datadir = 'test/box-luatest/upgrade/2.10.4',
env = {ERRINJ_AUTO_UPGRADE = 'true'},
})
cg.server:start()
end)

g_old_schema.after_test('test_net_box_space_sequence', function(cg)
cg.server:drop()
end)

g_old_schema.test_net_box_space_sequence = function(cg)
cg.server:exec(function()
local t = require('luatest')
local net = require('net.box')
t.assert_not_equals(box.space.gh_7858, nil)
t.assert_not_equals(box.sequence.gh_7858_seq, nil)
t.assert_equals(box.space.gh_7858.index.pk.sequence_id,
box.sequence.gh_7858_seq.id)
t.assert_equals(box.space.gh_7858.index.pk.sequence_fieldno, 2)
t.assert_equals(box.space.gh_7858.index.pk.sequence_path, '[3]')
local conn = net.connect(box.cfg.listen)
t.assert_equals(conn.error, nil)
t.assert_not_equals(conn.space.gh_7858, nil)
t.assert_equals(conn.space.gh_7858.index.pk.sequence_id, nil)
t.assert_equals(conn.space.gh_7858.index.pk.sequence_fieldno, nil)
t.assert_equals(conn.space.gh_7858.index.pk.sequence_path, nil)
box.schema.upgrade()
t.assert_equals(conn:ping(), true)
t.assert_equals(conn.space.gh_7858.index.pk.sequence_id,
box.sequence.gh_7858_seq.id)
t.assert_equals(conn.space.gh_7858.index.pk.sequence_fieldno, 2)
t.assert_equals(conn.space.gh_7858.index.pk.sequence_path, '[3]')
conn:close()
end)
end
Binary file not shown.
Binary file not shown.
15 changes: 15 additions & 0 deletions test/box-luatest/upgrade/2.10.4/gen.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
box.cfg{}

box.schema.user.create('eve')
box.schema.user.create('bob', {password = 'secret'})
box.schema.role.create('test')

box.schema.create_space('gh_7858')
box.space.gh_7858:create_index('pk', {
parts = {{'[2][3]', 'unsigned'}},
sequence = true,
})

box.snapshot()

os.exit(0)
5 changes: 1 addition & 4 deletions test/box/net.box_iproto_transactions_over_streams.result
Original file line number Diff line number Diff line change
Expand Up @@ -219,16 +219,13 @@ IPROTO_AUTH = 7
IPROTO_STREAM_ID = 0x0a
---
...
next_request_id = 10
---
...
test_run:cmd("setopt delimiter ';'")
---
- true
...
header = msgpack.encode({
[IPROTO_REQUEST_TYPE] = IPROTO_AUTH,
[IPROTO_SYNC] = next_request_id,
[IPROTO_SYNC] = conn:_next_sync(),
[IPROTO_STREAM_ID] = 1,
});
---
Expand Down
3 changes: 1 addition & 2 deletions test/box/net.box_iproto_transactions_over_streams.test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,10 @@ IPROTO_REQUEST_TYPE = 0x00
IPROTO_SYNC = 0x01
IPROTO_AUTH = 7
IPROTO_STREAM_ID = 0x0a
next_request_id = 10
test_run:cmd("setopt delimiter ';'")
header = msgpack.encode({
[IPROTO_REQUEST_TYPE] = IPROTO_AUTH,
[IPROTO_SYNC] = next_request_id,
[IPROTO_SYNC] = conn:_next_sync(),
[IPROTO_STREAM_ID] = 1,
});
body = msgpack.encode({nil});
Expand Down

0 comments on commit 457b293

Please sign in to comment.