From 46aa27fa674a4c1e590aeecd76123e4f91d78fd5 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Thu, 9 Mar 2017 18:03:14 +0000 Subject: [PATCH] Don't scan empty replicator databases Every account gets a _replicator database created by default, the burden of scanning them all is considerable. Don't start a changes reader if the database is empty (excluding the injected _design/replicator design document) BugzID: 84311 --- src/couch_replicator_manager.erl | 46 +++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/couch_replicator_manager.erl b/src/couch_replicator_manager.erl index 2bcad69..9f17087 100644 --- a/src/couch_replicator_manager.erl +++ b/src/couch_replicator_manager.erl @@ -266,9 +266,17 @@ handle_cast({resume_scan, DbName}, State) -> end, true = ets:insert(?DB_TO_SEQ, {DbName, Since, false}), ensure_rep_ddoc_exists(DbName), - Pid = start_changes_reader(DbName, Since, State#state.epoch), - couch_log:debug("Scanning ~s from update_seq ~p", [DbName, Since]), - [{DbName, Pid} | Pids] + case has_replication_docs(DbName) of + false -> + %% the database is empty save for the rep_ddoc, + %% don't bother scanning it. + couch_log:debug("ignoring empty ~s", [DbName]), + Pids; + true -> + Pid = start_changes_reader(DbName, Since, State#state.epoch), + couch_log:debug("Scanning ~s from update_seq ~p", [DbName, Since]), + [{DbName, Pid} | Pids] + end end, {noreply, State#state{rep_start_pids = NewPids}}; @@ -1005,6 +1013,38 @@ get_json_value(Key, Props, Default) when is_binary(Key) -> end. +has_replication_docs(DbName) -> + {ok, Db} = couch_db:open(DbName, []), + try + case couch_db:get_doc_count(Db) of + {ok, 0} -> + false; + {ok, 1} -> + case first_doc_id(Db) of + <<"_design/_replicator">> -> + false; + _Else -> + true + end; + _Else -> + true + end + after + couch_db:close(Db) + end. + + +first_doc_id(#db{} = Db) -> + Fun = fun + (#full_doc_info{deleted = true}, _Reds, Acc) -> + {ok, Acc}; + (FDI, _Reds, _Acc) -> + {stop, FDI#full_doc_info.id} + end, + {ok, _, Id} = couch_btree:fold(Db#db.id_tree, Fun, nil, []), + Id. + + -ifdef(TEST). -include_lib("couch/include/couch_eunit.hrl").