From cff79d01f26f2a4917204fcf3dd8d4d4d57271bc Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Tue, 28 Sep 2010 16:49:58 +0000 Subject: Replicator fix: for a filtered replication, the replication ID should take into account the filter function's code and not only its name. Closes COUCHDB-892. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1002259 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_rep.erl | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/couchdb/couch_rep.erl b/src/couchdb/couch_rep.erl index 6dbd3c7c..85ecc99e 100644 --- a/src/couchdb/couch_rep.erl +++ b/src/couchdb/couch_rep.erl @@ -486,14 +486,14 @@ make_replication_id({Props}, UserCtx, 2) -> Port = mochiweb_socket_server:get(couch_httpd, port), Src = get_rep_endpoint(UserCtx, ?getv(<<"source">>, Props)), Tgt = get_rep_endpoint(UserCtx, ?getv(<<"target">>, Props)), - maybe_append_filters({Props}, [HostName, Port, Src, Tgt]); + maybe_append_filters({Props}, [HostName, Port, Src, Tgt], UserCtx); make_replication_id({Props}, UserCtx, 1) -> {ok, HostName} = inet:gethostname(), Src = get_rep_endpoint(UserCtx, ?getv(<<"source">>, Props)), Tgt = get_rep_endpoint(UserCtx, ?getv(<<"target">>, Props)), - maybe_append_filters({Props}, [HostName, Src, Tgt]). + maybe_append_filters({Props}, [HostName, Src, Tgt], UserCtx). -maybe_append_filters({Props}, Base) -> +maybe_append_filters({Props}, Base, UserCtx) -> Base2 = Base ++ case ?getv(<<"filter">>, Props) of undefined -> @@ -504,10 +504,20 @@ maybe_append_filters({Props}, Base) -> [DocIds] end; Filter -> - [Filter, ?getv(<<"query_params">>, Props, {[]})] + [filter_code(Filter, Props, UserCtx), + ?getv(<<"query_params">>, Props, {[]})] end, couch_util:to_hex(couch_util:md5(term_to_binary(Base2))). +filter_code(Filter, Props, UserCtx) -> + {match, [DDocName, FilterName]} = + re:run(Filter, "(.*?)/(.*)", [{capture, [1, 2], binary}]), + ProxyParams = parse_proxy_params(?getv(<<"proxy">>, Props, [])), + Source = open_db(?getv(<<"source">>, Props), UserCtx, ProxyParams), + {ok, #doc{body = Body}} = open_doc(Source, <<"_design/", DDocName/binary>>), + Code = couch_util:get_nested_json_value(Body, [<<"filters">>, FilterName]), + re:replace(Code, "^\s*(.*?)\s*$", "\\1", [{return, binary}]). + maybe_add_trailing_slash(Url) -> re:replace(Url, "[^/]$", "&/", [{return, list}]). @@ -556,26 +566,27 @@ fold_replication_logs([Db|Rest]=Dbs, Vsn, LogId, NewId, RepProps, UserCtx, [MigratedLog|Acc]) end. -open_replication_log(#http_db{}=Db, DocId) -> - Req = Db#http_db{resource=couch_util:encode_doc_id(DocId)}, - case couch_rep_httpc:request(Req) of - {[{<<"error">>, _}, {<<"reason">>, _}]} -> - ?LOG_DEBUG("didn't find a replication log for ~s", [Db#http_db.url]), - {error, not_found}; - Doc -> - ?LOG_DEBUG("found a replication log for ~s", [Db#http_db.url]), - {ok, couch_doc:from_json_obj(Doc)} - end; open_replication_log(Db, DocId) -> - case couch_db:open_doc(Db, DocId, []) of + case open_doc(Db, DocId) of {ok, Doc} -> - ?LOG_DEBUG("found a replication log for ~s", [Db#db.name]), + ?LOG_DEBUG("found a replication log for ~s", [dbname(Db)]), {ok, Doc}; _ -> - ?LOG_DEBUG("didn't find a replication log for ~s", [Db#db.name]), + ?LOG_DEBUG("didn't find a replication log for ~s", [dbname(Db)]), {error, not_found} end. +open_doc(#http_db{} = Db, DocId) -> + Req = Db#http_db{resource = couch_util:encode_doc_id(DocId)}, + case couch_rep_httpc:request(Req) of + {[{<<"error">>, _}, {<<"reason">>, _}]} -> + {error, not_found}; + Doc -> + {ok, couch_doc:from_json_obj(Doc)} + end; +open_doc(Db, DocId) -> + couch_db:open_doc(Db, DocId). + open_db(Props, UserCtx, ProxyParams) -> open_db(Props, UserCtx, ProxyParams, false). -- cgit v1.2.3