Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Ring visualizer for riak core, based on the one by (Uwe Dauernheim)

  • Loading branch information...
commit 3ee3b74911ebef1d50dfdefcf241ca43fbef949d 1 parent 10b8387
@Vagabond Vagabond authored
View
2  ebin/riak_core.app
@@ -47,8 +47,10 @@
riak_core_vnode_sup,
riak_core_web,
riak_core_wm_urlmap,
+ riak_core_wm_ring_resource,
slide,
spiraltime,
+ riak_core_wm_static_resource,
vclock
]},
{registered, []},
View
7 src/riak_core_web.erl
@@ -98,4 +98,9 @@ spec_name(Scheme, Ip, Port) ->
common_config() ->
[{log_dir, app_helper:get_env(riak_core, http_logdir, "log")},
{backlog, 128},
- {dispatch, [{[], riak_core_wm_urlmap, []}]}].
+ {dispatch, [{[], riak_core_wm_urlmap, []},
+ {["ring"], riak_core_wm_ring_resource, []},
+ {['*'], riak_core_wm_static_resource,
+ [filename:join(code:priv_dir(riak_core), "www")]}
+ %["/home/andrew/riak/deps/riak_core/priv/www"]}
+ ]}].
View
99 src/riak_core_wm_ring_resource.erl
@@ -0,0 +1,99 @@
+%%% @doc Ring visualization resource.
+%%% @author Uwe Dauernheim <uwe@dauernheim.net>
+-module(riak_core_wm_ring_resource).
+
+-author("Uwe Dauernheim <uwe@dauernheim.net>").
+
+-export([ init/1
+ , to_html/2
+ ]).
+
+-include_lib("webmachine/include/webmachine.hrl").
+
+-record(chstate, {
+ nodename, % the Node responsible for this chstate
+ vclock, % for this chstate object, entries are {Node, Ctr}
+ chring, % chash ring of {IndexAsInt, Node} mappings
+ meta % dict of cluster-wide other data (primarily bucket N-value, etc)
+}).
+
+init([]) ->
+ io:format("init~n"),
+ {ok, undefined}.
+
+to_html(ReqData, Context) ->
+ io:format("to html~n"),
+ {_Down, Rings} = get_rings(),
+ Bleh = lists:map(fun({N, R}) ->
+ %{_Pri, Sec, Stopped} = partitions(N, R)
+ {_, Sec, _} = partitions(N, R),
+ {N, Sec}
+ end, Rings),
+ io:format("Bleh ~p~n", [Bleh]),
+ Result = template(get_ring(), get_down(), Bleh),
+ {Result, ReqData, Context}.
+
+get_ring() ->
+ {ok, State} = riak_core_ring_manager:get_my_ring(),
+ {_, Ring} = State#chstate.chring,
+ Ring.
+
+get_down() ->
+ try riak_kv_status:ringready() of
+ {error, {nodes_down, Down}} ->
+ Down;
+ _ -> []
+ catch
+ _:_ ->
+ []
+ end.
+
+template(Ring, Down, Bleh) ->
+ X = json_pp:print(mochijson2:encode({struct, Bleh})),
+ io:format("X ~p~n", [X]),
+ Data = lists:map(fun({ID, Node}) -> {struct, [{id, ID}, {node, Node}]} end, Ring),
+ DownData = {struct, [{down, Down}]},
+ {ok, Bin} = file:read_file("/home/andrew/riak/deps/riak_core/priv/www/ring.html"),
+ io_lib:format(binary_to_list(Bin),
+ [json_pp:print(mochijson2:encode(Data)),
+ json_pp:print(mochijson2:encode(DownData)), X]).
+
+
+%% Retrieve the rings for all other nodes by RPC
+get_rings() ->
+ {RawRings, Down} = riak_core_util:rpc_every_member(
+ riak_core_ring_manager, get_my_ring, [], 30000),
+ Rings = orddict:from_list([{riak_core_ring:owner_node(R), R} || {ok, R} <- RawRings]),
+ {lists:sort(Down), Rings}.
+
+%% Return a list of active primary partitions, active secondary partitions (to be handed off)
+%% and stopped partitions that should be started
+partitions(Node, Ring) ->
+ Owners = riak_core_ring:all_owners(Ring),
+ Owned = ordsets:from_list(owned_partitions(Owners, Node)),
+ Active = ordsets:from_list(active_partitions(Node)),
+ Stopped = ordsets:subtract(Owned, Active),
+ Secondary = ordsets:subtract(Active, Owned),
+ Primary = ordsets:subtract(Active, Secondary),
+ {Primary, Secondary, Stopped}.
+
+%% Return the list of partitions owned by a node
+owned_partitions(Owners, Node) ->
+ [P || {P, Owner} <- Owners, Owner =:= Node].
+
+%% Get a list of active partition numbers - regardless of vnode type
+active_partitions(Node) ->
+ lists:foldl(fun({_,P}, Ps) ->
+ ordsets:add_element(P, Ps)
+ end, [], running_vnodes(Node)).
+
+%% Get a list of running vnodes for a node
+running_vnodes(Node) ->
+ Pids = vnode_pids(Node),
+ [rpc:call(Node, riak_core_vnode, get_mod_index, [Pid], 30000) || Pid <- Pids].
+
+%% Get a list of vnode pids for a node
+vnode_pids(Node) ->
+ [Pid || {_,Pid,_,_} <- supervisor:which_children({riak_core_vnode_sup, Node})].
+
+
View
60 src/riak_core_wm_static_resource.erl
@@ -0,0 +1,60 @@
+%% @author author <daniel.kwiecinski@lambder.com>
+%% @copyright Daniel Kwiecinski.
+%% @doc Static webmachine resource.
+
+-module(riak_core_wm_static_resource).
+-export([init/1, allowed_methods/2,
+ content_types_provided/2, resource_exists/2, last_modified/2, provide_content/2]).
+
+-include_lib("webmachine/include/webmachine.hrl").
+-include_lib("kernel/include/file.hrl").
+-record(context, {docroot,fullpath,fileinfo}).
+
+init(DocRoot) -> {ok, #context{docroot=DocRoot}}.
+
+resource_exists(ReqData, Context) ->
+ case get_full_path(Context#context.docroot, wrq:disp_path(ReqData)) of
+ undefined -> {false, ReqData, Context};
+ Path ->
+ case filelib:is_regular(Path) of
+ true ->
+ case file:read_file_info(Path) of
+ {ok, FileInfo} ->
+ {true, ReqData, Context#context{fileinfo=FileInfo}};
+ {error, _} ->
+ {false, ReqData, Context}
+ end;
+ _ -> {false, ReqData, Context}
+ end
+ end.
+
+content_types_provided(ReqData, Context) ->
+ Path = get_full_path(Context#context.docroot, wrq:disp_path(ReqData)),
+ io:format("gor path ~p~n", [Path]),
+ {[{webmachine_util:guess_mime(Path), provide_content}], ReqData, Context#context{fullpath=Path}}.
+
+allowed_methods(ReqData, Context) -> {['HEAD', 'GET'], ReqData, Context}.
+
+last_modified(ReqData, Context) ->
+ {(Context#context.fileinfo)#file_info.mtime, ReqData, Context}.
+
+provide_content(ReqData, Context) ->
+ %%util:puts(Context),
+ {ok, Value} = file:read_file(Context#context.fullpath),
+ {Value, ReqData, Context}.
+% ------------------ PRIVATE ------------------------
+
+
+get_full_path(DocRoot, Path) ->
+ io:format("docroot ~p path ~p~n", [DocRoot, Path]),
+ case mochiweb_util:safe_relative_path(Path) of
+ undefined -> undefined;
+ RelPath ->
+ FullPath = filename:join([DocRoot, RelPath]),
+ case filelib:is_dir(FullPath) of
+ true ->
+ filename:join([FullPath, "index.html"]);
+ false ->
+ FullPath
+ end
+ end.
Please sign in to comment.
Something went wrong with that request. Please try again.