Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 831a035
Showing
8 changed files
with
359 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
%% @copyright Geoff Cant 2009, 2010 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @version {@vsn}, {@date} {@time} | ||
%% @doc Erlang shell code to trace the messages for one process. | ||
%% @end | ||
|
||
dbg:stop_clear(). | ||
f(GL). | ||
GL=group_leader(). | ||
f(TS). | ||
TS = fun (TimeStamp = {_,_,Mics}) -> | ||
{_,{H, M, Secs}} = calendar:now_to_local_time(TimeStamp), | ||
Micros = Mics div 1000, | ||
Seconds = Secs rem 60 + (Micros / 1000), | ||
[H,M,Seconds]; | ||
(OtherTimestamp) -> | ||
io:format("Help, help, got weird ts: ~p~n", [OtherTimestamp]), | ||
[0,0,0] | ||
end, | ||
dbg:tracer(process, | ||
{fun (Msg, State) -> | ||
case Msg of | ||
{trace, Pid, 'receive', TMsg} -> | ||
[H,M,Seconds] = TS(erlang:now()), | ||
io:format(GL, "~n~p:~p:~p ~p < ~p~n", | ||
[H, M, Seconds, Pid, TMsg]); | ||
{trace, Pid, 'send', TMsg, ToPid} -> | ||
[H,M,Seconds] = TS(erlang:now()), | ||
io:format(GL, "~n~p:~p:~p ~p > ~p: ~p~n", | ||
[H, M, Seconds, Pid, ToPid, TMsg]); | ||
{trace_ts, Pid, 'receive', TMsg, Timestamp} -> | ||
[H,M,Seconds] = TS(Timestamp), | ||
io:format(GL, "~n~p:~p:~pt ~p < ~p~n", | ||
[H, M, Seconds, Pid, TMsg]); | ||
{trace_ts, Pid, 'send', TMsg, ToPid, Timestamp} -> | ||
[H,M,Seconds] = TS(Timestamp), | ||
io:format(GL, "~n~p:~p:~pt ~p > ~p: ~p~n", | ||
[H, M, Seconds, Pid, ToPid, TMsg]); | ||
_Else -> | ||
Timestamp = case element(tuple_size(Msg), Msg) of | ||
{Mg,S,MS} when is_integer(Mg), | ||
is_integer(S), | ||
is_integer(MS) -> | ||
{Mg, S, MS}; | ||
_Other -> erlang:now() | ||
end, | ||
[H,M,Seconds] = TS(Timestamp), | ||
io:format(GL, "~n~p:~p:~p ~p~n", | ||
[H, M, Seconds, Msg]) | ||
|
||
end, | ||
State | ||
end, | ||
undefined}). | ||
|
||
f(Trace). | ||
Trace = fun(Pid) -> dbg:p(Pid, [m]) end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
%% @copyright Geoff Cant 2009, 2010 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @version {@vsn}, {@date} {@time} | ||
%% @doc Erlang shell code to trace process messages to a wrap log. | ||
%% @end | ||
|
||
dbg:stop_clear(). | ||
f(GL). | ||
GL=group_leader(). | ||
f(TS). | ||
TS = fun (TimeStamp = {_,_,Mics}) -> | ||
{_,{H, M, Secs}} = calendar:now_to_local_time(TimeStamp), | ||
Micros = Mics div 1000, | ||
Seconds = Secs rem 60 + (Micros / 1000), | ||
[H,M,Seconds]; | ||
(OtherTimestamp) -> | ||
io:format("Help, help, got weird ts: ~p~n", [OtherTimestamp]), | ||
[0,0,0] | ||
end. | ||
f(Log). | ||
{ok, Log} = disk_log:open([{name, dbg_log}, | ||
{file, "dbg_trace_log"}, | ||
{format, external}, | ||
{type, wrap}, | ||
{size, {1024*1024, 10}}, | ||
{mode, read_write}]). | ||
dbg:tracer(process, | ||
{fun (Msg, State) -> | ||
S = case Msg of | ||
{trace, Pid, 'receive', TMsg} -> | ||
[H,M,Seconds] = TS(erlang:now()), | ||
io_lib:format("~n~p:~p:~p ~p < ~p~n", | ||
[H, M, Seconds, Pid, TMsg]); | ||
{trace, Pid, 'send', TMsg, ToPid} -> | ||
[H,M,Seconds] = TS(erlang:now()), | ||
io_lib:format("~n~p:~p:~p ~p > ~p: ~p~n", | ||
[H, M, Seconds, Pid, ToPid, TMsg]); | ||
{trace_ts, Pid, 'receive', TMsg, Timestamp} -> | ||
[H,M,Seconds] = TS(Timestamp), | ||
io_lib:format("~n~p:~p:~pt ~p < ~p~n", | ||
[H, M, Seconds, Pid, TMsg]); | ||
{trace_ts, Pid, 'send', TMsg, ToPid, Timestamp} -> | ||
[H,M,Seconds] = TS(Timestamp), | ||
io_lib:format("~n~p:~p:~pt ~p > ~p: ~p~n", | ||
[H, M, Seconds, Pid, ToPid, TMsg]); | ||
_Else -> | ||
Timestamp = case element(tuple_size(Msg), Msg) of | ||
{Mg,Se,MS} when is_integer(Mg), | ||
is_integer(Se), | ||
is_integer(MS) -> | ||
{Mg, Se, MS}; | ||
_Other -> erlang:now() | ||
end, | ||
[H,M,Seconds] = TS(Timestamp), | ||
io_lib:format("~n~p:~p:~p ~p~n", | ||
[H, M, Seconds, Msg]) | ||
|
||
end, | ||
disk_log:balog(Log, iolist_to_binary(S)), | ||
io:format(GL, ".", []), | ||
State | ||
end, | ||
undefined}). | ||
|
||
f(Trace). | ||
Trace = fun(Pid) -> dbg:p(Pid, [m]) end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
%% @copyright Geoff Cant 2009 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @version {@vsn}, {@date} {@time} | ||
%% @doc Reprints the source code of a module compiled with debug_info. | ||
%% @end | ||
|
||
PrintSrc = fun (Module) -> | ||
{ok,{_,[{abstract_code,{_,AC}}]}} = | ||
beam_lib:chunks(code:which(Module),[abstract_code]), | ||
io:put_chars(erl_prettypr:format(erl_syntax:form_list(AC))) | ||
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
%% @copyright Geoff Cant 2010 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @doc Erlang shell code to cause a gen* process to evaluate a fun. | ||
%% | ||
%% @license This code was translated from an ancient tome in the | ||
%% Arkham university library (restricted section, 4th vault). As such, | ||
%% use of this code is restricted to only those who see it as the | ||
%% manifestly evil. Using this code under any circumstances other than in | ||
%% dire need while debugging revokes your right to use, view, posess | ||
%% said code. | ||
%% @end | ||
|
||
f(EvalAs). | ||
EvalAs = fun (Pid, Fun) when is_function(Fun, 0) -> | ||
Ref = make_ref(), | ||
Caller = self(), | ||
F = fun (nostate, {in, {hack, | ||
_Invocation, | ||
Ref}}, ProcState) -> | ||
Caller ! {hack, <<"Ia! Ia! Cthulhu fhtagn">>, Ref, | ||
catch Fun()}, | ||
done | ||
end, | ||
sys:install(Pid, {F,nostate}), | ||
Pid ! {hack, <<"Ph'nglui mglw'nafh " | ||
"Cthulhu R'lyeh wgah'nagl fhtan">>, Ref}, | ||
receive | ||
{hack, TerrifyingResponse, Ref, Result} -> | ||
{TerrifyingResponse, Result} | ||
end | ||
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
%% @copyright Geoff Cant 2009, 2010 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @version {@vsn}, {@date} {@time} | ||
%% @doc Erlang shell code to use funs with the rpc module. | ||
%% @end | ||
|
||
f(Multicall). | ||
Multicall = fun (Fun) when is_function(Fun,0) -> | ||
element(1, rpc:multicall(erlang, apply, [ Fun, [] ])) | ||
end. | ||
|
||
f(Ncall). | ||
Ncall = fun (Nodes, Fun) when is_function(Fun,0) -> | ||
element(1, rpc:multicall(Nodes, erlang, apply, [ Fun, [] ])) | ||
end. | ||
|
||
f(NodesCalled). | ||
NodesCalled = fun (Name) -> | ||
[N || N <- nodes(known), | ||
lists:member(Name, string:tokens(atom_to_list(N), "@"))] | ||
end. | ||
|
||
f(Call). | ||
Call = fun (Node, Fun) when is_function(Fun,0) -> | ||
rpc:call(Node, erlang, apply, [ Fun, [] ]) | ||
end. | ||
|
||
f(NamedCall). | ||
NamedCall = fun (Name, Fun) -> | ||
Ncall(NodesCalled(Name), Fun) | ||
end. | ||
|
||
f(ListDiff). | ||
ListDiff = fun (L1, L2) -> | ||
L1S = sets:from_list(L1), | ||
L2S = sets:from_list(L2), | ||
{sets:to_list(sets:subtract(L2S, L1S)), | ||
sets:to_list(sets:subtract(L1S, L2S))} | ||
end. | ||
|
||
f(EvalDiff). | ||
EvalDiff = fun (Node1, Node2, F) -> | ||
ListDiff(Call(Node1, F), | ||
Call(Node2, F)) | ||
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
%% @copyright Geoff Cant 2009 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @version {@vsn}, {@date} {@time} | ||
%% @doc Alter table copy types to match types on a specific node. | ||
%% @end | ||
|
||
f(Rebalance). | ||
Rebalance = fun (IdealNode, OtherNodes) -> | ||
Tables = rpc:call(IdealNode, mnesia, system_info, [tables]), | ||
TableTypes = [{T, rpc:call(IdealNode, mnesia, table_info, [T, storage_type])} | ||
|| T <- Tables], | ||
[{Table, Type, [ case rpc:call(N, mnesia, table_info, [Table, storage_type]) of | ||
Type -> N; | ||
unknown -> | ||
{atomic, ok} = mnesia:add_table_copy(Table, N, Type), | ||
{added, N}; | ||
Other -> | ||
{atomic, ok} = mnesia:change_table_copy_type(Table, N, Type), | ||
{fixed, N} | ||
end | ||
|| N <- OtherNodes]} | ||
|| {Table, Type} <- TableTypes] | ||
end. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
%% @copyright Geoff Cant 2009 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @version {@vsn}, {@date} {@time} | ||
%% @doc Erlang shell code get the state of an OTP compliant process as | ||
%% a proplist. | ||
%% @end | ||
|
||
f(GetStatus). | ||
GetStatus = fun (Pid) -> | ||
{status,_, | ||
Module, | ||
[[{'$ancestors',Ancestors}, | ||
{'$initial_call',MFA}], | ||
_,_,Debug, | ||
[_, | ||
State, | ||
Mod,infinity]]} = sys:get_status(Pid, timer:seconds(1)), | ||
[{state, State}, | ||
Module, | ||
{ancestors, Ancestors}, | ||
{initial_call, MFA}, | ||
{debug_flags, Debug}] | ||
end. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
%% @copyright Geoff Cant 2010 | ||
%% @author Geoff Cant <nem@erlang.geek.nz> | ||
%% @version {@vsn}, {@date} {@time} | ||
%% @doc Erlang shell code to fix pg2 tables. | ||
%% @end | ||
|
||
f(Pg2Groups). | ||
Pg2Groups = fun () -> | ||
ets:select(pg2_table, | ||
ets:fun2ms(fun ({{group, G}}) -> G end)) | ||
end. | ||
f(Pg2GroupMembers). | ||
Pg2GroupMembers = fun (Groups) -> | ||
[{G, lists:usort(ets:select(pg2_table, | ||
ets:fun2ms(fun ({{pid, Pid, Gr}}) | ||
when G =:= Gr -> | ||
Pid | ||
end)))} | ||
|| G <- Groups] | ||
end. | ||
f(Pg2Pids). | ||
Pg2Pids = fun () -> | ||
lists:usort(ets:select(pg2_table, | ||
ets:fun2ms(fun ({{ref, R}, Pid}) when is_reference(R) -> Pid end))) | ||
end. | ||
f(Pg2PidGrps). | ||
Pg2PidGrps = fun (Pids) -> | ||
[{P, lists:usort(ets:select(pg2_table, | ||
ets:fun2ms(fun ({{pid, P, Grp}}) -> Grp end)))} | ||
|| P <- Pids] | ||
end. | ||
f(Pg2Refs). | ||
Pg2Refs = fun () -> | ||
lists:usort(ets:select(pg2_table, | ||
ets:fun2ms(fun ({{ref, R}, Pid}) when is_reference(R) -> | ||
{Pid, R} | ||
end))) | ||
end. | ||
f(Correct). | ||
Correct = fun () -> | ||
Groups = Pg2Groups(), | ||
GrpMembers = Pg2GroupMembers(Groups), | ||
Pids = Pg2Pids(), | ||
PidGrps = Pg2PidGrps(Pids), | ||
Refs = Pg2Refs(), | ||
|
||
lists:flatten([ [{{group, G}} || G <- Groups], | ||
[{{ref, Ref}, Pid} || {Pid, Ref} <- Refs], | ||
[{{ref, Pid}, Pid, Ref, length(proplists:get_value(Pid, PidGrps))} | ||
|| {Pid, Ref} <- Refs], | ||
[ [{{local_member, Grp, Pid}} | ||
|| Grp <- Grps] | ||
|| {Pid, Grps} <- PidGrps, node() =:= node(Pid)], | ||
[ [[{{member, Grp, Pid}, 1}, | ||
{{pid, Pid, Grp}}] | ||
|| Grp <- Grps] | ||
|| {Pid, Grps} <- PidGrps] | ||
]) | ||
end. | ||
|
||
f(Diff). | ||
Diff = fun () -> | ||
Pg2List = ets:tab2list(pg2_table), | ||
Pg2 = sets:from_list(Pg2List), | ||
RightList = Correct(), | ||
Right = sets:from_list(RightList), | ||
[ case lists:keysearch(element(1, I), 1, Pg2List) of | ||
{value, Wrong} -> | ||
Pos = tuple_size(I), | ||
{fixup, element(1,I), {Pos, element(Pos, I)}, element(Pos, Wrong)}; | ||
false -> | ||
{insert, I} | ||
end | ||
|| I <- sets:to_list(sets:subtract(Right, Pg2)) | ||
] | ||
end. | ||
|
||
|
||
f(Diff2). | ||
Diff2 = fun () -> | ||
NewData = Correct(), | ||
Right = sets:from_list(NewData), | ||
Wrong = sets:from_list(ets:tab2list(pg2_table)), | ||
sets:to_list(sets:subtract(Wrong, Right)) | ||
end. | ||
|
||
f(Fixup). | ||
Fixup = fun () -> | ||
NewData = Correct(), | ||
Right = sets:from_list(NewData), | ||
Wrong = sets:from_list(ets:tab2list(pg2_table)), | ||
Deletable = sets:to_list(sets:subtract(Wrong, Right)), | ||
ets:insert(pg2_table, NewData) | ||
end. | ||
|
||
f(ListDiff). | ||
ListDiff = fun (L1, L2) -> | ||
L1S = sets:from_list(L1), | ||
L2S = sets:from_list(L2), | ||
{sets:to_list(sets:subtract(L2, L1)), | ||
sets:to_list(sets:subtract(L1, L2))} | ||
end. |