Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Compute and expose document conflict count in db_info api

BugzID:937
  • Loading branch information...
commit fa45cbbe12e97464deccd791fde106aff6ebcdc9 1 parent d3b0016
Bob Dionne authored
View
23 apps/couch/src/couch_db.erl
@@ -256,8 +256,12 @@ get_last_purged(#db{fd=Fd, header=#db_header{purged_docs=PurgedPointer}}) ->
couch_file:pread_term(Fd, PurgedPointer).
get_doc_count(Db) ->
- {ok, {Count, _, _}} = couch_btree:full_reduce(Db#db.id_tree),
- {ok, Count}.
+ case couch_btree:full_reduce(Db#db.id_tree) of
+ {ok, {OCount, _, _}} ->
+ {ok, OCount};
+ {ok, {NCount, _, _, _}} ->
+ {ok, NCount}
+ end.
get_db_info(Db) ->
#db{fd=Fd,
@@ -269,11 +273,16 @@ get_db_info(Db) ->
instance_start_time=StartTime,
committed_update_seq=CommittedUpdateSeq} = Db,
{ok, Size} = couch_file:bytes(Fd),
- {ok, {Count, DelCount, DataSize}} = couch_btree:full_reduce(FullDocBtree),
+ {ok, {Count, DelCount, Conflicts, DataSize}} =
+ case couch_btree:full_reduce(FullDocBtree) of
+ {ok, {_,_,_,_}} = New -> New;
+ {ok, {C,De,Da}} -> {ok, {C,De,0,Da}}
+ end,
InfoList = [
{db_name, Name},
{doc_count, Count},
{doc_del_count, DelCount},
+ {conflicts_count, Conflicts},
{update_seq, SeqNum},
{purge_seq, couch_db:get_purge_seq(Db)},
{compact_running, Compactor/=nil},
@@ -986,9 +995,11 @@ enum_docs_since_reduce_to_count(Reds) ->
fun couch_db_updater:btree_by_seq_reduce/2, Reds).
enum_docs_reduce_to_count(Reds) ->
- {Count, _, _} = couch_btree:final_reduce(
- fun couch_db_updater:btree_by_id_reduce/2, Reds),
- Count.
+ case couch_btree:final_reduce(
+ fun couch_db_updater:btree_by_id_reduce/2, Reds) of
+ {C1, _, _} -> C1;
+ {C2, _, _, _} -> C2
+ end.
changes_since(Db, StartSeq, Fun, Acc) ->
changes_since(Db, StartSeq, Fun, [], Acc).
View
40 apps/couch/src/couch_db_updater.erl
@@ -362,23 +362,37 @@ btree_by_id_join(Id, {HighSeq, Deleted, Size, DiskTree}) ->
btree_by_id_reduce(reduce, FullDocInfos) ->
lists:foldl(
- fun(#full_doc_info{deleted = false, data_size=Size},
- {NotDeleted, Deleted, DocSize}) ->
- {NotDeleted + 1, Deleted, DocSize + Size};
- (#full_doc_info{deleted = true, data_size=Size},
- {NotDeleted, Deleted, DocSize}) ->
- {NotDeleted, Deleted + 1, DocSize + Size}
+ fun(#full_doc_info{deleted = false, rev_tree = Tree, data_size=Size},
+ {NotDeleted, Deleted, Conflicts, DocSize}) ->
+ {NotDeleted + 1, Deleted,
+ Conflicts + case has_conflicts(Tree) of
+ true -> 1;
+ false -> 0
+ end,
+ DocSize + Size};
+ (#full_doc_info{deleted = true, rev_tree = Tree, data_size=Size},
+ {NotDeleted, Deleted, Conflicts, DocSize}) ->
+ {NotDeleted, Deleted + 1,
+ Conflicts + case has_conflicts(Tree) of
+ true -> 1;
+ false -> 0
+ end,
+ DocSize + Size}
end,
- {0, 0, 0}, FullDocInfos);
+ {0, 0, 0, 0}, FullDocInfos);
-btree_by_id_reduce(rereduce, Reductions) ->
+btree_by_id_reduce(rereduce, [FirstRed | RestReds]) ->
lists:foldl(
fun({NotDeleted, Deleted}, {AccNotDeleted, AccDeleted, AccDocSizes}) ->
- {AccNotDeleted + NotDeleted, AccDeleted + Deleted, AccDocSizes};
- ({NotDeleted, Deleted, DocSizes}, {AccNotDeleted, AccDeleted, AccDocSizes}) ->
- {AccNotDeleted + NotDeleted, AccDeleted + Deleted, DocSizes + AccDocSizes}
+ {AccNotDeleted + NotDeleted, AccDeleted + Deleted, 0, AccDocSizes};
+ ({NotDeleted, Deleted, DocSizes}, {AccNotDeleted, AccDeleted, AccConflicts, AccDocSizes}) ->
+ {AccNotDeleted + NotDeleted, AccDeleted + Deleted, AccConflicts, DocSizes + AccDocSizes};
+ ({NotDeleted, Deleted, Conflicts, DocSizes},
+ {AccNotDeleted, AccDeleted, AccConflicts, AccDocSizes}) ->
+ {AccNotDeleted + NotDeleted, AccDeleted + Deleted,
+ Conflicts + AccConflicts, DocSizes + AccDocSizes}
end,
- {0, 0, 0}, Reductions).
+ FirstRed, RestReds).
btree_by_seq_reduce(reduce, DocInfos) ->
% count the number of documents
@@ -458,6 +472,8 @@ init_db(DbName, Filepath, Fd, Header0) ->
close_db(#db{fd_monitor = Ref}) ->
erlang:demonitor(Ref).
+has_conflicts(RevTree) ->
+ couch_key_tree:has_conflicts(RevTree).
refresh_validate_doc_funs(Db) ->
{ok, DesignDocs} = couch_db:get_design_docs(Db),
View
45 apps/couch/src/couch_key_tree.erl
@@ -50,7 +50,7 @@
-export([merge/3, find_missing/2, get_key_leafs/2,
get_full_key_paths/2, get/2, compute_data_size/1]).
-export([map/2, get_all_leafs/1, count_leafs/1, remove_leafs/2,
- get_all_leafs_full/1,stem/2,map_leafs/2, fold/3]).
+ has_conflicts/1, get_all_leafs_full/1,stem/2,map_leafs/2, fold/3]).
-include("couch_db.hrl").
@@ -325,6 +325,49 @@ count_leafs_simple([{_Key, _Value, []} | RestTree]) ->
count_leafs_simple([{_Key, _Value, SubTree} | RestTree]) ->
count_leafs_simple(SubTree) + count_leafs_simple(RestTree).
+%% @doc check a revision tree for conflicts. By definition a tree has
+%% conflicts if there is more than one leaf that is not deleted
+has_conflicts([]) ->
+ false;
+has_conflicts(BranchList) ->
+ count_non_deleted(BranchList,0) > 1.
+
+count_non_deleted([],N) ->
+ N;
+count_non_deleted([{_Pos, Tree} | RestTree], N) ->
+ % once there is more than one return
+ case N > 1 of
+ true -> N;
+ false ->
+ NextN = count_non_deleted_leaves([Tree],N),
+ count_non_deleted(RestTree, NextN)
+ end.
+
+count_non_deleted_leaves([],N) ->
+ N;
+count_non_deleted_leaves([{_Key, Value, []} | RestTree],N) ->
+ NextN = case check_deleted(Value) of false -> N + 1; true -> N end,
+ case NextN > 1 of
+ true -> NextN;
+ false ->
+ count_non_deleted_leaves(RestTree, NextN)
+ end;
+count_non_deleted_leaves([{_Key, _Value, SubTree} | RestTree],N) ->
+ NextN = count_non_deleted_leaves(SubTree,N),
+ case NextN > 1 of
+ true ->
+ NextN;
+ false ->
+ count_non_deleted_leaves(RestTree, NextN)
+ end.
+
+check_deleted({true,_,_}) ->
+ true;
+check_deleted(#doc{deleted=true}) ->
+ true;
+check_deleted(_) ->
+ false.
+
compute_data_size(Tree) ->
{TotBodySizes,TotAttSizes} =
tree_fold(fun({_Pos, _Key, _Value},branch,Acc) ->
View
6 apps/couch/src/couch_view.erl
@@ -118,8 +118,10 @@ list_index_files(Db) ->
get_row_count(#view{btree=Bt}) ->
- {ok, {Count, _, _}} = couch_btree:full_reduce(Bt),
- {ok, Count}.
+ case couch_btree:full_reduce(Bt) of
+ {ok, {NC, _, _, _}} -> NC;
+ {ok, {OC, _, _}} -> OC
+ end.
get_temp_reduce_view(Db, Language, DesignOptions, MapSrc, RedSrc) ->
{ok, #group{views=[View]}=Group} =
View
8 apps/couch/src/couch_view_group.erl
@@ -530,8 +530,12 @@ get_group_info(State) ->
compute_data_size(ViewList) ->
lists:foldl(fun(#view{btree=Btree}, Acc) ->
- {ok, {_, _, Size}} = couch_btree:full_reduce(Btree),
- Size + Acc
+ case couch_btree:full_reduce(Btree) of
+ {ok, {_, _, _, NSize}} ->
+ NSize + Acc;
+ {ok, {_, _, OSize}} ->
+ OSize + Acc
+ end
end, 0, ViewList).
Please sign in to comment.
Something went wrong with that request. Please try again.