You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by fd...@apache.org on 2011/05/31 22:17:49 UTC

svn commit: r1129897 - in /couchdb/trunk/src/couchdb: couch_doc.erl couch_httpd_db.erl

Author: fdmanana
Date: Tue May 31 20:17:48 2011
New Revision: 1129897

URL: http://svn.apache.org/viewvc?rev=1129897&view=rev
Log:
Fixes to the doc PUT multipart API

Don't hold the connection forever if the document is rejected
by a validate_doc_update function. The solution is to discard
all the attachments' data if the document was rejected.

Modified:
    couchdb/trunk/src/couchdb/couch_doc.erl
    couchdb/trunk/src/couchdb/couch_httpd_db.erl

Modified: couchdb/trunk/src/couchdb/couch_doc.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_doc.erl?rev=1129897&r1=1129896&r2=1129897&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_doc.erl (original)
+++ couchdb/trunk/src/couchdb/couch_doc.erl Tue May 31 20:17:48 2011
@@ -18,6 +18,7 @@
 -export([validate_docid/1]).
 -export([doc_from_multi_part_stream/2]).
 -export([doc_to_multi_part_stream/5, len_doc_to_multi_part_stream/4]).
+-export([abort_multi_part_stream/1]).
 -export([to_path/1]).
 -export([mp_parse_doc/2]).
 -export([with_ejson_body/1, with_bin_body/1]).
@@ -520,7 +521,7 @@ doc_from_multi_part_stream(ContentType, 
             receive {Parser, finished} -> ok end,
             erlang:put(mochiweb_request_recv, true)
         end,
-        {ok, Doc#doc{atts=Atts2}, WaitFun}
+        {ok, Doc#doc{atts=Atts2}, WaitFun, Parser}
     end.
 
 mp_parse_doc({headers, H}, []) ->
@@ -553,6 +554,24 @@ mp_parse_atts(body_end) ->
     fun mp_parse_atts/1.
 
 
+abort_multi_part_stream(Parser) ->
+    abort_multi_part_stream(Parser, erlang:monitor(process, Parser)).
+
+abort_multi_part_stream(Parser, MonRef) ->
+    case is_process_alive(Parser) of
+    true ->
+        Parser ! {get_bytes, self()},
+        receive
+        {bytes, _Bytes} ->
+             abort_multi_part_stream(Parser, MonRef);
+        {'DOWN', MonRef, _, _, _} ->
+             ok
+        end;
+    false ->
+        erlang:demonitor(MonRef, [flush])
+    end.
+
+
 with_bin_body(#doc{body = Json} = Doc) when is_binary(Json) ->
     Doc;
 with_bin_body(#doc{body = EJson} = Doc) ->

Modified: couchdb/trunk/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_db.erl?rev=1129897&r1=1129896&r2=1129897&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_db.erl Tue May 31 20:17:48 2011
@@ -696,12 +696,18 @@ db_doc_req(#httpd{method='PUT'}=Req, Db,
     RespHeaders = [{"Location", Loc}],
     case couch_util:to_list(couch_httpd:header_value(Req, "Content-Type")) of
     ("multipart/related;" ++ _) = ContentType ->
-        {ok, Doc0, WaitFun} = couch_doc:doc_from_multi_part_stream(
+        {ok, Doc0, WaitFun, Parser} = couch_doc:doc_from_multi_part_stream(
             ContentType, fun() -> receive_request_data(Req) end),
         Doc = couch_doc_from_req(Req, DocId, Doc0),
-        Result = update_doc(Req, Db, DocId, Doc, RespHeaders, UpdateType),
-        WaitFun(),
-        Result;
+        try
+            Result = update_doc(Req, Db, DocId, Doc, RespHeaders, UpdateType),
+            WaitFun(),
+            Result
+        catch throw:Err ->
+            % Document rejected by a validate_doc_update function.
+            couch_doc:abort_multi_part_stream(Parser),
+            throw(Err)
+        end;
     _Else ->
         case couch_httpd:qs_value(Req, "batch") of
         "ok" ->