[Tarantool-patches] [PATCH] vinyl: fix recovery after deletion .run files

Nikita Pettik korablev at tarantool.org
Wed Jan 15 23:38:58 MSK 2020


On 13 Jan 14:27, Maksim Kulis wrote:
> While deletion .run files and recover with force_recovery=true we have to delete some logs which are responsible for deleted files so that we can recover later with force_recovery=false.

Please, limit commit message with 80 characters per line.

Is there any issue corresponding to the problem you are solving?
 
> ---
>  src/box/vy_lsm.c                   |  19 +-
>  test/vinyl/delete_run.result       | 302 +++++++++++++++++++++++++++++
>  test/vinyl/delete_run.test.lua     |  93 +++++++++
>  test/vinyl/force_recovery_true.lua |  11 ++
>  4 files changed, 421 insertions(+), 4 deletions(-)
>  create mode 100644 test/vinyl/delete_run.result
>  create mode 100644 test/vinyl/delete_run.test.lua
>  create mode 100644 test/vinyl/force_recovery_true.lua
> 
> diff --git a/src/box/vy_lsm.c b/src/box/vy_lsm.c
> index aa4bce9eb..a8abaf031 100644
> --- a/src/box/vy_lsm.c
> +++ b/src/box/vy_lsm.c
> @@ -374,6 +374,9 @@ vy_lsm_recover_run(struct vy_lsm *lsm, struct vy_run_recovery_info *run_info,
>  				  lsm->space_id, lsm->index_id,
>  				  lsm->cmp_def, lsm->key_def,
>  				  lsm->disk_format, &lsm->opts) != 0)) {
> +		vy_log_tx_begin();
> +		vy_log_drop_run(run_info->id, 0);
> +		vy_log_tx_try_commit();
>  		vy_run_unref(run);

You can re-use vy_run_discard().

>  		return NULL;
>  	}
> @@ -426,8 +429,14 @@ vy_lsm_recover_slice(struct vy_lsm *lsm, struct vy_range *range,
>  
>  	run = vy_lsm_recover_run(lsm, slice_info->run,
>  				 run_env, force_recovery);
> -	if (run == NULL)
> +	if (run == NULL) {
> +		if (force_recovery) {
> +			vy_log_tx_begin();
> +			vy_log_delete_slice(slice_info->id);
> +			vy_log_tx_try_commit();
> +		}
>  		goto out;
> +	}
>  
>  	slice = vy_slice_new(slice_info->id, run, begin, end, lsm->cmp_def);
>  	if (slice == NULL)
> @@ -486,9 +495,11 @@ vy_lsm_recover_range(struct vy_lsm *lsm,
>  	rlist_foreach_entry_reverse(slice_info, &range_info->slices, in_range) {
>  		if (vy_lsm_recover_slice(lsm, range, slice_info,
>  					 run_env, force_recovery) == NULL) {
> -			vy_range_delete(range);
> -			range = NULL;
> -			goto out;
> +			if (force_recovery == false) {

Nit: if (!force_recovery)

Why do we delete slice if force_recovery is enabled,
meanwhile delete range/run when force_recovery is disabled?

> +				vy_range_delete(range);
> +				range = NULL;
> +				goto out;
> +			}
>  		}
>  	}
>  	vy_lsm_add_range(lsm, range);
> diff --git a/test/vinyl/delete_run.test.lua b/test/vinyl/delete_run.test.lua
> new file mode 100644
> index 000000000..1e8ed39ed
> --- /dev/null
> +++ b/test/vinyl/delete_run.test.lua
> @@ -0,0 +1,93 @@
> +test_run = require('test_run').new()
> +fiber = require('fiber')
> +
> +-- Test 1

Could you comment these test cases explaining what's going on here?

> +test_run:cmd("create server test with script='vinyl/force_recovery_true.lua'")
> +test_run:cmd("start server test with args='1'")
> +test_run:cmd("switch test")
> +
> +test = box.schema.space.create('test', {engine='vinyl'})
> +_ = test:create_index('pk')
> +for i = 1, 10 do test:insert{i, i + 100} box.snapshot() end
> +test:select()
> +
> +fio = require ('fio')
> +for _, f in pairs(fio.glob(box.cfg.vinyl_dir .. '/' .. test.id .. '/0/*26*')) do fio.unlink(f) end
> +
> +test_run:cmd('switch default')
> +test_run:cmd('restart server test with args="1"')
> +test_run:cmd('switch test')
> +box.cfg.force_recovery
> +box.space.test:select()
> +
> +test_run:cmd('switch default')
> +test_run:cmd('restart server test with args="0"')
> +test_run:cmd('switch test')
> +box.cfg.force_recovery
> +box.space.test:select()
> +
> +test_run:cmd('switch default')
> +test_run:cmd('stop server test')
> +test_run:cmd('cleanup server test')
> +test_run:cmd('delete server test')
> +
> +-- Test 2
> +test_run = require('test_run').new()
> +test_run:cmd("create server test with script='vinyl/force_recovery_true.lua'")
> +test_run:cmd("start server test with args='1'")
> +test_run:cmd("switch test")
> +
> +test = box.schema.space.create('test', {engine='vinyl'})
> +_ = test:create_index('pk')
> +_ = test:insert{1, "123"}
> +test:select()
> +box.snapshot()
> +
> +fio = require ('fio')
> +for _, f in pairs(fio.glob(box.cfg.vinyl_dir .. '/' .. test.id .. '/0/*.index')) do fio.unlink(f) end
> +
> +test_run:cmd('switch default')
> +test_run:cmd('restart server test with args="1"')
> +test_run:cmd('switch test')
> +box.space.test:select()
> +
> +test_run:cmd('switch default')
> +test_run:cmd('restart server test with args="0"')
> +test_run:cmd('switch test')
> +box.space.test:select()
> +
> +test_run:cmd('switch default')
> +test_run:cmd('stop server test')
> +test_run:cmd('cleanup server test')
> +test_run:cmd('delete server test')
> +
> +-- Test3
> +
> +test_run = require('test_run').new()
> +test_run:cmd("create server test with script='vinyl/force_recovery_true.lua'")
> +test_run:cmd("start server test")
> +test_run:cmd("switch test")
> +
> +test = box.schema.space.create('test', {engine='vinyl'})
> +_ = test:create_index('pk')
> +_ = test:insert{1, "123"}
> +test:select(1)
> +box.snapshot()
> +
> +fio = require ('fio')
> +for _, f in pairs(fio.glob(box.cfg.vinyl_dir .. '/' .. test.id .. '/0/*.run')) do fio.unlink(f) end
> +
> +test_run:cmd('switch default')
> +test_run:cmd('restart server test with args="1"')
> +test_run:cmd('switch test')
> +box.space.test:select()
> +
> +test_run:cmd('switch default')
> +test_run:cmd('restart server test with args="0"')
> +test_run:cmd('switch test')
> +box.cfg.force_recovery
> +box.space.test:select()
> +test_run:cmd('switch default')
> +test_run:cmd('stop server test')
> +test_run:cmd('cleanup server test')
> +test_run:cmd('delete server test')
> diff --git a/test/vinyl/force_recovery_true.lua b/test/vinyl/force_recovery_true.lua
> new file mode 100644
> index 000000000..53414f22c
> --- /dev/null
> +++ b/test/vinyl/force_recovery_true.lua
> @@ -0,0 +1,11 @@
> +#!/usr/bin/env tarantool
> +
> +local fr = tonumber(arg[1])
> +box.cfg ({
> +    listen = os.getenv("LISTEN"),
> +    replication = os.getenv("MASTER"),
> +    vinyl_memory = 128 * 1024 * 1024,
> +    force_recovery = (fr == 1),
> +})
> +
> +require('console').listen(os.getenv('ADMIN'))
> -- 
> 2.17.1
> 


More information about the Tarantool-patches mailing list