From 0c6aa8b68ad386a248926dba3ee356f6279013a6 Mon Sep 17 00:00:00 2001 From: ILYA Khlopotov Date: Wed, 29 Aug 2018 06:07:20 -0700 Subject: [PATCH] Improve cleanup_index_files The previous implementation was based on a search using {view_index_dir}/.shards/*/{db_name}.[0-9]*_design/mrview/* This wildcard includes all shards for all indexes of all databases. This PR changes the search to look at index_directory of a database. --- src/couch/test/couchdb_mrview_tests.erl | 53 +++++++++++++++++++++++++ src/fabric/src/fabric.erl | 6 ++- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/couch/test/couchdb_mrview_tests.erl b/src/couch/test/couchdb_mrview_tests.erl index 402df02a620..2549528be6d 100644 --- a/src/couch/test/couchdb_mrview_tests.erl +++ b/src/couch/test/couchdb_mrview_tests.erl @@ -92,6 +92,19 @@ mrview_query_test_() -> } }. +mrview_cleanup_index_files_test_() -> + { + "Check index files cleanup", + { + setup, + fun start/0, fun teardown/1, + [ + make_test_case(clustered, [fun should_cleanup_index_files/2]) + ] + } + }. + + make_test_case(Mod, Funs) -> { lists:flatten(io_lib:format("~s", [Mod])), @@ -129,6 +142,46 @@ should_return_400_for_wrong_order_of_keys(_PortType, {Host, DbName}) -> ok end). +should_cleanup_index_files(_PortType, {Host, DbName}) -> + ?_test(begin + IndexWildCard = [ + config:get("couchdb", "view_index_dir"), + "/.shards/*/", + DbName, + ".[0-9]*_design/mrview/*" + ], + ReqUrl = Host ++ "/" ++ DbName ++ "/_design/foo/_view/view1", + {ok, Status0, _Headers0, Body0} = test_request:get(ReqUrl, [?AUTH]), + FileList0 = filelib:wildcard(IndexWildCard), + ?assertNotEqual([], FileList0), + + % It is hard to simulate inactive view. + % Since couch_mrview:cleanup is called on view definition change. + % That's why we just create extra files in place + ToDelete = lists:map(fun(FilePath) -> + ViewFile = filename:join([ + filename:dirname(FilePath), + "11111111111111111111111111111111.view"]), + file:write_file(ViewFile, <<>>), + ViewFile + end, FileList0), + FileList1 = filelib:wildcard(IndexWildCard), + ?assertEqual([], lists:usort(FileList1 -- (FileList0 ++ ToDelete))), + + CleanupUrl = Host ++ "/" ++ DbName ++ "/_view_cleanup", + {ok, Status1, _Headers1, Body1} = test_request:post( + CleanupUrl, [], <<>>, [?AUTH]), + test_util:wait(fun() -> + IndexFiles = filelib:wildcard(IndexWildCard), + case lists:usort(FileList0) == lists:usort(IndexFiles) of + false -> wait; + true -> ok + end + end), + ok + end). + + create_doc(backdoor, DbName, Id, Body) -> JsonDoc = couch_util:json_apply_field({<<"_id">>, Id}, Body), Doc = couch_doc:from_json_obj(JsonDoc), diff --git a/src/fabric/src/fabric.erl b/src/fabric/src/fabric.erl index cf9ad9428a9..36ed67154b3 100644 --- a/src/fabric/src/fabric.erl +++ b/src/fabric/src/fabric.erl @@ -485,8 +485,10 @@ cleanup_index_files(DbName) -> binary_to_list(couch_util:get_value(signature, Info)) end, [couch_doc:from_json_obj(DD) || DD <- DesignDocs]), - FileList = filelib:wildcard([config:get("couchdb", "view_index_dir"), - "/.shards/*/", couch_util:to_list(dbname(DbName)), ".[0-9]*_design/mrview/*"]), + FileList = lists:flatmap(fun(#shard{name = ShardName}) -> + IndexDir = couch_index_util:index_dir(mrview, ShardName), + filelib:wildcard([IndexDir, "/*"]) + end, mem3:local_shards(dbname(DbName))), DeleteFiles = if ActiveSigs =:= [] -> FileList; true -> {ok, RegExp} = re:compile([$(, string:join(ActiveSigs, "|"), $)]),