couchdb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Filipe Manana (JIRA)" <j...@apache.org>
Subject [jira] Commented: (COUCHDB-864) multipart/related PUT's always close the connection.
Date Sat, 21 Aug 2010 23:57:17 GMT

    [ https://issues.apache.org/jira/browse/COUCHDB-864?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12901113#action_12901113
] 

Filipe Manana commented on COUCHDB-864:
---------------------------------------

Hum, just added some logging code to mochiweb_request.erl where it decides whether to close
or not the socket:

diff --git a/src/mochiweb/mochiweb_http.erl b/src/mochiweb/mochiweb_http.erl
index f1821f4..47c5a27 100644
--- a/src/mochiweb/mochiweb_http.erl
+++ b/src/mochiweb/mochiweb_http.erl
@@ -144,9 +144,11 @@ after_response(Body, Req) ->
     Socket = Req:get(socket),
     case Req:should_close() of
         true ->
+            error_logger:info_report(couch_info, {"~nCLOSING SOCKET~n", []}),
             gen_tcp:close(Socket),
             exit(normal);
         false ->
+            error_logger:info_report(couch_info, {"~nNOT CLOSING SOCKET~n", []}),
             Req:cleanup(),
             ?MODULE:loop(Socket, Body)
     end.

Then, without the previous patch applied to CouchDB (the one with the put(mochiweb_request_recv,
true) in couch_httpd_db.erl) run the escript attached to this test.
I verified that mochiweb didn't close the socket immediately after the PUT request was served
but only on the next receive loop iteration - which does a socket receive call with a timeout
of 30 seconds.
So it seems it doesn't break an HTTP pipeline, unless consecutive requests take more than
30 seconds to be sent though the socket.

CouchDB's output:

[info] [<0.170.0>] 127.0.0.1 - - 'PUT' /testdb/doc1 201
[info] [<0.170.0>] 
NOT CLOSING SOCKET

The escript's output:

$ ./chunked.erl 
Received response:  <<"HTTP/1.1 201 Created\r\nServer: CouchDB/0.12.0ac533039-git (Erlang
OTP/R13B)\r\nLocation: http://127.0.0.1:5984/testdb/doc1\r\nEtag: \"1-0e0b0a89b2adea5c71e7db2799f7f7c1\"\r\nDate:
Sat, 21 Aug 2010 23:47:06 GMT\r\nContent-Type: text/plain;charset=utf-8\r\nContent-Length:
67\r\nCache-Control: must-revalidate\r\n\r\n{\"ok\":true,\"id\":\"doc1\",\"rev\":\"1-0e0b0a89b2adea5c71e7db2799f7f7c1\"}\n">>

Server closed connection after 30 seconds


Am I missing something?

> multipart/related PUT's always close the connection.
> ----------------------------------------------------
>
>                 Key: COUCHDB-864
>                 URL: https://issues.apache.org/jira/browse/COUCHDB-864
>             Project: CouchDB
>          Issue Type: Bug
>          Components: Database Core
>            Reporter: Robert Newson
>         Attachments: chunked.erl
>
>
> I noticed that mochiweb always closes the connection when doing a multipart/related PUT
(to insert the JSON document and accompanying attachments in one call). Ultimately it's because
we call recv(0) and not recv_body, thus consuming more data than we actually process. Mochiweb
notices that there is unread data on the socket and closes the connection.
> This impacts replication with attachments, as I believe they go through this code path
(and, thus, are forever reconnecting).
> The code below demonstrates a fix for this issue but isn't good enough for trunk. Adam
provided the important process dictionary fix.
> ---
>  src/couchdb/couch_doc.erl      |    1 +
>  src/couchdb/couch_httpd_db.erl |   13 +++++++++----
>  2 files changed, 10 insertions(+), 4 deletions(-)
> diff --git a/src/couchdb/couch_doc.erl b/src/couchdb/couch_doc.erl
> index 5009f8f..f8c874b 100644
> --- a/src/couchdb/couch_doc.erl
> +++ b/src/couchdb/couch_doc.erl
> @@ -455,6 +455,7 @@ doc_from_multi_part_stream(ContentType, DataFun) ->
>      Parser ! {get_doc_bytes, self()},
>      receive 
>      {doc_bytes, DocBytes} ->
> +        erlang:put(mochiweb_request_recv, true),
>          Doc = from_json_obj(?JSON_DECODE(DocBytes)),
>          % go through the attachments looking for 'follows' in the data,
>          % replace with function that reads the data from MIME stream.
> diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
> index b0fbe8d..eff7d67 100644
> --- a/src/couchdb/couch_httpd_db.erl
> +++ b/src/couchdb/couch_httpd_db.erl
> @@ -651,12 +651,13 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) ->
>      } = parse_doc_query(Req),
>      couch_doc:validate_docid(DocId),
>      
> +    Len = couch_httpd:header_value(Req,"Content-Length"),
>      Loc = absolute_uri(Req, "/" ++ ?b2l(Db#db.name) ++ "/" ++ ?b2l(DocId)),
>      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),
> +                fun() -> receive_request_data(Req, Len) end),
>          Doc = couch_doc_from_req(Req, DocId, Doc0),
>          update_doc(Req, Db, DocId, Doc, RespHeaders, UpdateType);
>      _Else ->
> @@ -775,9 +776,13 @@ send_docs_multipart(Req, Results, Options) ->
>      couch_httpd:send_chunk(Resp, <<"--">>),
>      couch_httpd:last_chunk(Resp).
>  
> -receive_request_data(Req) ->
> -    {couch_httpd:recv(Req, 0), fun() -> receive_request_data(Req) end}.
> -    
> +receive_request_data(Req, undefined) ->
> +    receive_request_data(Req, 0);
> +receive_request_data(Req, Len) when is_list(Len)->
> +    Remaining = list_to_integer(Len),
> +    Bin = couch_httpd:recv(Req, Remaining),
> +    {Bin, fun() -> receive_request_data(Req, Remaining - iolist_size(Bin)) end}.
> +
>  update_doc_result_to_json({{Id, Rev}, Error}) ->
>          {_Code, Err, Msg} = couch_httpd:error_info(Error),
>          {[{id, Id}, {rev, couch_doc:rev_to_str(Rev)},
> -- 
> 1.7.2.2
> Umbra

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


Mime
View raw message