diff options
author | Adam Kocoloski <adam@cloudant.com> | 2010-06-01 10:39:47 -0400 |
---|---|---|
committer | Adam Kocoloski <adam@cloudant.com> | 2010-06-01 10:39:47 -0400 |
commit | 9b7831dbbddc97b4134be2fa3b3ec2d2ebc9462b (patch) | |
tree | a675e52af675e626903a5a7c288d4e2cc4e24cac | |
parent | dc28af5e331e13283ec3915e60fa0431673d1845 (diff) |
RPC endpoint for all_docs w/o keylist, BugzID 10218
-rw-r--r-- | src/fabric_rpc.erl | 98 |
1 files changed, 93 insertions, 5 deletions
diff --git a/src/fabric_rpc.erl b/src/fabric_rpc.erl index 2d1f6572..a8e4585b 100644 --- a/src/fabric_rpc.erl +++ b/src/fabric_rpc.erl @@ -2,17 +2,52 @@ -export([get_db_info/1, get_doc_count/1, get_update_seq/1]). -export([open_doc/3, open_revs/4, get_missing_revs/2, update_docs/3]). +-export([all_docs/2]). -include("fabric.hrl"). +-record (view_acc, { + db, + limit, + include_docs, + offset = nil, + reduce_fun = fun couch_db:enum_docs_reduce_to_count/1, + stop_fun, + group_level = 0 +}). + %% rpc endpoints %% call to with_db will supply your M:F with a #db{} and then remaining args +all_docs(DbName, #view_query_args{keys=nil} = QueryArgs) -> + {ok, Db} = couch_db:open(DbName, []), + #view_query_args{ + start_key = StartKey, + start_docid = StartDocId, + limit = Limit, + skip = Skip, + include_docs = IncludeDocs, + direction = Dir + } = QueryArgs, + StartId = if is_binary(StartKey) -> StartKey; true -> StartDocId end, + Acc0 = #view_acc{ + db = Db, + include_docs = IncludeDocs, + limit = Limit+Skip, + stop_fun = all_docs_stop_fun(QueryArgs) + }, + {ok, Acc} = couch_db:enum_docs(Db, StartId, Dir, fun view_fold/3, Acc0), + if Acc#view_acc.offset == nil -> + Total = couch_db:get_doc_count(Db), + rexi:sync_reply({total_and_offset, Total, Total}); + true -> ok end, + rexi:reply(complete). + get_db_info(DbName) -> with_db(DbName, {couch_db, get_db_info, []}). get_doc_count(DbName) -> - rexi:reply(case couch_db:open(DbName) of + rexi:reply(case couch_db:open(DbName, []) of {ok, Db} -> {ok, {Count, _DelCount}} = couch_btree:full_reduce(Db#db.id_tree), {ok, Count}; @@ -21,7 +56,7 @@ get_doc_count(DbName) -> end). get_update_seq(DbName) -> - rexi:reply(case couch_db:open(DbName) of + rexi:reply(case couch_db:open(DbName, []) of {ok, #db{update_seq = Seq}} -> {ok, Seq}; Error -> @@ -66,7 +101,60 @@ with_db(DbName, {M,F,A}) -> rexi:reply(Error) end. +view_fold(#full_doc_info{} = FullDocInfo, OffsetReds, Acc) -> + % matches for _all_docs and translates #full_doc_info{} -> KV pair + case couch_doc:to_doc_info(FullDocInfo) of + #doc_info{revs=[#rev_info{deleted=false, rev=Rev}|_]} -> + Id = FullDocInfo#full_doc_info.id, + Value = {[{rev,couch_doc:rev_to_str(Rev)}]}, + view_fold({{Id,Id}, Value}, OffsetReds, Acc); + #doc_info{revs=[#rev_info{deleted=true}|_]} -> + {ok, Acc} + end; +view_fold(KV, OffsetReds, #view_acc{offset=nil} = Acc) -> + % calculates the offset for this shard + #view_acc{db=Db, reduce_fun=Reduce} = Acc, + Offset = Reduce(OffsetReds), + rexi:sync_reply({total_and_offset, couch_db:get_doc_count(Db), Offset}), + view_fold(KV, OffsetReds, Acc#view_acc{offset=Offset}); +view_fold(_KV, _Offset, #view_acc{limit=0} = Acc) -> + % we scanned through limit+skip local rows + {stop, Acc}; +view_fold({{Key,Id}, Value}, _Offset, Acc) -> + % the normal case + #view_acc{ + db = Db, + limit = Limit, + include_docs = IncludeDocs, + stop_fun = PassedEnd + } = Acc, + case PassedEnd(Key, Id) of + true -> + {stop, Acc}; + false -> + RowProps = case IncludeDocs of + true -> + case couch_db:open_doc(Db, Id, []) of + {not_found, missing} -> + [{id, Id}, {key, Key}, {value, Value}, {error, missing}]; + {not_found, deleted} -> + [{id, Id}, {key, Key}, {value, Value}]; + {ok, Doc} -> + JsonDoc = couch_doc:to_json_obj(Doc, []), + [{id, Id}, {key, Key}, {value, Value}, {doc, JsonDoc}] + end; + false -> + [{id, Id}, {key, Key}, {value, Value}] + end, + rexi:sync_reply({row, RowProps}), + {ok, Acc#view_acc{limit=Limit-1}} + end. -%% -%% helper funs -%% +all_docs_stop_fun(#view_query_args{direction=fwd, end_key=EndKey}) -> + fun(ViewKey, _) -> + couch_db_updater:less_docid(EndKey, ViewKey) + end; +all_docs_stop_fun(#view_query_args{direction=rev, end_key=EndKey}) -> + fun(ViewKey, _) -> + couch_db_updater:less_docid(ViewKey, EndKey) + end. |