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/23 13:05:26 UTC
svn commit: r1126431 - in /couchdb/branches/1.0.x/src/couchdb: couch_doc.erl
couch_httpd_db.erl
Author: fdmanana
Date: Mon May 23 11:05:26 2011
New Revision: 1126431
URL: http://svn.apache.org/viewvc?rev=1126431&view=rev
Log:
Merged revision 1126426 from trunk
Fix timing issues in the doc PUT multipart/related API
Two issues were present:
1) the handler replied to the request before the multipart parser consumed
all the request's data, causing a subsequent request in the same connection
to consume the remaining data from the multipart/related request;
2) the data function passed to the multipart parser could consume, and
discard, all or part of the data from a subsequent request in the same
connection.
This closes COUCHDB-1174.
Modified:
couchdb/branches/1.0.x/src/couchdb/couch_doc.erl
couchdb/branches/1.0.x/src/couchdb/couch_httpd_db.erl
Modified: couchdb/branches/1.0.x/src/couchdb/couch_doc.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/1.0.x/src/couchdb/couch_doc.erl?rev=1126431&r1=1126430&r2=1126431&view=diff
==============================================================================
--- couchdb/branches/1.0.x/src/couchdb/couch_doc.erl (original)
+++ couchdb/branches/1.0.x/src/couchdb/couch_doc.erl Mon May 23 11:05:26 2011
@@ -443,11 +443,13 @@ atts_to_mp([Att | RestAtts], Boundary, W
doc_from_multi_part_stream(ContentType, DataFun) ->
- Self = self(),
+ Parent = self(),
Parser = spawn_link(fun() ->
- couch_httpd:parse_multipart_request(ContentType, DataFun,
- fun(Next)-> mp_parse_doc(Next, []) end),
- unlink(Self)
+ {<<"--">>, _, _} = couch_httpd:parse_multipart_request(
+ ContentType, DataFun,
+ fun(Next) -> mp_parse_doc(Next, []) end),
+ unlink(Parent),
+ Parent ! {self(), finished}
end),
Parser ! {get_doc_bytes, self()},
receive
@@ -465,7 +467,11 @@ doc_from_multi_part_stream(ContentType,
(A) ->
A
end, Doc#doc.atts),
- {ok, Doc#doc{atts=Atts2}}
+ WaitFun = fun() ->
+ receive {Parser, finished} -> ok end,
+ erlang:put(mochiweb_request_recv, true)
+ end,
+ {ok, Doc#doc{atts=Atts2}, WaitFun}
end.
mp_parse_doc({headers, H}, []) ->
Modified: couchdb/branches/1.0.x/src/couchdb/couch_httpd_db.erl
URL: http://svn.apache.org/viewvc/couchdb/branches/1.0.x/src/couchdb/couch_httpd_db.erl?rev=1126431&r1=1126430&r2=1126431&view=diff
==============================================================================
--- couchdb/branches/1.0.x/src/couchdb/couch_httpd_db.erl (original)
+++ couchdb/branches/1.0.x/src/couchdb/couch_httpd_db.erl Mon May 23 11:05:26 2011
@@ -683,10 +683,12 @@ 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} = couch_doc:doc_from_multi_part_stream(ContentType,
- fun() -> receive_request_data(Req) end),
+ {ok, Doc0, WaitFun} = couch_doc:doc_from_multi_part_stream(
+ ContentType, fun() -> receive_request_data(Req) end),
Doc = couch_doc_from_req(Req, DocId, Doc0),
- update_doc(Req, Db, DocId, Doc, RespHeaders, UpdateType);
+ Result = update_doc(Req, Db, DocId, Doc, RespHeaders, UpdateType),
+ WaitFun(),
+ Result;
_Else ->
case couch_httpd:qs_value(Req, "batch") of
"ok" ->
@@ -804,7 +806,14 @@ send_docs_multipart(Req, Results, Option
couch_httpd:last_chunk(Resp).
receive_request_data(Req) ->
- {couch_httpd:recv(Req, 0), fun() -> receive_request_data(Req) end}.
+ receive_request_data(Req, couch_httpd:body_length(Req)).
+
+receive_request_data(Req, LenLeft) when LenLeft > 0 ->
+ Len = erlang:min(4096, LenLeft),
+ Data = couch_httpd:recv(Req, Len),
+ {Data, fun() -> receive_request_data(Req, LenLeft - iolist_size(Data)) end};
+receive_request_data(_Req, _) ->
+ throw(<<"expected more data">>).
update_doc_result_to_json({{Id, Rev}, Error}) ->
{_Code, Err, Msg} = couch_httpd:error_info(Error),