summaryrefslogtreecommitdiff
path: root/src/fabric_info.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/fabric_info.erl')
-rw-r--r--src/fabric_info.erl104
1 files changed, 97 insertions, 7 deletions
diff --git a/src/fabric_info.erl b/src/fabric_info.erl
index 95408b6f..51529da3 100644
--- a/src/fabric_info.erl
+++ b/src/fabric_info.erl
@@ -1,23 +1,113 @@
-module(fabric_info).
--export([all_databases/1]).
+-export([all_databases/1, get_db_info/2]).
-include("../../couch/src/couch_db.hrl").
+-include("../../dynomite/include/membership.hrl").
%% @doc gets all databases in the cluster.
-spec all_databases(binary() | []) -> [binary()].
all_databases([]) ->
- Dbs = ets:foldl(fun({DbName, _}, Acc0) ->
- [DbName | Acc0]
- end, [], dbs_cache),
+ Dbs = ets:foldl(fun(#part{dbname=DbName}, AccIn) ->
+ new_acc(DbName, AccIn)
+ end, [], partitions),
{ok, Dbs};
all_databases(Customer) ->
?debugFmt("~nCustomer: ~p~n", [Customer]),
- Dbs = ets:foldl(fun({DbName, _}, Acc0) ->
+ Dbs = ets:foldl(fun(#part{dbname=DbName}, AccIn) ->
DbNameStr = ?b2l(DbName),
case string:str(DbNameStr, Customer) of
- 1 -> [DbNameStr | Acc0];
- _ -> Acc0
+ 1 ->
+ new_acc(DbNameStr, AccIn);
+ _ -> AccIn
end
end, [], dbs_cache),
{ok, Dbs}.
+
+%% @doc get database information tuple
+get_db_info(DbName, _Customer) ->
+ Parts = partitions:all_parts(DbName),
+ RefPartMap = send_info_calls(DbName, Parts),
+ {ok, Results} = fabric_rpc:receive_loop(RefPartMap, 5000, fun info_loop/3),
+ InfoList = Results,
+ % process_infos(ShardInfos, [{db_name, Name}]);
+ {ok, InfoList}.
+
+%% =====================
+%% internal
+%% =====================
+
+new_acc(DbName, Acc) ->
+ case lists:member(DbName, Acc) of
+ true -> Acc;
+ _ ->[DbName | Acc]
+ end.
+
+send_info_calls(DbName, Parts) ->
+ lists:map(fun(#part{node=Node, b=Beg} = Part) ->
+ ShardName = showroom_utils:shard_name(Beg, DbName),
+ Ref = rexi:cast(Node, {rexi_rpc, get_db_info, ShardName}),
+ {Ref, Part}
+ end, Parts).
+
+%% @doc create_db receive loop
+%% Acc is either an accumulation of responses, or if we've received all
+%% responses, it's {ok, Responses}
+-spec info_loop([ref_part_map()], tref(), beg_acc()) ->
+ beg_acc() | {ok, beg_acc()}.
+info_loop(_,_,{ok, Acc}) -> {ok, Acc};
+info_loop(RefPartMap, TimeoutRef, AccIn) ->
+ receive
+ {Ref, {ok, Info}} when is_reference(Ref) ->
+ AccOut = check_all_parts(Ref, RefPartMap, AccIn, ok),
+ info_loop(RefPartMap, TimeoutRef, AccOut);
+ {Ref, Reply} when is_reference(Ref) ->
+ AccOut = check_all_parts(Ref, RefPartMap, AccIn, Reply),
+ info_loop(RefPartMap, TimeoutRef, AccOut);
+ {timeout, TimeoutRef} ->
+ {error, timeout}
+ end.
+
+
+cloudant_db_name(Customer, FullName) ->
+ case Customer of
+ "" ->
+ FullName;
+ Name ->
+ re:replace(FullName, [Name,"/"], "", [{return, binary}])
+ end.
+
+%% Loop through Tasks on the flattened Infos and get the aggregated result
+process_infos(Infos, Initial) ->
+ Tasks = [
+ {doc_count, fun sum/2, 0},
+ {doc_del_count, fun sum/2, 0},
+ {update_seq, fun max/2, 1},
+ {purge_seq, fun sum/2, 0},
+ {compact_running, fun bool/2, 0},
+ {disk_size, fun sum/2, 0},
+ {instance_start_time, fun(_, _) -> <<"0">> end, 0},
+ {disk_format_version, fun max/2, 0}],
+
+ Infos1 = lists:flatten(Infos),
+
+ Result = lists:map(fun({Type, Fun, Default}) ->
+ {Type, process_info(Type, Fun, Default, Infos1)}
+ end, Tasks),
+ lists:flatten([Initial, Result]).
+
+ process_info(Type, Fun, Default, List) ->
+ lists:foldl(fun(V, AccIn) -> Fun(V, AccIn) end, Default,
+ couch_util:get_all_values(Type, List)).
+
+sum(New, Existing) ->
+ New + Existing.
+
+bool(New, Existing) ->
+ New andalso Existing.
+
+max(New, Existing) ->
+ case New > Existing of
+ true -> New;
+ false -> Existing
+ end.