summaryrefslogtreecommitdiff
path: root/src/couchdb/couch_httpd_db.erl
diff options
context:
space:
mode:
authorJohn Christopher Anderson <jchris@apache.org>2009-02-15 20:36:53 +0000
committerJohn Christopher Anderson <jchris@apache.org>2009-02-15 20:36:53 +0000
commit146bc594aef47b675670e7a7fd7f89b7c6a10843 (patch)
tree4f1ea083353560951b640f8c1ceaaf728e2def65 /src/couchdb/couch_httpd_db.erl
parentc91f851dc421466402721eb7baa644860f874ce1 (diff)
View etags are now provided. See note in the source about how they could be more efficient. Changes arity on make_view_fold_fun etc. Closes COUCHDB-4
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@744747 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/couchdb/couch_httpd_db.erl')
-rw-r--r--src/couchdb/couch_httpd_db.erl218
1 files changed, 112 insertions, 106 deletions
diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl
index 89f8ce04..95c96349 100644
--- a/src/couchdb/couch_httpd_db.erl
+++ b/src/couchdb/couch_httpd_db.erl
@@ -191,46 +191,48 @@ db_req(#httpd{method='GET',path_parts=[_,<<"_all_docs_by_seq">>]}=Req, Db) ->
} = QueryArgs = couch_httpd_view:parse_view_query(Req),
{ok, Info} = couch_db:get_db_info(Db),
- TotalRowCount = proplists:get_value(doc_count, Info),
-
- FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, Db,
- TotalRowCount, #view_fold_helper_funs{
- reduce_count = fun couch_db:enum_docs_since_reduce_to_count/1
- }),
- StartKey2 = case StartKey of
- nil -> 0;
- <<>> -> 100000000000;
- {} -> 100000000000;
- StartKey when is_integer(StartKey) -> StartKey
- end,
- {ok, FoldResult} = couch_db:enum_docs_since(Db, StartKey2, Dir,
- fun(DocInfo, Offset, Acc) ->
- #doc_info{
- id=Id,
- rev=Rev,
- update_seq=UpdateSeq,
- deleted=Deleted,
- conflict_revs=ConflictRevs,
- deleted_conflict_revs=DelConflictRevs
- } = DocInfo,
- Json = {
- [{<<"rev">>, Rev}] ++
- case ConflictRevs of
- [] -> [];
- _ -> [{<<"conflicts">>, ConflictRevs}]
- end ++
- case DelConflictRevs of
- [] -> [];
- _ -> [{<<"deleted_conflicts">>, DelConflictRevs}]
- end ++
- case Deleted of
- true -> [{<<"deleted">>, true}];
- false -> []
- end
- },
- FoldlFun({{UpdateSeq, Id}, Json}, Offset, Acc)
- end, {Limit, SkipCount, undefined, []}),
- couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult});
+ CurrentEtag = couch_httpd:make_etag(proplists:get_value(update_seq, Info)),
+ couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
+ TotalRowCount = proplists:get_value(doc_count, Info),
+ FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db,
+ TotalRowCount, #view_fold_helper_funs{
+ reduce_count = fun couch_db:enum_docs_since_reduce_to_count/1
+ }),
+ StartKey2 = case StartKey of
+ nil -> 0;
+ <<>> -> 100000000000;
+ {} -> 100000000000;
+ StartKey when is_integer(StartKey) -> StartKey
+ end,
+ {ok, FoldResult} = couch_db:enum_docs_since(Db, StartKey2, Dir,
+ fun(DocInfo, Offset, Acc) ->
+ #doc_info{
+ id=Id,
+ rev=Rev,
+ update_seq=UpdateSeq,
+ deleted=Deleted,
+ conflict_revs=ConflictRevs,
+ deleted_conflict_revs=DelConflictRevs
+ } = DocInfo,
+ Json = {
+ [{<<"rev">>, Rev}] ++
+ case ConflictRevs of
+ [] -> [];
+ _ -> [{<<"conflicts">>, ConflictRevs}]
+ end ++
+ case DelConflictRevs of
+ [] -> [];
+ _ -> [{<<"deleted_conflicts">>, DelConflictRevs}]
+ end ++
+ case Deleted of
+ true -> [{<<"deleted">>, true}];
+ false -> []
+ end
+ },
+ FoldlFun({{UpdateSeq, Id}, Json}, Offset, Acc)
+ end, {Limit, SkipCount, undefined, []}),
+ couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult})
+ end);
db_req(#httpd{path_parts=[_,<<"_all_docs_by_seq">>]}=Req, _Db) ->
send_method_not_allowed(Req, "GET,HEAD");
@@ -289,77 +291,81 @@ all_docs_view(Req, Db, Keys) ->
direction = Dir
} = QueryArgs = couch_httpd_view:parse_view_query(Req, Keys),
{ok, Info} = couch_db:get_db_info(Db),
- TotalRowCount = proplists:get_value(doc_count, Info),
- StartId = if is_binary(StartKey) -> StartKey;
- true -> StartDocId
- end,
- FoldAccInit = {Limit, SkipCount, undefined, []},
+ CurrentEtag = couch_httpd:make_etag(proplists:get_value(update_seq, Info)),
+ couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
- PassedEndFun =
- case Dir of
- fwd ->
- fun(ViewKey, _ViewId) ->
- couch_db_updater:less_docid(EndKey, ViewKey)
- end;
- rev->
- fun(ViewKey, _ViewId) ->
- couch_db_updater:less_docid(ViewKey, EndKey)
- end
- end,
-
- case Keys of
- nil ->
- FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, Db,
- TotalRowCount, #view_fold_helper_funs{
- reduce_count = fun couch_db:enum_docs_reduce_to_count/1,
- passed_end = PassedEndFun
- }),
- AdapterFun = fun(#full_doc_info{id=Id}=FullDocInfo, Offset, Acc) ->
- case couch_doc:to_doc_info(FullDocInfo) of
- #doc_info{deleted=false, rev=Rev} ->
- FoldlFun({{Id, Id}, {[{rev, Rev}]}}, Offset, Acc);
- #doc_info{deleted=true} ->
- {ok, Acc}
- end
+ TotalRowCount = proplists:get_value(doc_count, Info),
+ StartId = if is_binary(StartKey) -> StartKey;
+ true -> StartDocId
end,
- {ok, FoldResult} = couch_db:enum_docs(Db, StartId, Dir,
- AdapterFun, FoldAccInit),
- couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult});
- _ ->
- FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, Db,
- TotalRowCount, #view_fold_helper_funs{
- reduce_count = fun(Offset) -> Offset end
- }),
- KeyFoldFun = case Dir of
+ FoldAccInit = {Limit, SkipCount, undefined, []},
+
+ PassedEndFun =
+ case Dir of
fwd ->
- fun lists:foldl/3;
- rev ->
- fun lists:foldr/3
+ fun(ViewKey, _ViewId) ->
+ couch_db_updater:less_docid(EndKey, ViewKey)
+ end;
+ rev->
+ fun(ViewKey, _ViewId) ->
+ couch_db_updater:less_docid(ViewKey, EndKey)
+ end
end,
- {ok, FoldResult} = KeyFoldFun(
- fun(Key, {ok, FoldAcc}) ->
- DocInfo = (catch couch_db:get_doc_info(Db, Key)),
- Doc = case DocInfo of
- {ok, #doc_info{id=Id, rev=Rev, deleted=false}} = DocInfo ->
- {{Id, Id}, {[{rev, Rev}]}};
- {ok, #doc_info{id=Id, rev=Rev, deleted=true}} = DocInfo ->
- {{Id, Id}, {[{rev, Rev}, {deleted, true}]}};
- not_found ->
- {{Key, error}, not_found};
- _ ->
- ?LOG_ERROR("Invalid DocInfo: ~p", [DocInfo]),
- throw({error, invalid_doc_info})
- end,
- Acc = (catch FoldlFun(Doc, 0, FoldAcc)),
- case Acc of
- {stop, Acc2} ->
- {ok, Acc2};
- _ ->
- Acc
+
+ case Keys of
+ nil ->
+ FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db,
+ TotalRowCount, #view_fold_helper_funs{
+ reduce_count = fun couch_db:enum_docs_reduce_to_count/1,
+ passed_end = PassedEndFun
+ }),
+ AdapterFun = fun(#full_doc_info{id=Id}=FullDocInfo, Offset, Acc) ->
+ case couch_doc:to_doc_info(FullDocInfo) of
+ #doc_info{deleted=false, rev=Rev} ->
+ FoldlFun({{Id, Id}, {[{rev, Rev}]}}, Offset, Acc);
+ #doc_info{deleted=true} ->
+ {ok, Acc}
end
- end, {ok, FoldAccInit}, Keys),
- couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult})
- end.
+ end,
+ {ok, FoldResult} = couch_db:enum_docs(Db, StartId, Dir,
+ AdapterFun, FoldAccInit),
+ couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult});
+ _ ->
+ FoldlFun = couch_httpd_view:make_view_fold_fun(Req, QueryArgs, CurrentEtag, Db,
+ TotalRowCount, #view_fold_helper_funs{
+ reduce_count = fun(Offset) -> Offset end
+ }),
+ KeyFoldFun = case Dir of
+ fwd ->
+ fun lists:foldl/3;
+ rev ->
+ fun lists:foldr/3
+ end,
+ {ok, FoldResult} = KeyFoldFun(
+ fun(Key, {ok, FoldAcc}) ->
+ DocInfo = (catch couch_db:get_doc_info(Db, Key)),
+ Doc = case DocInfo of
+ {ok, #doc_info{id=Id, rev=Rev, deleted=false}} = DocInfo ->
+ {{Id, Id}, {[{rev, Rev}]}};
+ {ok, #doc_info{id=Id, rev=Rev, deleted=true}} = DocInfo ->
+ {{Id, Id}, {[{rev, Rev}, {deleted, true}]}};
+ not_found ->
+ {{Key, error}, not_found};
+ _ ->
+ ?LOG_ERROR("Invalid DocInfo: ~p", [DocInfo]),
+ throw({error, invalid_doc_info})
+ end,
+ Acc = (catch FoldlFun(Doc, 0, FoldAcc)),
+ case Acc of
+ {stop, Acc2} ->
+ {ok, Acc2};
+ _ ->
+ Acc
+ end
+ end, {ok, FoldAccInit}, Keys),
+ couch_httpd_view:finish_view_fold(Req, TotalRowCount, {ok, FoldResult})
+ end
+ end).