You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2014/08/01 11:06:16 UTC

[40/49] chttpd commit: updated refs/heads/windsor-merge to 554ef74

Move attachment code into couch_att

This is an attempt to isolate the attachment record and
some related code. This will allow seamless upgrades
over time.


Project: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/commit/d6161e77
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/tree/d6161e77
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/diff/d6161e77

Branch: refs/heads/windsor-merge
Commit: d6161e778e777c9fe972eb203a614bd473929dee
Parents: 6deefa1
Author: Brian Mitchell <br...@p2p.io>
Authored: Wed Dec 11 23:09:54 2013 -0500
Committer: Robert Newson <rn...@apache.org>
Committed: Thu Jul 31 11:55:10 2014 +0100

----------------------------------------------------------------------
 src/chttpd_db.erl | 103 +++++++++++++++++++++++++++----------------------
 1 file changed, 56 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-chttpd/blob/d6161e77/src/chttpd_db.erl
----------------------------------------------------------------------
diff --git a/src/chttpd_db.erl b/src/chttpd_db.erl
index 8491004..d9d720b 100644
--- a/src/chttpd_db.erl
+++ b/src/chttpd_db.erl
@@ -619,16 +619,19 @@ db_doc_req(#httpd{method='POST', user_ctx=Ctx}=Req, Db, DocId) ->
         {ok, [{ok, Doc}]} = fabric:open_revs(Db, DocId, [Rev], [])
     end,
     UpdatedAtts = [
-        #att{name=validate_attachment_name(Name),
-            type=list_to_binary(ContentType),
-            data=Content} ||
+        couch_att:new([
+            {name, validate_attachment_name(Name)},
+            {type, list_to_binary(ContentType)},
+            {data, Content}
+        ]) ||
         {Name, {ContentType, _}, Content} <-
         proplists:get_all_values("_attachments", Form)
     ],
     #doc{atts=OldAtts} = Doc,
     OldAtts2 = lists:flatmap(
-        fun(#att{name=OldName}=Att) ->
-            case [1 || A <- UpdatedAtts, A#att.name == OldName] of
+        fun(Att) ->
+            OldName = couch_att:fetch(name, Att),
+            case [1 || A <- UpdatedAtts, couch_att:fetch(name, A) == OldName] of
             [] -> [Att]; % the attachment wasn't in the UpdatedAtts, return it
             _ -> [] % the attachment was in the UpdatedAtts, drop it
             end
@@ -951,10 +954,11 @@ db_attachment_req(#httpd{method='GET',mochi_req=MochiReq}=Req, Db, DocId, FileNa
     #doc{
         atts=Atts
     } = Doc = couch_doc_open(Db, DocId, Rev, Options),
-    case [A || A <- Atts, A#att.name == FileName] of
+    case [A || A <- Atts, couch_att:fetch(name, A) == FileName] of
     [] ->
         throw({not_found, "Document is missing attachment"});
-    [#att{type=Type, encoding=Enc, disk_len=DiskLen, att_len=AttLen}=Att] ->
+    [Att] ->
+        [Type, Enc, DiskLen, AttLen] = couch_att:fetch([type, encoding, disk_len, att_len], Att),
         Refs = monitor_attachments(Att),
         try
         Etag = chttpd:doc_etag(Doc),
@@ -1000,9 +1004,9 @@ db_attachment_req(#httpd{method='GET',mochi_req=MochiReq}=Req, Db, DocId, FileNa
         end,
         AttFun = case ReqAcceptsAttEnc of
         false ->
-            fun couch_doc:att_foldl_decode/3;
+            fun couch_att:foldl_decode/3;
         true ->
-            fun couch_doc:att_foldl/3
+            fun couch_att:foldl/3
         end,
         chttpd:etag_respond(
             Req,
@@ -1020,14 +1024,14 @@ db_attachment_req(#httpd{method='GET',mochi_req=MochiReq}=Req, Db, DocId, FileNa
                             Headers1 = [{<<"Content-Range">>, make_content_range(From, To, Len)}]
                                 ++ Headers,
                             {ok, Resp} = start_response_length(Req, 206, Headers1, To - From + 1),
-                            couch_doc:range_att_foldl(Att, From, To + 1,
+                            couch_att:range_foldl(Att, From, To + 1,
                                 fun(Seg, _) -> send(Resp, Seg) end, {ok, Resp});
                         {identity, Ranges} when is_list(Ranges) andalso length(Ranges) < 10 ->
                             send_ranges_multipart(Req, Type, Len, Att, Ranges);
                         _ ->
                             Headers1 = Headers ++
                                 if Enc =:= identity orelse ReqAcceptsAttEnc =:= true ->
-                                    [{"Content-MD5", base64:encode(Att#att.md5)}];
+                                    [{"Content-MD5", base64:encode(couch_att:fetch(md5, Att))}];
                                 true ->
                                     []
                             end,
@@ -1054,38 +1058,39 @@ db_attachment_req(#httpd{method=Method, user_ctx=Ctx}=Req, Db, DocId, FileNamePa
         'DELETE' ->
             [];
         _ ->
-            [#att{
-                name=FileName,
-                type = case couch_httpd:header_value(Req,"Content-Type") of
-                    undefined ->
-                        % We could throw an error here or guess by the FileName.
-                        % Currently, just giving it a default.
-                        <<"application/octet-stream">>;
-                    CType ->
-                        list_to_binary(CType)
-                    end,
-                data = fabric:att_receiver(Req, chttpd:body_length(Req)),
-                att_len = case couch_httpd:header_value(Req,"Content-Length") of
-                    undefined ->
-                        undefined;
-                    Length ->
-                        list_to_integer(Length)
-                    end,
-                md5 = get_md5_header(Req),
-                encoding = case string:to_lower(string:strip(
-                    couch_httpd:header_value(Req,"Content-Encoding","identity")
-                )) of
+            MimeType = case couch_httpd:header_value(Req,"Content-Type") of
+                % We could throw an error here or guess by the FileName.
+                % Currently, just giving it a default.
+                undefined -> <<"application/octet-stream">>;
+                CType -> list_to_binary(CType)
+            end,
+            Data = fabric:att_receiver(Req, chttpd:body_length(Req)),
+            ContentLen = case couch_httpd:header_value(Req,"Content-Length") of
+                undefined -> undefined;
+                Length -> list_to_integer(Length)
+            end,
+            ContentEnc = string:to_lower(string:strip(
+                couch_httpd:header_value(Req, "Content-Encoding", "identity")
+            )),
+            Encoding = case ContentEnc of
                 "identity" ->
-                   identity;
+                    identity;
                 "gzip" ->
-                   gzip;
+                    gzip;
                 _ ->
-                   throw({
-                       bad_ctype,
-                       "Only gzip and identity content-encodings are supported"
-                   })
-                end
-            }]
+                    throw({
+                        bad_ctype,
+                        "Only gzip and identity content-encodings are supported"
+                    })
+            end,
+            [couch_att:new([
+                {name, FileName},
+                {type, MimeType},
+                {data, Data},
+                {att_len, ContentLen},
+                {md5, get_md5_header(Req)},
+                {encoding, Encoding}
+            ])]
     end,
 
     Doc = case extract_header_rev(Req, couch_httpd:qs_value(Req, "rev")) of
@@ -1101,7 +1106,7 @@ db_attachment_req(#httpd{method=Method, user_ctx=Ctx}=Req, Db, DocId, FileNamePa
 
     #doc{atts=Atts} = Doc,
     DocEdited = Doc#doc{
-        atts = NewAtt ++ [A || A <- Atts, A#att.name /= FileName]
+        atts = NewAtt ++ [A || A <- Atts, couch_att:fetch(name, A) /= FileName]
     },
     case fabric:update_doc(Db, DocEdited, [{user_ctx,Ctx}]) of
     {ok, UpdatedRev} ->
@@ -1140,7 +1145,7 @@ send_ranges_multipart(Req, ContentType, Len, Att, Ranges) ->
             <<"\r\nContent-Type: ", ContentType/binary, "\r\n",
             "Content-Range: ", ContentRange/binary, "\r\n",
            "\r\n">>),
-        couch_doc:range_att_foldl(Att, From, To + 1,
+        couch_att:range_foldl(Att, From, To + 1,
             fun(Seg, _) -> send_chunk(Resp, Seg) end, {ok, Resp}),
         couch_httpd:send_chunk(Resp, <<"\r\n--", Boundary/binary>>)
     end, Ranges),
@@ -1327,7 +1332,8 @@ extract_header_rev(Req, ExplicitRev) ->
 
 
 validate_attachment_names(Doc) ->
-    lists:foreach(fun(#att{name=Name}) ->
+    lists:foreach(fun(Att) ->
+        Name = couch_att:fetch(name, Att),
         validate_attachment_name(Name)
     end, Doc#doc.atts).
 
@@ -1342,11 +1348,14 @@ validate_attachment_name(Name) ->
         false -> throw({bad_request, <<"Attachment name is not UTF-8 encoded">>})
     end.
 
--spec monitor_attachments(#att{} | [#att{}]) -> [reference()].
-monitor_attachments(#att{}=Att) ->
-    monitor_attachments([Att]);
+-spec monitor_attachments(couch_att:att() | [couch_att:att()]) -> [reference()].
 monitor_attachments(Atts) when is_list(Atts) ->
-    [monitor(process, Fd) || #att{data={Fd,_}} <- Atts].
+    lists:map(fun(Att) ->
+        {Fd, _} = couch_att:fetch(data, Att),
+        monitor(process, Fd)
+    end, Atts);
+monitor_attachments(Att) ->
+    monitor_attachments([Att]).
 
 demonitor_refs(Refs) when is_list(Refs) ->
     [demonitor(Ref) || Ref <- Refs].