<HTML><BODY><p style='margin-top: 0px;' dir="ltr">Thanks for fixes. LGTM. </p>
понедельник, 16 августа 2021г., 19:32 +03:00 от Serge Petrenko <a href="mailto:sergepetrenko@tarantool.org">sergepetrenko@tarantool.org</a>:<br><br><blockquote id="mail-app-auto-quote" cite="16291315490771329628" style="border-left:1px solid #005FF9; margin:0px 0px 0px 10px; padding:0px 0px 0px 10px;">






<div class="js-helper js-readmsg-msg">
        <style type="text/css"></style>
        <div >
                <base target="_self" href="https://e.mail.ru/" />
                
            <div id="style_16291315490771329628_BODY"><br>
<br>
16.08.2021 16:18, Бабин Олег пишет:<br>
                                 > Thanks for your patch. LGTM but consider several nits below.<br>
><br>
      <br>
Thanks for the review! Please, find my answers and incremental diff below.<br>
><br>
>     Пятница, 13 августа 2021, 2:35 +03:00 от Serge Petrenko via<br>
>     Tarantool-patches <<a href="mailto:tarantool-patches@dev.tarantool.org">tarantool-patches@dev.tarantool.org</a>>:<br>
>     Direct upgrade support from pre-1.7.5 versions was removed in commit<br>
>     7d3b80e78206c479cab75b4893629cfa1932252e<br>
>     (Forbid upgrade from Tarantool < 1.7.5 and refactor upgrade.lua)<br>
>     The reason for that was the mandatory space format checks introduced<br>
>     back then. With these space format checks, old schema couldn't be<br>
>     recovered on new Tarantool versions, because newer versions had<br>
>     different system space formats. So old schema couldn't be upgraded<br>
>     because it couldn't even be recovered.<br>
><br>
>     Actually this was rather inconvenient. One had to perform an extra<br>
>     upgrade step when upgrading from, say, 1.6 to 2.x: instead of<br>
>     performing a direct upgrade one had to do 1.6 -> 1.10 -> 2.x upgrade<br>
>     which takes twice the time.<br>
><br>
>     Make it possible to boot from snapshots coming from Tarantool version<br>
>     1.6.8 and above.<br>
><br>
>     In order to do so, introduce before_replace triggers on system spaces,<br>
>     which work during snapshot/xlog recovery. The triggers will set tuple<br>
>     formats to the ones supported by current Tarantool (2.x). This way the<br>
>     recovered data will have the correct format for a usual schema<br>
>     upgrade.<br>
><br>
>     Also add upgrade_to_1_7_5() handler, which finishes transformation of<br>
>     old schema to 1.7.5. The handler is fired together with other<br>
>     box.schema.upgrade() handlers, so there's no user-visible behaviour<br>
>     change.<br>
><br>
>     Side note: it would be great to use the same technique to allow<br>
>     booting<br>
>     from pre-1.6.8 snapshots. Unfortunately, this is not possible.<br>
><br>
>     Current triggers don't break the order of schema upgrades, so 1.7.1<br>
>     upgrades come before 1.7.2 and 1.7.5. This is because all the upgrades<br>
>     in these versions are replacing existing tuples and not inserting new<br>
>     ones, so the upgrades may be handled by the before_replace triggers.<br>
><br>
>     Upgrade to 1.6.8 requires inserting new tuples: creating sysviews,<br>
>     like<br>
>     _vspace, _vuser and so on. This can't be done from the before_replace<br>
>     triggers, so we would have to run triggers for 1.7.x first which would<br>
>     allow Tarantool to recover the snapshot, and then run an upgrade<br>
>     handler for<br>
>     1.6.8. This looks really messy.<br>
><br>
>     Closes #5894<br>
>     ---<br>
>      src/box/lua/load_cfg.lua | 14 +<br>
>      src/box/lua/upgrade.lua | 276 +++++++++++-<br>
>      test/xlog/gh-5894-pre-1.7.7-upgrade.result | 400 ++++++++++++++++++<br>
>      test/xlog/gh-5894-pre-1.7.7-upgrade.test.lua | 77 ++++<br>
>      .../1.6.8/gh-5894-pre-1.7.7-upgrade/fill.lua | 1 +<br>
>      .../1.7.1/gh-5894-pre-1.7.7-upgrade/fill.lua | 1 +<br>
>      .../1.7.2/gh-5894-pre-1.7.7-upgrade/fill.lua | 1 +<br>
>      .../1.7.5/gh-5894-pre-1.7.7-upgrade/fill.lua | 1 +<br>
>      test/xlog/upgrade/fill.lua | 4 +<br>
>      9 files changed, 773 insertions(+), 2 deletions(-)<br>
>      create mode 100644 test/xlog/gh-5894-pre-1.7.7-upgrade.result<br>
>      create mode 100644 test/xlog/gh-5894-pre-1.7.7-upgrade.test.lua<br>
>      create mode 120000<br>
>     test/xlog/upgrade/1.6.8/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>      create mode 120000<br>
>     test/xlog/upgrade/1.7.1/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>      create mode 120000<br>
>     test/xlog/upgrade/1.7.2/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>      create mode 120000<br>
>     test/xlog/upgrade/1.7.5/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
><br>
>     diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua<br>
>     index 4df70c210..7a8cab3fd 100644<br>
>     --- a/src/box/lua/load_cfg.lua<br>
>     +++ b/src/box/lua/load_cfg.lua<br>
>     @@ -719,9 +719,23 @@ local function load_cfg(cfg)<br>
>                  __call = locked(reload_cfg),<br>
>              })<br>
><br>
>     + -- Check schema version of the snapshot we're about to recover,<br>
>     if any.<br>
>     + -- Some schema versions (below 1.7.5) are incompatible with<br>
>     Tarantool 2.x<br>
>     + -- When recovering from such an old snapshot, special recovery<br>
>     triggers on<br>
>     + -- system spaces are needed in order to be able to recover and<br>
>     upgrade<br>
>     + -- the schema then.<br>
>     + local snap_dir = box.cfg.memtx_dir<br>
>     + local snap_version = private.get_snapshot_version(snap_dir)<br>
>     + if snap_version then<br>
>     + private.set_recovery_triggers(snap_version)<br>
>     + end<br>
>     +<br>
>          -- This call either succeeds or calls panic() / exit().<br>
>          private.cfg_load()<br>
><br>
>     + if snap_version then<br>
>     + private.clear_recovery_triggers()<br>
>     + end<br>
>          -- This block does not raise an error: all necessary checks<br>
>          -- already performed in private.cfg_check(). See <dynamic_cfg><br>
>          -- comment.<br>
>     diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua<br>
>     index 6abce50f4..925adab18 100644<br>
>     --- a/src/box/lua/upgrade.lua<br>
>     +++ b/src/box/lua/upgrade.lua<br>
>     @@ -1,6 +1,8 @@<br>
>      local log = require('log')<br>
>      local bit = require('bit')<br>
>      local json = require('json')<br>
>     +local fio = require('fio')<br>
>     +local xlog = require('xlog')<br>
><br>
>      -- Guest user id - the default user<br>
>      local GUEST = 0<br>
>     @@ -86,6 +88,40 @@ local function set_system_triggers(val)<br>
>          foreach_system_space(function(s) s:run_triggers(val) end)<br>
>      end<br>
><br>
>     +-- Get schema version, stored in _schema system space, by reading<br>
>     the latest<br>
>     +-- snapshot file from the snap_dir. Useful to define<br>
>     schema_version before<br>
>     +-- recovering the snapshot, because some schema versions are too<br>
>     old and cannot<br>
>     +-- be recovered normally.<br>
>     +local function get_snapshot_version(snap_dir)<br>
>     + local snap_pattern = snap_dir..'/'..string.rep('[0-9]', 20)..'.snap'<br>
><br>
> Probably we could use fio.pathjoin here<br>
<br>
Yep, sure. Changed.<br>
<br>
>     + local snap_list = fio.glob(snap_pattern)<br>
>     + table.sort(snap_list)<br>
>     + local snap = snap_list[#snap_list]<br>
>     + if not snap then<br>
>     + return nil<br>
>     + end<br>
>     + local version = nil<br>
>     + for _, row in xlog.pairs(snap) do<br>
>     + local sid = row.BODY and row.BODY.space_id<br>
>     + if sid == box.schema.SCHEMA_ID then<br>
>     + local tuple = row.BODY.tuple<br>
>     + if tuple and tuple[1] == 'version' then<br>
>     + local major, minor, patch = tuple[2], tuple[3], tuple[4] or 0<br>
><br>
> Could it be replaced with tuple:unpack(2, 4)?<br>
<br>
Yep. Fixed as well.<br>
<br>
>     + if major and minor and patch and type(major) == 'number' and<br>
>     + type(minor) == 'number' and type(patch) == 'number' then<br>
><br>
> Here you use type() == number checks. Could it be different? In case <br>
> of broken snap?<br>
<br>
Yep, that's a check for a broken snap.<br>
> So, we should log it I assume. The same for similar places below.<br>
<br>
Added logging.<br>
<br>
>     + version = mkversion(major, minor, patch)<br>
>     + break<br>
>     + end<br>
>     + end<br>
>     + elseif sid and sid > box.schema.SCHEMA_ID then<br>
>     + -- Exit early if version wasn't found in _schema space.<br>
>     + -- Snapshot rows are ordered by space id.<br>
>     + break<br>
>     + end<br>
>     + end<br>
>     + return version<br>
>     +end<br>
>     +<br>
>      --------------------------------------------------------------------------------<br>
>      -- Bootstrap<br>
>      --------------------------------------------------------------------------------<br>
>     @@ -131,6 +167,144 @@ local function create_sysview(source_id,<br>
>     target_id)<br>
>          end<br>
>      end<br>
><br>
>     +--------------------------------------------------------------------------------<br>
>     +-- Tarantool 1.7.1<br>
>     +--------------------------------------------------------------------------------<br>
>     +local function user_trig_1_7_1(_, tuple)<br>
>     + if tuple and tuple[3] == 'guest' and not tuple[5] then<br>
><br>
> I think it’s better to use explicit check for tuple[5] value.<br>
> If it’s a boolean value could it be box.NULL?<br>
<br>
not box.NULL returns false, while not nil returns true.<br>
<br>
On the other hand, box.NULL == nil returns true.<br>
<br>
So I'd rather leave this check.<br>
<br>
<br>
Here's the full diff:<br>
<br>
============================================<br>
diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua<br>
index 925adab18..01e22aa7c 100644<br>
--- a/src/box/lua/upgrade.lua<br>
+++ b/src/box/lua/upgrade.lua<br>
@@ -88,12 +88,23 @@ local function set_system_triggers(val)<br>
      foreach_system_space(function(s) s:run_triggers(val) end)<br>
  end<br>
<br>
+local function version_from_tuple(tuple)<br>
+    local major, minor, patch = tuple:unpack(2, 4)<br>
+    patch = patch or 0<br>
+    if major and minor and type(major) == 'number' and<br>
+       type(minor) == 'number' and type(patch) == 'number' then<br>
+        return mkversion(major, minor, patch)<br>
+    end<br>
+    return nil<br>
+end<br>
+<br>
  -- Get schema version, stored in _schema system space, by reading the <br>
latest<br>
  -- snapshot file from the snap_dir. Useful to define schema_version before<br>
  -- recovering the snapshot, because some schema versions are too old <br>
and cannot<br>
  -- be recovered normally.<br>
  local function get_snapshot_version(snap_dir)<br>
-    local snap_pattern = snap_dir..'/'..string.rep('[0-9]', 20)..'.snap'<br>
+    local snap_pattern = fio.pathjoin(snap_dir,<br>
+                                      string.rep('[0-9]', 20)..'.snap')<br>
      local snap_list = fio.glob(snap_pattern)<br>
      table.sort(snap_list)<br>
      local snap = snap_list[#snap_list]<br>
@@ -106,12 +117,14 @@ local function get_snapshot_version(snap_dir)<br>
          if sid == box.schema.SCHEMA_ID then<br>
              local tuple = row.BODY.tuple<br>
              if tuple and tuple[1] == 'version' then<br>
-                local major, minor, patch = tuple[2], tuple[3], <br>
tuple[4] or 0<br>
-                if major and minor and patch and type(major) == <br>
'number' and<br>
-                   type(minor) == 'number' and type(patch) == 'number' then<br>
-                    version = mkversion(major, minor, patch)<br>
-                    break<br>
+                local major, minor, patch = tuple:unpack(2, 4)<br>
+                patch = patch or 0<br>
+                version = version_from_tuple(tuple)<br>
+                if not version then<br>
+                    log.error("Corrupted version tuple in space <br>
'_schema' "..<br>
+                              "in snapshot '%s': %s ", snap, tuple)<br>
                  end<br>
+                break<br>
              end<br>
          elseif sid and sid > box.schema.SCHEMA_ID then<br>
              -- Exit early if version wasn't found in _schema space.<br>
@@ -1284,10 +1297,8 @@ local recovery_triggers = {<br>
  -- snapshot), the triggers helping recover the old schema should be <br>
removed.<br>
  local function schema_trig_last(_, tuple)<br>
      if tuple and tuple[1] == 'version' then<br>
-        local major, minor, patch = tuple[2], tuple[3], tuple[4] or 0<br>
-        if major and minor and patch and type(major) == 'number' and<br>
-           type(minor) == 'number' and type(patch) == 'number' then<br>
-            local version = mkversion(major, minor, patch)<br>
+        local version = version_from_tuple(tuple)<br>
+        if version then<br>
              log.info("Recovery trigger: recovered schema version %s. "..<br>
                       "Removing outdated recovery triggers.", version)<br>
              box.internal.clear_recovery_triggers(version)<br>
<br>
<br>
============================================<br>
><br>
>     + local auth_method_list = {}<br>
>     + auth_method_list["chap-sha1"] = box.schema.user.password("")<br>
>     + tuple = tuple:update{{'=', 5, auth_method_list}}<br>
>     + log.info("Set empty password to user 'guest'")<br>
>     + end<br>
>     + return tuple<br>
>     +end<br>
>     +<br>
>     +--------------------------------------------------------------------------------<br>
>     +-- Tarantool 1.7.2<br>
>     +--------------------------------------------------------------------------------<br>
>     +local function index_trig_1_7_2(_, tuple)<br>
>     + local field_types_v16 = {<br>
>     + num = 'unsigned',<br>
>     + int = 'integer',<br>
>     + str = 'string',<br>
>     + }<br>
>     + if not tuple then<br>
>     + return tuple<br>
>     + end<br>
>     + local parts = tuple[6]<br>
>     + local changed = false<br>
>     + for _, part in pairs(parts) do<br>
>     + local field_type = part[2]:lower()<br>
>     + if field_types_v16[field_type] ~= nil then<br>
>     + part[2] = field_types_v16[field_type]<br>
>     + changed = true<br>
>     + end<br>
>     + end<br>
>     + if changed then<br>
>     + log.info("Update index '%s' on space '%s': set parts to %s",<br>
>     tuple[3],<br>
>     + box.space[tuple[1]].name, json.encode(parts))<br>
>     + tuple = tuple:update{{'=', 6, parts}}<br>
>     + end<br>
>     + return tuple<br>
>     +end<br>
>     +<br>
>     +--------------------------------------------------------------------------------<br>
>     +-- Tarantool 1.7.5<br>
>     +--------------------------------------------------------------------------------<br>
>     +local function create_truncate_space()<br>
>     + local _truncate = box.space[box.schema.TRUNCATE_ID]<br>
>     +<br>
>     + log.info("create space _truncate")<br>
>     + box.space._space:insert{<br>
>     + _truncate.id, ADMIN, '_truncate', 'memtx', 0, setmap({}),<br>
>     + {{name = 'id', type = 'unsigned'}, {name = 'count', type =<br>
>     'unsigned'}}<br>
>     + }<br>
>     +<br>
>     + log.info("create index primary on _truncate")<br>
>     + box.space._index:insert{<br>
>     + _truncate.id, 0, 'primary', 'tree', {unique = true}, {{0,<br>
>     'unsigned'}}<br>
>     + }<br>
>     +<br>
>     + local _priv = box.space[box.schema.PRIV_ID]<br>
>     + _priv:insert{ADMIN, PUBLIC, 'space', _truncate.id, box.priv.W}<br>
>     +end<br>
>     +<br>
>     +local function upgrade_to_1_7_5()<br>
>     + create_truncate_space()<br>
>     +end<br>
>     +<br>
>     +local function user_trig_1_7_5(_, tuple)<br>
>     + if tuple and not tuple[5] then<br>
>     + tuple = tuple:update{{'=', 5, setmap({})}}<br>
>     + log.info("Set empty password to %s '%s'", tuple[4], tuple[3])<br>
>     + end<br>
>     + return tuple<br>
>     +end<br>
>     +<br>
>     +local space_formats_1_7_5 = {<br>
>     + _schema = {<br>
>     + {name = 'key', type = 'string'},<br>
>     + },<br>
>     + _space = {<br>
>     + {name = 'id', type = 'unsigned'},<br>
>     + {name = 'owner', type = 'unsigned'},<br>
>     + {name = 'name', type = 'string'},<br>
>     + {name = 'engine', type = 'string'},<br>
>     + {name = 'field_count', type = 'unsigned'},<br>
>     + {name = 'flags', type = 'map'},<br>
>     + {name = 'format', type = 'array'},<br>
>     + },<br>
>     + _index = {<br>
>     + {name = 'id', type = 'unsigned'},<br>
>     + {name = 'iid', type = 'unsigned'},<br>
>     + {name = 'name', type = 'string'},<br>
>     + {name = 'type', type = 'string'},<br>
>     + {name = 'opts', type = 'map'},<br>
>     + {name = 'parts', type = 'array'},<br>
>     + },<br>
>     + _func = {<br>
>     + {name = 'id', type = 'unsigned'},<br>
>     + {name = 'owner', type = 'unsigned'},<br>
>     + {name = 'name', type = 'string'},<br>
>     + {name = 'setuid', type = 'unsigned'},<br>
>     + },<br>
>     + _user = {<br>
>     + {name = 'id', type = 'unsigned'},<br>
>     + {name = 'owner', type = 'unsigned'},<br>
>     + {name = 'name', type = 'string'},<br>
>     + {name = 'type', type = 'string'},<br>
>     + {name = 'auth', type = 'map'},<br>
>     + },<br>
>     + _priv = {<br>
>     + {name = 'grantor', type = 'unsigned'},<br>
>     + {name = 'grantee', type = 'unsigned'},<br>
>     + {name = 'object_type', type = 'string'},<br>
>     + {name = 'object_id', type = 'unsigned'},<br>
>     + {name = 'privilege', type = 'unsigned'},<br>
>     + },<br>
>     + _cluster = {<br>
>     + {name = 'id', type = 'unsigned'},<br>
>     + {name = 'uuid', type = 'string'},<br>
>     + },<br>
>     +}<br>
>     +<br>
>     +space_formats_1_7_5._vspace = space_formats_1_7_5._space<br>
>     +space_formats_1_7_5._vindex = space_formats_1_7_5._index<br>
>     +space_formats_1_7_5._vfunc = space_formats_1_7_5._func<br>
>     +space_formats_1_7_5._vuser = space_formats_1_7_5._user<br>
>     +space_formats_1_7_5._vpriv = space_formats_1_7_5._priv<br>
>     +<br>
>     +local function space_trig_1_7_5(_, tuple)<br>
>     + if tuple and space_formats_1_7_5[tuple[3]] and<br>
>     + not table.equals(space_formats_1_7_5[tuple[3]], tuple[7]) then<br>
>     + tuple = tuple:update{{'=', 7, space_formats_1_7_5[tuple[3]]}}<br>
>     + log.info("Update space '%s' format: new format %s", tuple[3],<br>
>     + json.encode(tuple[7]))<br>
>     + end<br>
>     + return tuple<br>
>     +end<br>
>     +<br>
>      local function initial_1_7_5()<br>
>          -- stick to the following convention:<br>
>          -- prefer user id (owner id) in field #1<br>
>     @@ -452,6 +626,15 @@ local function upgrade_to_1_7_7()<br>
>          _priv:replace({ADMIN, SUPER, 'universe', 0, 4294967295})<br>
>      end<br>
><br>
>     +local function priv_trig_1_7_7(_, tuple)<br>
>     + if tuple and tuple[2] == ADMIN and tuple[3] == 'universe' and<br>
>     + tuple[5] ~= box.priv.ALL then<br>
>     + tuple = tuple:update{{'=', 5, box.priv.ALL}}<br>
>     + log.info("Grant all privileges to user 'admin'")<br>
>     + end<br>
>     + return tuple<br>
>     +end<br>
>     +<br>
>      --------------------------------------------------------------------------------<br>
>      --- Tarantool 1.10.0<br>
>      --------------------------------------------------------------------------------<br>
>     @@ -1021,6 +1204,7 @@ end<br>
>      --------------------------------------------------------------------------------<br>
><br>
>      local handlers = {<br>
>     + {version = mkversion(1, 7, 5), func = upgrade_to_1_7_5, auto=true},<br>
>          {version = mkversion(1, 7, 6), func = upgrade_to_1_7_6, auto<br>
>     = true},<br>
>          {version = mkversion(1, 7, 7), func = upgrade_to_1_7_7, auto<br>
>     = true},<br>
>          {version = mkversion(1, 10, 0), func = upgrade_to_1_10_0,<br>
>     auto = true},<br>
>     @@ -1061,13 +1245,98 @@ local function schema_needs_upgrade()<br>
>          return false<br>
>      end<br>
><br>
>     +local trig_oldest_version = nil<br>
>     +<br>
>     +-- Some schema changes before version 1.7.7 make it impossible to<br>
>     recover from<br>
>     +-- older snapshot. The table below consists of before_replace<br>
>     triggers on system<br>
>     +-- spaces, which make old snapshot schema compatible with current<br>
>     Tarantool<br>
>     +-- (version 2.x). The triggers replace old format tuples with new<br>
>     ones<br>
>     +-- in-memory, thus making it possible to recover from a rather<br>
>     old snapshot<br>
>     +-- (up to schema version 1.6.8). Once the snapshot is recovered,<br>
>     a normal<br>
>     +-- upgrade procedure may set schema version to the latest one.<br>
>     +--<br>
>     +-- The triggers mostly repeat the corresponding upgrade_to_1_7_x<br>
>     functions,<br>
>     +-- which were used when pre-1.7.x snapshot schema was still<br>
>     recoverable.<br>
>     +--<br>
>     +-- When the triggers are used (i.e. when snapshot schema version<br>
>     is below 1.7.5,<br>
>     +-- the upgrade procedure works as follows:<br>
>     +-- * first the snapshot is recovered and 1.7.5-compatible schema<br>
>     is applied to<br>
>     +-- it in-memory with the help of triggers.<br>
>     +-- * then usual upgrade_to_X_X_X() handlers may be fired to turn<br>
>     schema into the<br>
>     +-- latest one.<br>
>     +local recovery_triggers = {<br>
>     + {version = mkversion(1, 7, 1), tbl = {<br>
>     + _user = user_trig_1_7_1,<br>
>     + }},<br>
>     + {version = mkversion(1, 7, 2), tbl = {<br>
>     + _index = index_trig_1_7_2,<br>
>     + }},<br>
>     + {version = mkversion(1, 7, 5), tbl = {<br>
>     + _space = space_trig_1_7_5,<br>
>     + _user = user_trig_1_7_5,<br>
>     + }},<br>
>     + {version = mkversion(1, 7, 7), tbl = {<br>
>     + _priv = priv_trig_1_7_7,<br>
>     + }},<br>
>     +}<br>
>     +<br>
>     +-- Once newer schema version is recovered (say, from an xlog<br>
>     following the old<br>
>     +-- snapshot), the triggers helping recover the old schema should<br>
>     be removed.<br>
>     +local function schema_trig_last(_, tuple)<br>
>     + if tuple and tuple[1] == 'version' then<br>
>     + local major, minor, patch = tuple[2], tuple[3], tuple[4] or 0<br>
>     + if major and minor and patch and type(major) == 'number' and<br>
>     + type(minor) == 'number' and type(patch) == 'number' then<br>
>     + local version = mkversion(major, minor, patch)<br>
>     + log.info("Recovery trigger: recovered schema version %s. "..<br>
>     + "Removing outdated recovery triggers.", version)<br>
>     + box.internal.clear_recovery_triggers(version)<br>
>     + trig_oldest_version = version<br>
>     + end<br>
>     + end<br>
>     + return tuple<br>
>     +end<br>
>     +<br>
>     +recovery_triggers[#recovery_triggers].tbl['_schema'] =<br>
>     schema_trig_last<br>
>     +<br>
>     +local function on_init_set_recovery_triggers()<br>
>     + log.info("Recovering snapshot with schema version %s",<br>
>     trig_oldest_version)<br>
>     + for _, trig_tbl in ipairs(recovery_triggers) do<br>
>     + if trig_tbl.version > trig_oldest_version then<br>
>     + for space, trig in pairs(trig_tbl.tbl) do<br>
>     + box.space[space]:before_replace(trig)<br>
>     + log.info("Set recovery trigger on space '%s' to comply with "..<br>
>     + "version %s format", space, trig_tbl.version)<br>
>     + end<br>
>     + end<br>
>     + end<br>
>     +end<br>
>     +<br>
>     +local function set_recovery_triggers(version)<br>
>     + trig_oldest_version = version<br>
>     + box.ctl.on_schema_init(on_init_set_recovery_triggers)<br>
>     +end<br>
>     +<br>
>     +local function clear_recovery_triggers(version)<br>
>     + for _, trig_tbl in ipairs(recovery_triggers) do<br>
>     + if trig_tbl.version > trig_oldest_version and<br>
>     + (not version or trig_tbl.version <= version) then<br>
>     + for space, trig in pairs(trig_tbl.tbl) do<br>
>     + box.space[space]:before_replace(nil, trig)<br>
>     + log.info("Remove recovery trigger on space '%s' for version %s",<br>
>     + space, trig_tbl.version)<br>
>     + end<br>
>     + end<br>
>     + end<br>
>     +end<br>
>     +<br>
>      local function upgrade(options)<br>
>          options = options or {}<br>
>          setmetatable(options, {__index = {auto = false}})<br>
><br>
>          local version = get_version()<br>
>     - if version < mkversion(1, 7, 5) then<br>
>     - log.warn('can upgrade from 1.7.5 only')<br>
>     + if version < mkversion(1, 6, 8) then<br>
>     + log.warn('can upgrade from 1.6.8 only')<br>
>              return<br>
>          end<br>
><br>
>     @@ -1110,3 +1379,6 @@ end<br>
>      box.schema.upgrade = upgrade;<br>
>      box.internal.bootstrap = bootstrap;<br>
>      box.internal.schema_needs_upgrade = schema_needs_upgrade;<br>
>     +box.internal.get_snapshot_version = get_snapshot_version;<br>
>     +box.internal.set_recovery_triggers = set_recovery_triggers;<br>
>     +box.internal.clear_recovery_triggers = clear_recovery_triggers;<br>
>     diff --git a/test/xlog/gh-5894-pre-1.7.7-upgrade.result<br>
>     b/test/xlog/gh-5894-pre-1.7.7-upgrade.result<br>
>     new file mode 100644<br>
>     index 000000000..aba5a56ab<br>
>     --- /dev/null<br>
>     +++ b/test/xlog/gh-5894-pre-1.7.7-upgrade.result<br>
>     @@ -0,0 +1,400 @@<br>
>     +-- test-run result file version 2<br>
>     +test_run = require('test_run').new()<br>
>     + | ---<br>
>     + | ...<br>
>     +<br>
>     +-- Upgrade from 1.6.8.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.6.8/gh-5894-pre-1.7.7-upgrade"')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('start server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:switch('upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +box.space.distro:select{}<br>
>     + | ---<br>
>     + | - - ['debian', 'sarge', 31, 1118059200]<br>
>     + | - ['debian', 'etch', 40, 1176033600]<br>
>     + | - ['ubuntu', 'trusty', 1404, 1397736000]<br>
>     + | - ['ubuntu', 'vivid', 1504, 1429790400]<br>
>     + | - ['ubuntu', 'wily', 1510, 1445515200]<br>
>     + | - ['debian', 'wheezy', 70, 1367668800]<br>
>     + | - ['debian', 'squeeze', 60, 1296907200]<br>
>     + | - ['debian', 'lenny', 50, 1234612800]<br>
>     + | - ['debian', 'jessie', 80, 1430049600]<br>
>     + | - ['ubuntu', 'precise', 1510, 1335441600]<br>
>     + | - ['debian', 'woody', 30, 1027080000]<br>
>     + | ...<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     + | ---<br>
>     + | - - [512, 0, 'primary', 'hash', {'unique': true}, [[0,<br>
>     'string'], [1, 'string'], [<br>
>     + | 2, 'unsigned']]]<br>
>     + | - [512, 1, 'codename', 'hash', {'unique': true}, [[1, 'string']]]<br>
>     + | - [512, 2, 'time', 'tree', {'unique': false}, [[3, 'unsigned']]]<br>
>     + | ...<br>
>     +box.space._space:format()<br>
>     + | ---<br>
>     + | - [{'name': 'id', 'type': 'unsigned'}, {'name': 'owner',<br>
>     'type': 'unsigned'}, {'name': 'name',<br>
>     + | 'type': 'string'}, {'name': 'engine', 'type': 'string'},<br>
>     {'name': 'field_count',<br>
>     + | 'type': 'unsigned'}, {'name': 'flags', 'type': 'map'},<br>
>     {'name': 'format', 'type': 'array'}]<br>
>     + | ...<br>
>     +box.schema.user.info('admin')<br>
>     + | ---<br>
>     + | - - -<br>
>     read,write,execute,session,usage,create,drop,alter,reference,trigger,insert,update,delete<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('guest')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('someuser')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - function<br>
>     + | - someotherfunc<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - somerole<br>
>     + | - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - temporary<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.role.info('somerole')<br>
>     + | ---<br>
>     + | - - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - distro<br>
>     + | ...<br>
>     +<br>
>     +test_run:switch('default')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('stop server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('delete server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +<br>
>     +-- Upgrade from 1.7.1.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.7.1/gh-5894-pre-1.7.7-upgrade"')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('start server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:switch('upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +box.space.distro:select{}<br>
>     + | ---<br>
>     + | - - ['debian', 'etch', 40, 1176033600]<br>
>     + | - ['debian', 'sarge', 31, 1118059200]<br>
>     + | - ['ubuntu', 'wily', 1510, 1445515200]<br>
>     + | - ['ubuntu', 'trusty', 1404, 1397736000]<br>
>     + | - ['ubuntu', 'vivid', 1504, 1429790400]<br>
>     + | - ['debian', 'wheezy', 70, 1367668800]<br>
>     + | - ['debian', 'squeeze', 60, 1296907200]<br>
>     + | - ['debian', 'lenny', 50, 1234612800]<br>
>     + | - ['debian', 'jessie', 80, 1430049600]<br>
>     + | - ['ubuntu', 'precise', 1510, 1335441600]<br>
>     + | - ['debian', 'woody', 30, 1027080000]<br>
>     + | ...<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     + | ---<br>
>     + | - - [512, 0, 'primary', 'hash', {'unique': true}, [[0,<br>
>     'string'], [1, 'string'], [<br>
>     + | 2, 'unsigned']]]<br>
>     + | - [512, 1, 'codename', 'hash', {'unique': true}, [[1, 'string']]]<br>
>     + | - [512, 2, 'time', 'tree', {'unique': false}, [[3, 'unsigned']]]<br>
>     + | ...<br>
>     +box.space._space:format()<br>
>     + | ---<br>
>     + | - [{'name': 'id', 'type': 'unsigned'}, {'name': 'owner',<br>
>     'type': 'unsigned'}, {'name': 'name',<br>
>     + | 'type': 'string'}, {'name': 'engine', 'type': 'string'},<br>
>     {'name': 'field_count',<br>
>     + | 'type': 'unsigned'}, {'name': 'flags', 'type': 'map'},<br>
>     {'name': 'format', 'type': 'array'}]<br>
>     + | ...<br>
>     +box.schema.user.info('admin')<br>
>     + | ---<br>
>     + | - - -<br>
>     read,write,execute,session,usage,create,drop,alter,reference,trigger,insert,update,delete<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('guest')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('someuser')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - function<br>
>     + | - someotherfunc<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - somerole<br>
>     + | - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - temporary<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.role.info('somerole')<br>
>     + | ---<br>
>     + | - - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - distro<br>
>     + | ...<br>
>     +<br>
>     +test_run:switch('default')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('stop server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('delete server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +<br>
>     +-- Upgrade from 1.7.2.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.7.2/gh-5894-pre-1.7.7-upgrade"')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('start server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:switch('upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +box.space.distro:select{}<br>
>     + | ---<br>
>     + | - - ['debian', 'sarge', 31, 1118059200]<br>
>     + | - ['debian', 'etch', 40, 1176033600]<br>
>     + | - ['ubuntu', 'trusty', 1404, 1397736000]<br>
>     + | - ['ubuntu', 'vivid', 1504, 1429790400]<br>
>     + | - ['debian', 'lenny', 50, 1234612800]<br>
>     + | - ['debian', 'wheezy', 70, 1367668800]<br>
>     + | - ['debian', 'squeeze', 60, 1296907200]<br>
>     + | - ['ubuntu', 'wily', 1510, 1445515200]<br>
>     + | - ['debian', 'jessie', 80, 1430049600]<br>
>     + | - ['ubuntu', 'precise', 1510, 1335441600]<br>
>     + | - ['debian', 'woody', 30, 1027080000]<br>
>     + | ...<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     + | ---<br>
>     + | - - [512, 0, 'primary', 'hash', {'unique': true}, [[0,<br>
>     'string'], [1, 'string'], [<br>
>     + | 2, 'unsigned']]]<br>
>     + | - [512, 1, 'codename', 'hash', {'unique': true}, [[1, 'string']]]<br>
>     + | - [512, 2, 'time', 'tree', {'unique': false}, [[3, 'unsigned']]]<br>
>     + | ...<br>
>     +box.space._space:format()<br>
>     + | ---<br>
>     + | - [{'name': 'id', 'type': 'unsigned'}, {'name': 'owner',<br>
>     'type': 'unsigned'}, {'name': 'name',<br>
>     + | 'type': 'string'}, {'name': 'engine', 'type': 'string'},<br>
>     {'name': 'field_count',<br>
>     + | 'type': 'unsigned'}, {'name': 'flags', 'type': 'map'},<br>
>     {'name': 'format', 'type': 'array'}]<br>
>     + | ...<br>
>     +box.schema.user.info('admin')<br>
>     + | ---<br>
>     + | - - -<br>
>     read,write,execute,session,usage,create,drop,alter,reference,trigger,insert,update,delete<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('guest')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('someuser')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - function<br>
>     + | - someotherfunc<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - somerole<br>
>     + | - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - temporary<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.role.info('somerole')<br>
>     + | ---<br>
>     + | - - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - distro<br>
>     + | ...<br>
>     +<br>
>     +test_run:switch('default')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('stop server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('delete server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +<br>
>     +-- Upgrade from 1.7.5.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.7.5/gh-5894-pre-1.7.7-upgrade"')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('start server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:switch('upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +box.space.distro:select{}<br>
>     + | ---<br>
>     + | - - ['debian', 'etch', 40, 1176033600]<br>
>     + | - ['debian', 'sarge', 31, 1118059200]<br>
>     + | - ['debian', 'lenny', 50, 1234612800]<br>
>     + | - ['ubuntu', 'trusty', 1404, 1397736000]<br>
>     + | - ['ubuntu', 'vivid', 1504, 1429790400]<br>
>     + | - ['debian', 'wheezy', 70, 1367668800]<br>
>     + | - ['debian', 'squeeze', 60, 1296907200]<br>
>     + | - ['ubuntu', 'wily', 1510, 1445515200]<br>
>     + | - ['debian', 'jessie', 80, 1430049600]<br>
>     + | - ['ubuntu', 'precise', 1510, 1335441600]<br>
>     + | - ['debian', 'woody', 30, 1027080000]<br>
>     + | ...<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     + | ---<br>
>     + | - - [512, 0, 'primary', 'hash', {'unique': true}, [[0,<br>
>     'string'], [1, 'string'], [<br>
>     + | 2, 'unsigned']]]<br>
>     + | - [512, 1, 'codename', 'hash', {'unique': true}, [[1, 'string']]]<br>
>     + | - [512, 2, 'time', 'tree', {'unique': false}, [[3, 'unsigned']]]<br>
>     + | ...<br>
>     +box.space._space:format()<br>
>     + | ---<br>
>     + | - [{'name': 'id', 'type': 'unsigned'}, {'name': 'owner',<br>
>     'type': 'unsigned'}, {'name': 'name',<br>
>     + | 'type': 'string'}, {'name': 'engine', 'type': 'string'},<br>
>     {'name': 'field_count',<br>
>     + | 'type': 'unsigned'}, {'name': 'flags', 'type': 'map'},<br>
>     {'name': 'format', 'type': 'array'}]<br>
>     + | ...<br>
>     +box.schema.user.info('admin')<br>
>     + | ---<br>
>     + | - - -<br>
>     read,write,execute,session,usage,create,drop,alter,reference,trigger,insert,update,delete<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('guest')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.user.info('someuser')<br>
>     + | ---<br>
>     + | - - - execute<br>
>     + | - function<br>
>     + | - someotherfunc<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - public<br>
>     + | - - execute<br>
>     + | - role<br>
>     + | - somerole<br>
>     + | - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - temporary<br>
>     + | - - session,usage<br>
>     + | - universe<br>
>     + | -<br>
>     + | ...<br>
>     +box.schema.role.info('somerole')<br>
>     + | ---<br>
>     + | - - - read,write,drop,alter<br>
>     + | - space<br>
>     + | - distro<br>
>     + | ...<br>
>     +<br>
>     +test_run:switch('default')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('stop server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     +test_run:cmd('delete server upgrade')<br>
>     + | ---<br>
>     + | - true<br>
>     + | ...<br>
>     diff --git a/test/xlog/gh-5894-pre-1.7.7-upgrade.test.lua<br>
>     b/test/xlog/gh-5894-pre-1.7.7-upgrade.test.lua<br>
>     new file mode 100644<br>
>     index 000000000..9096bcb7a<br>
>     --- /dev/null<br>
>     +++ b/test/xlog/gh-5894-pre-1.7.7-upgrade.test.lua<br>
>     @@ -0,0 +1,77 @@<br>
>     +test_run = require('test_run').new()<br>
>     +<br>
>     +-- Upgrade from 1.6.8.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.6.8/gh-5894-pre-1.7.7-upgrade"')<br>
>     +test_run:cmd('start server upgrade')<br>
>     +test_run:switch('upgrade')<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     +box.space.distro:select{}<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     +box.space._space:format()<br>
>     +box.schema.user.info('admin')<br>
>     +box.schema.user.info('guest')<br>
>     +box.schema.user.info('someuser')<br>
>     +box.schema.role.info('somerole')<br>
>     +<br>
>     +test_run:switch('default')<br>
>     +test_run:cmd('stop server upgrade')<br>
>     +test_run:cmd('delete server upgrade')<br>
>     +<br>
>     +-- Upgrade from 1.7.1.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.7.1/gh-5894-pre-1.7.7-upgrade"')<br>
>     +test_run:cmd('start server upgrade')<br>
>     +test_run:switch('upgrade')<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     +box.space.distro:select{}<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     +box.space._space:format()<br>
>     +box.schema.user.info('admin')<br>
>     +box.schema.user.info('guest')<br>
>     +box.schema.user.info('someuser')<br>
>     +box.schema.role.info('somerole')<br>
>     +<br>
>     +test_run:switch('default')<br>
>     +test_run:cmd('stop server upgrade')<br>
>     +test_run:cmd('delete server upgrade')<br>
>     +<br>
>     +-- Upgrade from 1.7.2.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.7.2/gh-5894-pre-1.7.7-upgrade"')<br>
>     +test_run:cmd('start server upgrade')<br>
>     +test_run:switch('upgrade')<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     +box.space.distro:select{}<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     +box.space._space:format()<br>
>     +box.schema.user.info('admin')<br>
>     +box.schema.user.info('guest')<br>
>     +box.schema.user.info('someuser')<br>
>     +box.schema.role.info('somerole')<br>
>     +<br>
>     +test_run:switch('default')<br>
>     +test_run:cmd('stop server upgrade')<br>
>     +test_run:cmd('delete server upgrade')<br>
>     +<br>
>     +-- Upgrade from 1.7.5.<br>
>     +test_run:cmd('create server upgrade with script="xlog/upgrade.lua", \<br>
>     + workdir="xlog/upgrade/1.7.5/gh-5894-pre-1.7.7-upgrade"')<br>
>     +test_run:cmd('start server upgrade')<br>
>     +test_run:switch('upgrade')<br>
>     +<br>
>     +assert(not box.internal.schema_needs_upgrade())<br>
>     +box.space.distro:select{}<br>
>     +box.space._index:select{box.space.distro.id}<br>
>     +box.space._space:format()<br>
>     +box.schema.user.info('admin')<br>
>     +box.schema.user.info('guest')<br>
>     +box.schema.user.info('someuser')<br>
>     +box.schema.role.info('somerole')<br>
>     +<br>
>     +test_run:switch('default')<br>
>     +test_run:cmd('stop server upgrade')<br>
>     +test_run:cmd('delete server upgrade')<br>
>     diff --git<br>
>     a/test/xlog/upgrade/1.6.8/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     b/test/xlog/upgrade/1.6.8/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     new file mode 120000<br>
>     index 000000000..2f2a84962<br>
>     --- /dev/null<br>
>     +++ b/test/xlog/upgrade/1.6.8/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     @@ -0,0 +1 @@<br>
>     +../../fill.lua<br>
>     \ No newline at end of file<br>
>     diff --git<br>
>     a/test/xlog/upgrade/1.7.1/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     b/test/xlog/upgrade/1.7.1/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     new file mode 120000<br>
>     index 000000000..2f2a84962<br>
>     --- /dev/null<br>
>     +++ b/test/xlog/upgrade/1.7.1/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     @@ -0,0 +1 @@<br>
>     +../../fill.lua<br>
>     \ No newline at end of file<br>
>     diff --git<br>
>     a/test/xlog/upgrade/1.7.2/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     b/test/xlog/upgrade/1.7.2/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     new file mode 120000<br>
>     index 000000000..2f2a84962<br>
>     --- /dev/null<br>
>     +++ b/test/xlog/upgrade/1.7.2/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     @@ -0,0 +1 @@<br>
>     +../../fill.lua<br>
>     \ No newline at end of file<br>
>     diff --git<br>
>     a/test/xlog/upgrade/1.7.5/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     b/test/xlog/upgrade/1.7.5/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     new file mode 120000<br>
>     index 000000000..2f2a84962<br>
>     --- /dev/null<br>
>     +++ b/test/xlog/upgrade/1.7.5/gh-5894-pre-1.7.7-upgrade/fill.lua<br>
>     @@ -0,0 +1 @@<br>
>     +../../fill.lua<br>
>     \ No newline at end of file<br>
>     diff --git a/test/xlog/upgrade/fill.lua b/test/xlog/upgrade/fill.lua<br>
>     index 0ef1a8bb9..310c1ca72 100644<br>
>     --- a/test/xlog/upgrade/fill.lua<br>
>     +++ b/test/xlog/upgrade/fill.lua<br>
>     @@ -56,4 +56,8 @@ end<br>
>      box.schema.func.create('someotherfunc')<br>
>      box.schema.user.grant('someuser', 'execute', 'function',<br>
>     'someotherfunc')<br>
>      box.schema.user.grant('someuser', 'read,write', 'space', 'temporary')<br>
>     +<br>
>     +box.schema.upgrade()<br>
>     +box.snapshot()<br>
>     +<br>
>      os.exit(0)<br>
>     --<br>
>     2.30.1 (Apple Git-130)<br>
><br>
> --<br>
> Oleg Babin<br>
<br>
-- <br>
Serge Petrenko<br>
</div>
            
        
                <base target="_self" href="https://e.mail.ru/" />
        </div>

        
</div>


</blockquote></BODY></HTML>