From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp38.i.mail.ru (smtp38.i.mail.ru [94.100.177.98]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 2C3F145C304 for ; Wed, 2 Dec 2020 03:16:20 +0300 (MSK) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.120.23.2.1\)) From: Roman Khabibov In-Reply-To: <68080f1b-a50d-3e7b-cb3a-7b8e8d6e437b@tarantool.org> Date: Wed, 2 Dec 2020 03:16:17 +0300 Content-Transfer-Encoding: quoted-printable Message-Id: <5F726C10-5FE5-4494-B08A-5657AD44C894@tarantool.org> References: <20201115235416.72858-1-roman.habibov@tarantool.org> <39A73765-A387-4EA2-83DA-4B80534AAAF0@tarantool.org> <2046B5A1-96D9-48D5-9F17-7AC1EAE83496@tarantool.org> <271345E1-6C02-40D2-ADC3-50C96F4BCA90@tarantool.org> <68080f1b-a50d-3e7b-cb3a-7b8e8d6e437b@tarantool.org> Subject: Re: [Tarantool-patches] [PATCH] box: check schema version after tarantool update List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Serge Petrenko Cc: tarantool-patches@dev.tarantool.org Hi! Thanks for the review. > On Dec 1, 2020, at 12:58, Serge Petrenko = wrote: >=20 >=20 > 30.11.2020 16:43, Roman Khabibov =D0=BF=D0=B8=D1=88=D0=B5=D1=82: >> Thanks. >>=20 >> Serge, could you, please, look through the patch? >=20 >=20 > Hi! Thanks for the patch! >=20 > Since you're working on this instead of Sergey now, you may add = yourself to >=20 > the Co-developed-by field in the commit message, like it is done here: >=20 > = https://github.com/tarantool/tarantool/commit/cfccfd449c890c18615185ba4895= d9081e50c318 >=20 >=20 > Please see 3 more comments below. >=20 >=20 >> commit 8b3265c1599772f5a85e47ed1a8232571ec23f8d >> Author: Sergey Voinov >> Date: Wed Dec 11 17:28:39 2019 +0300 >>=20 >> box: check schema version after tarantool update >> Check schema version (stored in box.space._schema) on start = and >> print a warning if it doesn't match last available schema = version. >> It is needed because some users forget to call >> box.schema.upgrade() after Tarantool update and get stuck with an >> old schema version until they encounter some hard to debug >> problems. >> Closes #4574 >>=20 >> diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua >> index 76e2e92c2..451247dcf 100644 >> --- a/src/box/lua/load_cfg.lua >> +++ b/src/box/lua/load_cfg.lua >> @@ -702,6 +702,22 @@ local function load_cfg(cfg) >> box_configured =3D nil >> box_is_configured =3D true >> + >> + -- Check if schema version matches Tarantool version >> + -- and print warning if it's not (in case user forgot to call = box.schema.upgrade()) >> + local version =3D box.space._schema:get{'version'} >=20 >=20 > 1. Version unused. You get schema version in `schema_needs_upgrade()` = anyway. >=20 > Also you may omit testing for nil here. You may just test schema = version > inside `schema_needs_upgrade()` and simply return false, if it is = nil. >=20 >=20 > You'll also need to update test/box/stat.result after this is done. diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua index 76e2e92c2..770442052 100644 --- a/src/box/lua/load_cfg.lua +++ b/src/box/lua/load_cfg.lua @@ -702,6 +702,18 @@ local function load_cfg(cfg) box_configured =3D nil =20 box_is_configured =3D true + + -- Check if schema version matches Tarantool version and print + -- warning if it's not (in case user forgot to call + -- box.schema.upgrade()). + local needs, schema_version_str =3D private.schema_needs_upgrade() + if needs then + local msg =3D string.format( + 'Your schema version is %s while Tarantool %s requires a = more'.. + ' recent schema version. Please, consider using box.'.. + 'schema.upgrade().', schema_version_str, box.info.version) + log.warn(msg) + end end box.cfg =3D locked(load_cfg) >=20 >> + if version ~=3D nil then >> + local needs, schema_version_str =3D = private.schema_needs_upgrade() >> + local tarantool_version_str =3D box.info.version >> + if needs then >> + -- Print the warning >> + local msg =3D string.format( >> + 'Your schema version is %s while Tarantool %s = requires a more'.. >> + ' recent schema version. Please, consider using = box.'.. >> + 'schema.upgrade().', schema_version_str, = tarantool_version_str) >> + log.warn(msg) >> + end >> + end >> end >> box.cfg =3D locked(load_cfg) >> =20 >=20 >> diff --git a/test/box/cfg.test.lua b/test/box/cfg.test.lua >> index 56018b1a0..e806c9efe 100644 >> --- a/test/box/cfg.test.lua >> +++ b/test/box/cfg.test.lua >> @@ -159,3 +159,21 @@ test_run:grep_log('cfg_tester7', 'set = \'replication\' configuration option to', >> test_run:grep_log('cfg_tester7', 'test%-cluster%-cookie', 1000) >> test_run:cmd("stop server cfg_tester7") >> test_run:cmd("cleanup server cfg_tester7") >> + >> +-- >> +-- gh-4574: Check schema version after Tarantool update. >> +-- >> +test_run:cmd('create server cfg_tester8 with script =3D = "box/lua/cfg_test8.lua", workdir=3D"sql/upgrade/2.1.0/"') >=20 >=20 > 2. Can you reuse `cfg_test1.lua` here? No, I need to have "read_only =3D true=E2=80=9D. >=20 >> +test_run:cmd("start server cfg_tester8") >> +--- Check that the warning is printed. >> +version_warning =3D "Please, consider using box.schema.upgrade()." >> +test_run:grep_log('cfg_tester8', version_warning, 1000) ~=3D nil >=20 >=20 > 3. Better use `wait_log` instead of `grep_log`. It's not guaranteed = that the > server will print this message by the time you grep for it. Done. >=20 >> +test_run:cmd("stop server cfg_tester8") >> +test_run:cmd("cleanup server cfg_tester8") >> + >> +test_run:cmd('create server cfg_tester9 with script =3D = "box/lua/cfg_test1.lua"') >> +test_run:cmd("start server cfg_tester9") >> +--- Check that the warning isn't printed. >> +test_run:grep_log('cfg_tester9', version_warning, 1000) =3D=3D nil >> +test_run:cmd("stop server cfg_tester9") >> +test_run:cmd("cleanup server cfg_tester9") >> diff --git a/test/box/lua/cfg_test8.lua b/test/box/lua/cfg_test8.lua >> new file mode 100644 >> index 000000000..c61b86ae3 >> --- /dev/null >> +++ b/test/box/lua/cfg_test8.lua >> @@ -0,0 +1,9 @@ >> +#!/usr/bin/env tarantool >> +os =3D require('os') >> + >> +box.cfg{ >> + listen =3D os.getenv("LISTEN"), >> + read_only =3D true >> +} >> + >> +require('console').listen(os.getenv('ADMIN')) >=20 > --=20 > Serge Petrenko >=20 commit ca9744ddab1f04663ef5fe0c1e7dc872cf6d55fd Author: Sergey Voinov Date: Wed Dec 11 17:28:39 2019 +0300 box: check schema version after tarantool update =20 Check schema version (stored in box.space._schema) on start and print a warning if it doesn't match last available schema version. It is needed because some users forget to call box.schema.upgrade() after Tarantool update and get stuck with an old schema version until they encounter some hard to debug problems. =20 Closes #4574 =20 Co-developed-by: Roman Khabibov diff --git a/src/box/lua/load_cfg.lua b/src/box/lua/load_cfg.lua index 76e2e92c2..770442052 100644 --- a/src/box/lua/load_cfg.lua +++ b/src/box/lua/load_cfg.lua @@ -702,6 +702,18 @@ local function load_cfg(cfg) box_configured =3D nil =20 box_is_configured =3D true + + -- Check if schema version matches Tarantool version and print + -- warning if it's not (in case user forgot to call + -- box.schema.upgrade()). + local needs, schema_version_str =3D private.schema_needs_upgrade() + if needs then + local msg =3D string.format( + 'Your schema version is %s while Tarantool %s requires a = more'.. + ' recent schema version. Please, consider using box.'.. + 'schema.upgrade().', schema_version_str, box.info.version) + log.warn(msg) + end end box.cfg =3D locked(load_cfg) =20 diff --git a/src/box/lua/upgrade.lua b/src/box/lua/upgrade.lua index add791cd7..a86a0d410 100644 --- a/src/box/lua/upgrade.lua +++ b/src/box/lua/upgrade.lua @@ -973,6 +973,21 @@ end =20 = --------------------------------------------------------------------------= ------ =20 +local handlers =3D { + {version =3D mkversion(1, 7, 6), func =3D upgrade_to_1_7_6, auto =3D = true}, + {version =3D mkversion(1, 7, 7), func =3D upgrade_to_1_7_7, auto =3D = true}, + {version =3D mkversion(1, 10, 0), func =3D upgrade_to_1_10_0, auto = =3D true}, + {version =3D mkversion(1, 10, 2), func =3D upgrade_to_1_10_2, auto = =3D true}, + {version =3D mkversion(2, 1, 0), func =3D upgrade_to_2_1_0, auto =3D = true}, + {version =3D mkversion(2, 1, 1), func =3D upgrade_to_2_1_1, auto =3D = true}, + {version =3D mkversion(2, 1, 2), func =3D upgrade_to_2_1_2, auto =3D = true}, + {version =3D mkversion(2, 1, 3), func =3D upgrade_to_2_1_3, auto =3D = true}, + {version =3D mkversion(2, 2, 1), func =3D upgrade_to_2_2_1, auto =3D = true}, + {version =3D mkversion(2, 3, 0), func =3D upgrade_to_2_3_0, auto =3D = true}, + {version =3D mkversion(2, 3, 1), func =3D upgrade_to_2_3_1, auto =3D = true}, +} + +-- Schema version of the snapshot. local function get_version() local version =3D box.space._schema:get{'version'} if version =3D=3D nil then @@ -982,7 +997,19 @@ local function get_version() local minor =3D version[3] local patch =3D version[4] or 0 =20 - return mkversion(major, minor, patch) + return mkversion(major, minor, patch), + string.format("%s.%s.%s", major, minor, patch) +end + +local function schema_needs_upgrade() + -- Schema needs upgrade if current schema version is greater + -- than schema version of the snapshot. + local schema_version, schema_version_str =3D get_version() + if schema_version ~=3D nil and + handlers[#handlers].version > schema_version then + return true, schema_version_str + end + return false end =20 local function upgrade(options) @@ -995,20 +1022,6 @@ local function upgrade(options) return end =20 - local handlers =3D { - {version =3D mkversion(1, 7, 6), func =3D upgrade_to_1_7_6, = auto =3D true}, - {version =3D mkversion(1, 7, 7), func =3D upgrade_to_1_7_7, = auto =3D true}, - {version =3D mkversion(1, 10, 0), func =3D upgrade_to_1_10_0, = auto =3D true}, - {version =3D mkversion(1, 10, 2), func =3D upgrade_to_1_10_2, = auto =3D true}, - {version =3D mkversion(2, 1, 0), func =3D upgrade_to_2_1_0, = auto =3D true}, - {version =3D mkversion(2, 1, 1), func =3D upgrade_to_2_1_1, = auto =3D true}, - {version =3D mkversion(2, 1, 2), func =3D upgrade_to_2_1_2, = auto =3D true}, - {version =3D mkversion(2, 1, 3), func =3D upgrade_to_2_1_3, = auto =3D true}, - {version =3D mkversion(2, 2, 1), func =3D upgrade_to_2_2_1, = auto =3D true}, - {version =3D mkversion(2, 3, 0), func =3D upgrade_to_2_3_0, = auto =3D true}, - {version =3D mkversion(2, 3, 1), func =3D upgrade_to_2_3_1, = auto =3D true}, - } - for _, handler in ipairs(handlers) do if version >=3D handler.version then goto continue @@ -1047,3 +1060,4 @@ end =20 box.schema.upgrade =3D upgrade; box.internal.bootstrap =3D bootstrap; +box.internal.schema_needs_upgrade =3D schema_needs_upgrade; diff --git a/test/box/cfg.result b/test/box/cfg.result index 4ad3c6493..5ca6ce72b 100644 --- a/test/box/cfg.result +++ b/test/box/cfg.result @@ -656,3 +656,53 @@ test_run:cmd("cleanup server cfg_tester7") | --- | - true | ... + +-- +-- gh-4574: Check schema version after Tarantool update. +-- +test_run:cmd('create server cfg_tester8 with script =3D = "box/lua/cfg_test8.lua", workdir=3D"sql/upgrade/2.1.0/"') + | --- + | - true + | ... +test_run:cmd("start server cfg_tester8") + | --- + | - true + | ... +--- Check that the warning is printed. +version_warning =3D "Please, consider using box.schema.upgrade()." + | --- + | ... +test_run:wait_log('cfg_tester8', version_warning, 1000, 1.0) ~=3D nil + | --- + | - true + | ... +test_run:cmd("stop server cfg_tester8") + | --- + | - true + | ... +test_run:cmd("cleanup server cfg_tester8") + | --- + | - true + | ... + +test_run:cmd('create server cfg_tester9 with script =3D = "box/lua/cfg_test1.lua"') + | --- + | - true + | ... +test_run:cmd("start server cfg_tester9") + | --- + | - true + | ... +--- Check that the warning isn't printed. +test_run:wait_log('cfg_tester9', version_warning, 1000, 1.0) =3D=3D nil + | --- + | - true + | ... +test_run:cmd("stop server cfg_tester9") + | --- + | - true + | ... +test_run:cmd("cleanup server cfg_tester9") + | --- + | - true + | ... diff --git a/test/box/cfg.test.lua b/test/box/cfg.test.lua index 56018b1a0..74100adaa 100644 --- a/test/box/cfg.test.lua +++ b/test/box/cfg.test.lua @@ -159,3 +159,21 @@ test_run:grep_log('cfg_tester7', 'set = \'replication\' configuration option to', test_run:grep_log('cfg_tester7', 'test%-cluster%-cookie', 1000) test_run:cmd("stop server cfg_tester7") test_run:cmd("cleanup server cfg_tester7") + +-- +-- gh-4574: Check schema version after Tarantool update. +-- +test_run:cmd('create server cfg_tester8 with script =3D = "box/lua/cfg_test8.lua", workdir=3D"sql/upgrade/2.1.0/"') +test_run:cmd("start server cfg_tester8") +--- Check that the warning is printed. +version_warning =3D "Please, consider using box.schema.upgrade()." +test_run:wait_log('cfg_tester8', version_warning, 1000, 1.0) ~=3D nil +test_run:cmd("stop server cfg_tester8") +test_run:cmd("cleanup server cfg_tester8") + +test_run:cmd('create server cfg_tester9 with script =3D = "box/lua/cfg_test1.lua"') +test_run:cmd("start server cfg_tester9") +--- Check that the warning isn't printed. +test_run:wait_log('cfg_tester9', version_warning, 1000, 1.0) =3D=3D nil +test_run:cmd("stop server cfg_tester9") +test_run:cmd("cleanup server cfg_tester9") diff --git a/test/box/lua/cfg_test8.lua b/test/box/lua/cfg_test8.lua new file mode 100644 index 000000000..c61b86ae3 --- /dev/null +++ b/test/box/lua/cfg_test8.lua @@ -0,0 +1,9 @@ +#!/usr/bin/env tarantool +os =3D require('os') + +box.cfg{ + listen =3D os.getenv("LISTEN"), + read_only =3D true +} + +require('console').listen(os.getenv('ADMIN')) diff --git a/test/box/stat.result b/test/box/stat.result index 55f29fe59..1ed243410 100644 --- a/test/box/stat.result +++ b/test/box/stat.result @@ -24,7 +24,7 @@ box.stat.REPLACE.total ... box.stat.SELECT.total --- -- 1 +- 2 ... box.stat.ERROR.total --- @@ -59,7 +59,7 @@ box.stat.REPLACE.total ... box.stat.SELECT.total --- -- 5 +- 6 ... -- check exceptions space:get('Impossible value') @@ -77,14 +77,14 @@ space:get(1) ... box.stat.SELECT.total --- -- 6 +- 7 ... space:get(11) --- ... box.stat.SELECT.total --- -- 7 +- 8 ... space:select(5) --- @@ -92,7 +92,7 @@ space:select(5) ... box.stat.SELECT.total --- -- 8 +- 9 ... space:select(15) --- @@ -100,14 +100,14 @@ space:select(15) ... box.stat.SELECT.total --- -- 9 +- 10 ... for _ in space:pairs() do end --- ... box.stat.SELECT.total --- -- 10 +- 11 ... -- reset box.stat.reset() @@ -157,7 +157,7 @@ box.stat.REPLACE.total ... box.stat.SELECT.total --- -- 1 +- 2 ... box.stat.ERROR.total =E2=80=94