From e206d061ebad2853b64af473cdb4d9d0b0e00d73 Mon Sep 17 00:00:00 2001 From: "Paul J. Davis" Date: Wed, 5 Dec 2018 13:42:47 -0600 Subject: [PATCH 1/2] Add `couch_db:get_design_doc/2` This adds an API call for looking up a single design doc regardless of whether the database is clustered or not. --- src/couch/src/couch_db.erl | 14 ++++++++++++++ src/couch/src/couch_util.erl | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/src/couch/src/couch_db.erl b/src/couch/src/couch_db.erl index 0d435c2ffef..2304ba1fa56 100644 --- a/src/couch/src/couch_db.erl +++ b/src/couch/src/couch_db.erl @@ -77,6 +77,7 @@ get_full_doc_info/2, get_full_doc_infos/2, get_missing_revs/2, + get_design_doc/2, get_design_docs/1, get_design_doc_count/1, get_purge_infos/2, @@ -608,6 +609,19 @@ get_db_info(Db) -> ], {ok, InfoList}. +get_design_doc(#db{name = <<"shards/", _/binary>> = ShardDbName}, DDocId0) -> + DDocId = couch_util:normalize_ddoc_id(DDocId0), + DbName = mem3:dbname(ShardDbName), + {_, Ref} = spawn_monitor(fun() -> + exit(fabric:open_doc(DbName, DDocId, [])) + end), + receive {'DOWN', Ref, _, _, Response} -> + Response + end; +get_design_doc(#db{} = Db, DDocId0) -> + DDocId = couch_util:normalize_ddoc_id(DDocId0), + couch_db:open_doc_int(Db, DDocId, [ejson_body]). + get_design_docs(#db{name = <<"shards/", _/binary>> = ShardDbName}) -> DbName = mem3:dbname(ShardDbName), {_, Ref} = spawn_monitor(fun() -> exit(fabric:design_docs(DbName)) end), diff --git a/src/couch/src/couch_util.erl b/src/couch/src/couch_util.erl index 3efec84a9b2..ddd24aab000 100644 --- a/src/couch/src/couch_util.erl +++ b/src/couch/src/couch_util.erl @@ -27,6 +27,7 @@ -export([reorder_results/2]). -export([url_strip_password/1]). -export([encode_doc_id/1]). +-export([normalize_ddoc_id/1]). -export([with_db/2]). -export([rfc1123_date/0, rfc1123_date/1]). -export([integer_to_boolean/1, boolean_to_integer/1]). @@ -543,6 +544,10 @@ encode_doc_id(<<"_local/", Rest/binary>>) -> encode_doc_id(Id) -> url_encode(Id). +normalize_ddoc_id(<<"_design/", _/binary>> = DDocId) -> + DDocId; +normalize_ddoc_id(DDocId) when is_binary(DDocId) -> + <<"_design/", DDocId/binary>>. with_db(DbName, Fun) when is_binary(DbName) -> case couch_db:open_int(DbName, [?ADMIN_CTX]) of From 0a2e8e8ebd13246a31bda84b1a47b86849fc1a67 Mon Sep 17 00:00:00 2001 From: "Paul J. Davis" Date: Wed, 5 Dec 2018 13:43:31 -0600 Subject: [PATCH 2/2] Avoid calls to `fabric:design_docs/1` The underlying clustered _all_docs call can cause significant extra load during compaction. --- src/couch_mrview/src/couch_mrview_index.erl | 26 +++------------------ 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/couch_mrview/src/couch_mrview_index.erl b/src/couch_mrview/src/couch_mrview_index.erl index 4718b562d2b..d3bcfe04bc6 100644 --- a/src/couch_mrview/src/couch_mrview_index.erl +++ b/src/couch_mrview/src/couch_mrview_index.erl @@ -226,16 +226,15 @@ verify_index_exists(DbName, Props) -> if Type =/= <<"mrview">> -> false; true -> DDocId = couch_util:get_value(<<"ddoc_id">>, Props), couch_util:with_db(DbName, fun(Db) -> - {ok, DesignDocs} = couch_db:get_design_docs(Db), - case get_ddoc(DbName, DesignDocs, DDocId) of - #doc{} = DDoc -> + case couch_db:get_design_doc(Db, DDocId) of + {ok, #doc{} = DDoc} -> {ok, IdxState} = couch_mrview_util:ddoc_to_mrst( DbName, DDoc), IdxSig = IdxState#mrst.sig, SigInLocal = couch_util:get_value( <<"signature">>, Props), couch_index_util:hexsig(IdxSig) == SigInLocal; - not_found -> + {not_found, _} -> false end end) @@ -245,25 +244,6 @@ verify_index_exists(DbName, Props) -> end. -get_ddoc(<<"shards/", _/binary>> = _DbName, DesignDocs, DDocId) -> - DDocs = [couch_doc:from_json_obj(DD) || DD <- DesignDocs], - case lists:keyfind(DDocId, #doc.id, DDocs) of - #doc{} = DDoc -> DDoc; - false -> not_found - end; -get_ddoc(DbName, DesignDocs, DDocId) -> - couch_util:with_db(DbName, fun(Db) -> - case lists:keyfind(DDocId, #full_doc_info.id, DesignDocs) of - #full_doc_info{} = DDocInfo -> - {ok, DDoc} = couch_db:open_doc_int( - Db, DDocInfo, [ejson_body]), - DDoc; - false -> - not_found - end - end). - - ensure_local_purge_docs(DbName, DDocs) -> couch_util:with_db(DbName, fun(Db) -> lists:foreach(fun(DDoc) ->