Skip to content

Commit

Permalink
box: move mkversion into a separate module
Browse files Browse the repository at this point in the history
This commit moves all code, related to working with versions and which
was used in box/lua/upgrade.lua, into a separate module and exports it
to Lua API as 'internal.version'

This is needed, as in the following commit we start to broadcast the
dd_version_id variable, which shows the version of schema, stored in
_schema['version']. This module allows us to write a trigger for
config module and avoid code duplication.

Needed for tarantool#8978

NO_DOC=internal
NO_TEST=<already tested>
NO_CHANGELOG=internal
  • Loading branch information
Serpentian committed Sep 27, 2023
1 parent db8b26b commit c1efb1b
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 59 deletions.
1 change: 1 addition & 0 deletions src/box/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ lua_source(lua_sources lua/console.lua console_lua)
lua_source(lua_sources lua/xlog.lua xlog_lua)
lua_source(lua_sources lua/key_def.lua key_def_lua)
lua_source(lua_sources lua/merger.lua merger_lua)
lua_source(lua_sources lua/mkversion.lua mkversion_lua)

# {{{ config
lua_source(lua_sources lua/config/applier/app.lua config_applier_app_lua)
Expand Down
2 changes: 2 additions & 0 deletions src/box/lua/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ extern char session_lua[],
feedback_daemon_lua[],
#endif
net_box_lua[],
mkversion_lua[],
upgrade_lua[],
console_lua[],
merger_lua[],
Expand Down Expand Up @@ -204,6 +205,7 @@ static const char *lua_sources[] = {
READ_VIEW_BOX_LUA_MODULES
SECURITY_BOX_LUA_MODULES
"box/xlog", "xlog", xlog_lua,
"box/mkversion", "internal.mkversion", mkversion_lua,
"box/upgrade", NULL, upgrade_lua,
"box/net_box", "net.box", net_box_lua,
"box/console", "console", console_lua,
Expand Down
69 changes: 69 additions & 0 deletions src/box/lua/mkversion.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
local bit = require('bit')
local ffi = require('ffi')

ffi.cdef([[ uint32_t box_dd_version_id(void); ]])
local builtin = ffi.C

local mkversion_mt = {
__tostring = function(self)
return string.format('%s.%s.%s', self.major, self.minor, self.patch)
end,
__eq = function(lhs, rhs)
return lhs.id == rhs.id
end,
__lt = function(lhs, rhs)
return lhs.id < rhs.id
end,
}

local function mkversion_new(major, minor, patch)
local self = setmetatable({}, mkversion_mt)
self.major = major
self.minor = minor
self.patch = patch
self.id = bit.bor(bit.lshift(bit.bor(bit.lshift(major, 8), minor), 8),
patch)
return self
end

-- Parse string with version in format 'A.B.C' to version object.
local function mkversion_from_string(version)
local major, minor, patch = version:match('^(%d+)%.(%d+)%.(%d+)$')
if major == nil then
error('version should be in format A.B.C')
end
return mkversion_new(tonumber(major), tonumber(minor), tonumber(patch))
end

local function mkversion_from_id(version_id)
local major = bit.band(bit.rshift(version_id, 16), 0xff)
local minor = bit.band(bit.rshift(version_id, 8), 0xff)
local patch = bit.band(version_id, 0xff)
return mkversion_new(major, minor, patch)
end

-- Schema version of the snapshot.
local function mkversion_get()
local version = builtin.box_dd_version_id()
return mkversion_from_id(version)
end

local function mkversion_from_tuple(tuple)
local major, minor, patch = tuple:unpack(2, 4)
patch = patch or 0
if major and minor and type(major) == 'number' and
type(minor) == 'number' and type(patch) == 'number' then
return mkversion_new(major, minor, patch)
end
return nil
end

return setmetatable({
new = mkversion_new,
get = mkversion_get,
from_id = mkversion_from_id,
from_tuple = mkversion_from_tuple,
from_string = mkversion_from_string,
}, {
__call = function(self, ...) return mkversion_new(...) end;
})
65 changes: 6 additions & 59 deletions src/box/lua/upgrade.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ local xlog = require('xlog')
local ffi = require('ffi')
local fun = require('fun')
local utils = require('internal.utils')
local mkversion = require('internal.mkversion')

ffi.cdef([[
uint32_t box_dd_version_id(void);
void box_init_latest_dd_version_id(uint32_t version_id);
bool box_schema_needs_upgrade(void);
int box_schema_upgrade_begin(void);
Expand Down Expand Up @@ -40,40 +40,6 @@ local function setmap(tab)
return setmetatable(tab, { __serialize = 'map' })
end

local mkversion = {}
mkversion.__index = mkversion
setmetatable(mkversion, {__call = function(c, ...) return c.new(...) end})

function mkversion.new(major, minor, patch)
local self = setmetatable({}, mkversion)
self.major = major
self.minor = minor
self.patch = patch
self.id = bit.bor(bit.lshift(bit.bor(bit.lshift(major, 8), minor), 8), patch)
return self
end

-- Parse string with version in format 'A.B.C' to version object.
function mkversion.parse(version)
local major, minor, patch = version:match('^(%d+)%.(%d+)%.(%d+)$')
if major == nil then
error('version should be in format A.B.C')
end
return mkversion.new(tonumber(major), tonumber(minor), tonumber(patch))
end

function mkversion.__tostring(self)
return string.format('%s.%s.%s', self.major, self.minor, self.patch)
end

function mkversion.__eq(lhs, rhs)
return lhs.id == rhs.id
end

function mkversion.__lt(lhs, rhs)
return lhs.id < rhs.id
end

-- space:truncate() doesn't work with disabled triggers on __index
local function truncate(space)
local pk = space.index[0]
Expand Down Expand Up @@ -138,16 +104,6 @@ local function reset_system_formats()
end)
end

local function version_from_tuple(tuple)
local major, minor, patch = tuple:unpack(2, 4)
patch = patch or 0
if major and minor and type(major) == 'number' and
type(minor) == 'number' and type(patch) == 'number' then
return mkversion(major, minor, patch)
end
return nil
end

-- Get schema version, stored in _schema system space, by reading the latest
-- snapshot file from the snap_dir. Useful to define schema_version before
-- recovering the snapshot, because some schema versions are too old and cannot
Expand All @@ -167,7 +123,7 @@ local function get_snapshot_version(snap_dir)
if sid == box.schema.SCHEMA_ID then
local tuple = row.BODY.tuple
if tuple and tuple[1] == 'version' then
version = version_from_tuple(tuple)
version = mkversion.from_tuple(tuple)
if not version then
log.error("Corrupted version tuple in space '_schema' "..
"in snapshot '%s': %s ", snap, tuple)
Expand Down Expand Up @@ -1468,15 +1424,6 @@ local handlers = {
}
builtin.box_init_latest_dd_version_id(handlers[#handlers].version.id)

-- Schema version of the snapshot.
local function get_version()
local version = builtin.box_dd_version_id()
local major = bit.band(bit.rshift(version, 16), 0xff)
local minor = bit.band(bit.rshift(version, 8), 0xff)
local patch = bit.band(version, 0xff)
return mkversion(major, minor, patch)
end

local trig_oldest_version = nil

-- Some schema changes before version 1.7.7 make it impossible to recover from
Expand Down Expand Up @@ -1516,7 +1463,7 @@ local recovery_triggers = {
-- snapshot), the triggers helping recover the old schema should be removed.
local function schema_trig_last(_, tuple)
if tuple and tuple[1] == 'version' then
local version = version_from_tuple(tuple)
local version = mkversion.from_tuple(tuple)
if version then
log.info("Recovery trigger: recovered schema version %s. "..
"Removing outdated recovery triggers.", version)
Expand Down Expand Up @@ -1594,7 +1541,7 @@ local function run_upgrade(func, ...)
end

local function upgrade()
local version = get_version()
local version = mkversion.get()
run_upgrade(upgrade_from, version)
end

Expand Down Expand Up @@ -2110,13 +2057,13 @@ local downgrade_versions = {
-- If any issue is found then downgrade is failed and no any changes are done.
local function downgrade_impl(version_str, dry_run)
utils.check_param(version_str, 'version_str', 'string')
local version = mkversion.parse(version_str)
local version = mkversion.from_string(version_str)
if fun.index(version_str, downgrade_versions) == nil then
error("Downgrade is only possible to version listed in" ..
" box.schema.downgrade_versions().")
end

local schema_version_cur = get_version()
local schema_version_cur = mkversion.get()
local schema_version_dst = app2schema_version(version)
if schema_version_cur < schema_version_dst then
local err = "Cannot downgrade as current schema version %s is older" ..
Expand Down

0 comments on commit c1efb1b

Please sign in to comment.