diff options
Diffstat (limited to 'lib/appmon/src/appmon_dg.erl')
-rw-r--r-- | lib/appmon/src/appmon_dg.erl | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/lib/appmon/src/appmon_dg.erl b/lib/appmon/src/appmon_dg.erl new file mode 100644 index 0000000000..f53defa946 --- /dev/null +++ b/lib/appmon/src/appmon_dg.erl @@ -0,0 +1,205 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%%------------------------------------------------------------ +%% +%% Digraph handling for process view GUI. Feeble attempt at data +%% separation. Provides functional interface to the data structures +%% vdata and edata, v for vertex and e for edge. +%% +%%------------------------------------------------------------ +-module(appmon_dg). + +-include("appmon_dg.hrl"). + +%% Exports for vertices +-export([get/3, get/2, set/4, av/3, add/4, del/2, visited/3]). + +%% Exports for edges +-export([eget/2, eget/3, eset/4, eadd/4, edel/2, ae/3]). + +%% Exports for convenience +-export([print_dg/1]). + + +%%------------------------------------------------------------ + + +eget(all, DG) -> + digraph:edges(DG). + +eget(data, DG, E) -> + case digraph:edge(DG, E) of + {_, _V1, _V2, Data} -> Data; + _Other -> false + end; +eget(edge, DG, {V1, V2}) -> + case digraph:edge(DG, {V1, V2}) of + {E, W1, W2, ED} -> {E, W1, W2, ED}; + Other -> + case digraph:edge(DG, {V2, V1}) of + {E, W1, W2, ED} -> {E, W1, W2, ED}; + Other -> false + end + end; + +%% Weight in edge name +eget(edge, DG, {V1, V2, Weight}) -> + case digraph:edge(DG, {V1, V2, Weight}) of + {E, W1, W2, ED} -> {E, W1, W2, ED}; + _Other -> false + end; +eget(in, DG, V) -> + efilter(digraph:in_edges(DG, V)). + +efilter(Es) -> + lists:filter(fun({_V1, _V2, primary}) -> true; + (_E) -> false end, + Es). + +eset(ref, DG, E, Ref) -> + {E2, _V1, _V2, D} = eget(edge, DG, E), + update_e(DG, E2, D#edata{ref=Ref}); +eset(line, DG, E, Line) -> + {E2, _V1, _V2, D} = eget(edge, DG, E), + update_e(DG, E2, D#edata{line=Line}). + +edel(DG, E) -> + digraph:del_edge(DG, E). + +eadd(DG, E, D, Ref) -> + case eget(edge, DG, E) of + {_, _, _, ED} when is_record(ED, edata), ED#edata.ref == Ref -> + known; + {_, _, _, ED} when is_record(ED, edata), ED#edata.ref /= Ref -> + update_e(DG, E, ED#edata{ref=Ref}), + updated; + _Other -> + ae(DG, E, D) + end. + +ae(DG, {V1, V2, Weight}, D) -> + digraph:add_edge(DG, {V1, V2, Weight}, V1, V2, D). + +update_e(DG, {V1, V2, Weight}, D) -> + digraph:del_edge(DG, {V1, V2, Weight}), + digraph:add_edge(DG, {V1, V2, Weight}, V1, V2, D). + +%% Filter destination vertex from a list of edges +vfilter(Vs) -> + lists:map(fun({_V1, V2, _Weight}) -> V2; + ({_V1, V2}) -> V2 + end, Vs). + +get(all, DG) -> + digraph:vertices(DG). + +get(data, DG, {V1, V2}) -> + case digraph:edge(DG, {V1, V2}) of + {_,_,_,Data} -> Data; + _Other -> false + end; +get(data, DG, V) -> + case digraph:vertex(DG, V) of + {_,Data} -> Data; + _Other -> false + end; + +%% Return all children of vertex V (those which V has edges to) +get(out, DG, V) -> + vfilter(efilter(digraph:out_edges(DG, V))); +get(in, DG, V) -> + digraph:in_neighbours(DG, V); +get(edges, DG, V) -> + digraph:edges(DG, V); +get(w, DG, V) -> + Data = get(data, DG, V), + Data#vdata.width; +get(x, DG, V) -> + Data = get(data, DG, V), + Data#vdata.x. + +set(type, DG, V, Type) -> + D = get(data, DG, V), + av(DG, V, D#vdata{type=Type}); + +set(ref, DG, V, Ref) -> + D = get(data, DG, V), + av(DG, V, D#vdata{ref=Ref}); + +set(y, DG, V, Y) -> + D = get(data, DG, V), + av(DG, V, D#vdata{y=Y}); + +set(data, DG, V, D) when is_record(D, vdata)-> + av(DG, V, D); + +set(x, DG, V, X) -> + D = get(data, DG, V), + if D#vdata.x /= X -> + av(DG, V, D#vdata{x=X}); + true -> true + end. + +visited(DG, {V1, V2}, Ref) -> % for edge + D = eget(data, DG, {V1, V2}), + if is_record(D, edata), D#edata.ref == Ref -> true; + true -> false + end; +visited(DG, V, Ref) -> + D = get(data, DG, V), + if is_record(D, vdata), D#vdata.ref == Ref -> true; + true -> false + end. + +add(DG, V, D, Ref) -> + case get(data, DG, V) of + D2 when is_record(D2, vdata), D2#vdata.ref==Ref -> + io:format("Ooops in ~p:add vertex~n", [?MODULE]), + known; + D2 when is_record(D2, vdata) -> + %%io:format("~p touch vertex ~p~n", [self(), V]), + set(ref, DG, V, Ref), + set(type, DG, V, D#vdata.type), + save_coords(DG, V), + updated; + _Other -> + av(DG, V, D), added + end. + +save_coords(DG, V) -> + D = get(data, DG, V), + D2 = D#vdata{origx=D#vdata.x, origy=D#vdata.y}, + av(DG, V, D2). + +del(DG, V) -> + digraph:del_vertex(DG, V). + + +av(DG, V, D) -> + digraph:add_vertex(DG, V, D). + +print_dg(DG) -> + io:format("Vertices:~n", []), + lists:foreach(fun(V) -> io:format(" ~p ~p~n", + [V, get(data, DG, V)]) end, + get(all, DG)), + io:format("Edges:~n", []), + lists:foreach(fun(V) -> io:format(" ~p ~p~n", + [V, eget(edge, DG, V)]) end, + eget(all, DG)), + true. |