diff --git a/src/box/vinyl.c b/src/box/vinyl.c index d5d5adc11cc9d28b21a37e6826d3beea89b3d2fa..1ceeb847cf88ae3a0960dd84a11cbb106fdca63d 100644 --- a/src/box/vinyl.c +++ b/src/box/vinyl.c @@ -54,7 +54,6 @@ #include <small/region.h> #include <small/mempool.h> -#include "coio_file.h" #include "coio_task.h" #include "cbus.h" #include "histogram.h" @@ -3340,20 +3339,8 @@ vy_gc_cb(const struct vy_log_record *record, void *cb_arg) (long long)record->run_id); goto out;}); /* Try to delete files. */ - bool forget = true; - char path[PATH_MAX]; - for (int type = 0; type < vy_file_MAX; type++) { - vy_run_snprint_path(path, sizeof(path), arg->env->path, - arg->space_id, arg->index_id, - record->run_id, type); - say_info("removing %s", path); - if (coio_unlink(path) < 0 && errno != ENOENT) { - say_syserror("error while removing %s", path); - forget = false; - } - } - - if (!forget) + if (vy_run_remove_files(arg->env->path, arg->space_id, + arg->index_id, record->run_id) != 0) goto out; /* Forget the run on success. */ diff --git a/src/box/vy_run.c b/src/box/vy_run.c index fa4c5f9b9f0a9b1ba6320bd95347b975ed497939..32fdd67bc9011f2cce3a28506db2ad22ced72fc1 100644 --- a/src/box/vy_run.c +++ b/src/box/vy_run.c @@ -37,6 +37,7 @@ #include "fio.h" #include "cbus.h" #include "memory.h" +#include "coio_file.h" #include "replication.h" #include "tuple_hash.h" /* for bloom filter */ @@ -2604,6 +2605,24 @@ vy_run_rebuild_index(struct vy_run *run, const char *dir, return -1; } +int +vy_run_remove_files(const char *dir, uint32_t space_id, + uint32_t iid, int64_t run_id) +{ + int ret = 0; + char path[PATH_MAX]; + for (int type = 0; type < vy_file_MAX; type++) { + vy_run_snprint_path(path, sizeof(path), dir, + space_id, iid, run_id, type); + say_info("removing %s", path); + if (coio_unlink(path) < 0 && errno != ENOENT) { + say_syserror("error while removing %s", path); + ret = -1; + } + } + return ret; +} + /** * Read a page with stream->page_no from the run and save it in stream->page. * Support function of slice stream. diff --git a/src/box/vy_run.h b/src/box/vy_run.h index cf0569c271cfd43ef416713a13b80f70cf878245..1dde0776628cef8749b4625b77de94126a4ac92f 100644 --- a/src/box/vy_run.h +++ b/src/box/vy_run.h @@ -403,6 +403,15 @@ vy_run_snprint_path(char *buf, int size, const char *dir, return total; } +/** + * Remove all files (data, index) corresponding to a run + * with the given id. Return 0 on success, -1 if unlink() + * failed. + */ +int +vy_run_remove_files(const char *dir, uint32_t space_id, + uint32_t iid, int64_t run_id); + int vy_run_write(struct vy_run *run, const char *dirpath, uint32_t space_id, uint32_t iid, diff --git a/src/box/vy_scheduler.c b/src/box/vy_scheduler.c index 35fc24f43c847eaca85affa3a3731905351c9c81..df8eb87fabd1ab54760edf41804201a4c3eaf041 100644 --- a/src/box/vy_scheduler.c +++ b/src/box/vy_scheduler.c @@ -1071,6 +1071,23 @@ vy_task_compact_complete(struct vy_scheduler *scheduler, struct vy_task *task) return -1; } + if (gc_lsn < 0) { + /* + * If there is no last snapshot, i.e. we are in + * the middle of join, we can delete compacted + * run files right away. + */ + vy_log_tx_begin(); + rlist_foreach_entry(run, &unused_runs, in_unused) { + if (vy_run_remove_files(index->env->path, + index->space_id, index->id, + run->id) == 0) { + vy_log_forget_run(run->id); + } + } + vy_log_tx_try_commit(); + } + /* * Account the new run if it is not empty, * otherwise discard it. diff --git a/test/vinyl/join_quota.lua b/test/vinyl/replica_quota.lua similarity index 100% rename from test/vinyl/join_quota.lua rename to test/vinyl/replica_quota.lua diff --git a/test/vinyl/replica_quota.result b/test/vinyl/replica_quota.result index b85c7398b9455a0b9c41510f739d5c2697355ec4..460cc1e61eeca71347ffd149081e2eefeb1ba9b3 100644 --- a/test/vinyl/replica_quota.result +++ b/test/vinyl/replica_quota.result @@ -10,7 +10,7 @@ box.schema.user.grant('guest', 'replication') s = box.schema.space.create('test', { engine = 'vinyl' }) --- ... -_ = s:create_index('pk') +_ = s:create_index('pk', {run_count_per_level = 1}) --- ... -- Send > 2 MB to replica. @@ -36,7 +36,7 @@ for i = 1001,2000 do s:insert{i, pad} end -- a dump to complete and hence would result in bootstrap failure -- were the timeout not ignored. -- -_ = test_run:cmd("create server replica with rpl_master=default, script='vinyl/join_quota.lua'") +_ = test_run:cmd("create server replica with rpl_master=default, script='vinyl/replica_quota.lua'") --- ... _ = test_run:cmd("start server replica") @@ -58,6 +58,30 @@ _ = test_run:cmd("start server replica") _ = test_run:wait_lsn('replica', 'default') --- ... +-- During join we remove compacted run files immediately (gh-3162). +-- Check that we don't delete files that are still in use. +_ = test_run:cmd("stop server replica") +--- +... +_ = test_run:cmd("cleanup server replica") +--- +... +box.snapshot() +--- +- ok +... +for i = 3001,4000 do s:insert{i, pad} end +--- +... +_ = test_run:cmd("start server replica") -- join +--- +... +_ = test_run:cmd("stop server replica") +--- +... +_ = test_run:cmd("start server replica") -- recovery +--- +... _ = test_run:cmd("stop server replica") --- ... diff --git a/test/vinyl/replica_quota.test.lua b/test/vinyl/replica_quota.test.lua index ab89c1bc719bf04fd234064e9cd0008e0c86494a..eade6f2f7548e488d194817c4beb363d6f772de8 100644 --- a/test/vinyl/replica_quota.test.lua +++ b/test/vinyl/replica_quota.test.lua @@ -4,7 +4,7 @@ box.schema.user.grant('guest', 'read,write,execute', 'universe') box.schema.user.grant('guest', 'replication') s = box.schema.space.create('test', { engine = 'vinyl' }) -_ = s:create_index('pk') +_ = s:create_index('pk', {run_count_per_level = 1}) -- Send > 2 MB to replica. pad = string.rep('x', 1100) @@ -21,7 +21,7 @@ for i = 1001,2000 do s:insert{i, pad} end -- a dump to complete and hence would result in bootstrap failure -- were the timeout not ignored. -- -_ = test_run:cmd("create server replica with rpl_master=default, script='vinyl/join_quota.lua'") +_ = test_run:cmd("create server replica with rpl_master=default, script='vinyl/replica_quota.lua'") _ = test_run:cmd("start server replica") _ = test_run:wait_lsn('replica', 'default') @@ -31,6 +31,18 @@ for i = 2001,3000 do s:insert{i, pad} end _ = test_run:cmd("start server replica") _ = test_run:wait_lsn('replica', 'default') +-- During join we remove compacted run files immediately (gh-3162). +-- Check that we don't delete files that are still in use. +_ = test_run:cmd("stop server replica") +_ = test_run:cmd("cleanup server replica") + +box.snapshot() +for i = 3001,4000 do s:insert{i, pad} end + +_ = test_run:cmd("start server replica") -- join +_ = test_run:cmd("stop server replica") +_ = test_run:cmd("start server replica") -- recovery + _ = test_run:cmd("stop server replica") _ = test_run:cmd("cleanup server replica")