diff options
author | Damien F. Katz <damien@apache.org> | 2009-01-15 23:12:56 +0000 |
---|---|---|
committer | Damien F. Katz <damien@apache.org> | 2009-01-15 23:12:56 +0000 |
commit | 1c13d302c9bfa4e6532fab6fd9c210acd64b962f (patch) | |
tree | 1682cbb16823542101fd0d36184e3a863677223b /src | |
parent | 369dfbc2babdc2db0e5a07736b763bc06c5b9914 (diff) |
Support for streaming attachment writes.
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@734849 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r-- | src/couchdb/couch_db.erl | 21 | ||||
-rw-r--r-- | src/couchdb/couch_httpd.erl | 5 | ||||
-rw-r--r-- | src/couchdb/couch_httpd_db.erl | 10 |
3 files changed, 30 insertions, 6 deletions
diff --git a/src/couchdb/couch_db.erl b/src/couchdb/couch_db.erl index 3011d744..b3102044 100644 --- a/src/couchdb/couch_db.erl +++ b/src/couchdb/couch_db.erl @@ -400,7 +400,9 @@ doc_flush_binaries(Doc, Fd) -> % written to a different file SizeAcc + Len; {_Key, {_Type, Bin}} when is_binary(Bin) -> - SizeAcc + size(Bin) + SizeAcc + size(Bin); + {_Key, {_Type, {Fun, Len}}} when is_function(Fun) -> + SizeAcc + Len end end, 0, Bins), @@ -433,7 +435,11 @@ doc_flush_binaries(Doc, Fd) -> {Fd, NewStreamPointer, Len}; Bin when is_binary(Bin) -> {ok, StreamPointer} = couch_stream:write(OutputStream, Bin), - {Fd, StreamPointer, size(Bin)} + {Fd, StreamPointer, size(Bin)}; + {Fun, Len} when is_function(Fun) -> + {ok, StreamPointer} = + write_streamed_attachment(OutputStream, Fun, Len, nil), + {Fd, StreamPointer, Len} end, {Key, {Type, NewBinValue}} end, Bins), @@ -441,6 +447,17 @@ doc_flush_binaries(Doc, Fd) -> {ok, _FinalPos} = couch_stream:close(OutputStream), Doc#doc{attachments = NewBins}. + +write_streamed_attachment(_Stream, _F, 0, SpAcc) -> + {ok, SpAcc}; +write_streamed_attachment(Stream, F, LenLeft, nil) -> + Bin = F(), + {ok, StreamPointer} = couch_stream:write(Stream, Bin), + write_streamed_attachment(Stream, F, LenLeft - size(Bin), StreamPointer); +write_streamed_attachment(Stream, F, LenLeft, SpAcc) -> + Bin = F(), + {ok, _} = couch_stream:write(Stream, Bin), + write_streamed_attachment(Stream, F, LenLeft - size(Bin), SpAcc). enum_docs_since_reduce_to_count(Reds) -> couch_btree:final_reduce( diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index 38c34e17..93062d69 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -16,7 +16,7 @@ -export([start_link/0, stop/0, handle_request/3]). -export([header_value/2,header_value/3,qs_value/2,qs_value/3,qs/1,path/1]). --export([verify_is_server_admin/1,unquote/1]). +-export([verify_is_server_admin/1,unquote/1,recv/2]). -export([parse_form/1,json_body/1,body/1,doc_etag/1]). -export([primary_header_value/2,partition/1,serve_file/3]). -export([start_chunked_response/3,send_chunk/2]). @@ -244,6 +244,9 @@ unquote(UrlEncodedString) -> parse_form(#httpd{mochi_req=MochiReq}) -> mochiweb_multipart:parse_form(MochiReq). +recv(#httpd{mochi_req=MochiReq}, Len) -> + MochiReq:recv(Len). + body(#httpd{mochi_req=MochiReq}) -> MochiReq:recv_body(?MAX_DOC_SIZE). diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index 44b6265c..cdebb1e3 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -255,7 +255,7 @@ db_req(#httpd{path_parts=[_,<<"_admins">>]}=Req, _Db) -> % Special case to enable using an unencoded slash in the URL of design docs, % as slashes in document IDs must otherwise be URL encoded. -db_req(#httpd{method='GET',mochi_req=MochiReq, path_parts=[DbName,<<"_design/",Name/binary>>|Rest]}=Req, Db) -> +db_req(#httpd{method='GET',mochi_req=MochiReq, path_parts=[DbName,<<"_design/",_/binary>>|_]}=Req, _Db) -> PathFront = "/" ++ binary_to_list(DbName) ++ "/_design", {ok, [PathFront|PathTail]} = regexp:split(MochiReq:get(raw_path),"%2F"), RedirectTo = PathFront ++ "/" ++ mochiweb_util:join(PathTail, "%2F"), @@ -279,7 +279,6 @@ all_docs_view(Req, Db, Keys) -> start_key = StartKey, start_docid = StartDocId, end_key = EndKey, - end_docid = EndDocId, limit = Limit, skip = SkipCount, direction = Dir @@ -590,7 +589,12 @@ db_attachment_req(#httpd{method=Method}=Req, Db, DocId, FileNameParts) _ -> [{FileName, { list_to_binary(couch_httpd:header_value(Req,"Content-Type")), - couch_httpd:body(Req) + case couch_httpd:header_value(Req,"Content-Length") of + undefined -> + throw({bad_request, "Attachment uploads must be fixed length"}); + Length -> + {fun() -> couch_httpd:recv(Req, 0) end, list_to_integer(Length)} + end }}] end, |