📄 megaco.erl
字号:
L = tuple_to_list(T), lversion(L).lversion([]) -> "";lversion([A]) -> integer_to_list(A);lversion([A|R]) -> integer_to_list(A) ++ "." ++ lversion(R).print_mods_info(Versions) -> case key1search(mod_info, Versions) of {value, ModsInfo} when list(ModsInfo) -> io:format("Module info: ~n", []), lists:foreach(fun print_mod_info/1, ModsInfo); _ -> io:format("Module info: Not found~n", []), not_found end.print_mod_info({Module, Info}) -> % Maybe a asn1 generated module Asn1Vsn = case (catch Module:info()) of AI when is_list(AI) -> case (catch key1search(vsn, AI)) of {value, V} when is_atom(V) -> atom_to_list(V); _ -> "-" end; _ -> "-" end, Vsn = case key1search(vsn, Info) of {value, I} when integer(I) -> integer_to_list(I); _ -> "Not found" end, AppVsn = case key1search(app_vsn, Info) of {value, S1} when list(S1) -> S1; _ -> "Not found" end, CompVer = case key1search(compiler_version, Info) of {value, S2} when list(S2) -> S2; _ -> "Not found" end, CompDate = case key1search(compile_time, Info) of {value, {Year, Month, Day, Hour, Min, Sec}} -> lists:flatten( io_lib:format("~w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w", [Year, Month, Day, Hour, Min, Sec])); _ -> "Not found" end, io:format(" ~w:~n" " Vsn: ~s~n" " App vsn: ~s~n" " ASN.1 vsn: ~s~n" " Compiler ver: ~s~n" " Compile time: ~s~n", [Module, Vsn, AppVsn, Asn1Vsn, CompVer, CompDate]), ok. key1search(Key, Vals) -> case lists:keysearch(Key, 1, Vals) of {value, {Key, Val}} -> {value, Val}; false -> not_found end.key1search(Key, Vals, Def) -> case key1search(Key, Vals) of not_found -> {value, Def}; Value -> Value end.%%-----------------------------------------------------------------versions1() -> case ms1() of {ok, Mods} -> {ok, version_info(Mods)}; Error -> Error end.versions2() -> case ms2() of {ok, Mods} -> {ok, version_info(Mods)}; Error -> Error end.version_info(Mods) -> SysInfo = sys_info(), OsInfo = os_info(), ModInfo = [mod_version_info(Mod) || Mod <- Mods], [{sys_info, SysInfo}, {os_info, OsInfo}, {mod_info, ModInfo}]. mod_version_info(Mod) -> Info = Mod:module_info(), {value, {attributes, Attr}} = lists:keysearch(attributes, 1, Info), {value, {vsn, [Vsn]}} = lists:keysearch(vsn, 1, Attr), {value, {app_vsn, AppVsn}} = lists:keysearch(app_vsn, 1, Attr), {value, {compile, Comp}} = lists:keysearch(compile, 1, Info), {value, {version, Ver}} = lists:keysearch(version, 1, Comp), {value, {time, Time}} = lists:keysearch(time, 1, Comp), {Mod, [{vsn, Vsn}, {app_vsn, AppVsn}, {compiler_version, Ver}, {compile_time, Time}]}.sys_info() -> SysArch = string:strip(erlang:system_info(system_architecture),right,$\n), SysVer = string:strip(erlang:system_info(system_version),right,$\n), [{arch, SysArch}, {ver, SysVer}].os_info() -> V = os:version(), case os:type() of {OsFam, OsName} -> [{fam, OsFam}, {name, OsName}, {ver, V}]; OsFam -> [{fam, OsFam}, {ver, V}] end. ms() -> ms1().ms1() -> App = ?APPLICATION, LibDir = code:lib_dir(App), File = filename:join([LibDir, "ebin", atom_to_list(App) ++ ".app"]), case file:consult(File) of {ok, [{application, App, AppFile}]} -> case lists:keysearch(modules, 1, AppFile) of {value, {modules, Mods}} -> {ok, Mods}; _ -> {error, {invalid_format, modules}} end; Error -> {error, {invalid_format, Error}} end.ms2() -> application:get_key(?APPLICATION, modules).nc() -> {ok, Mods} = ms(), nc(Mods).nc(all) -> application:load(?APPLICATION), case application:get_key(?APPLICATION, modules) of {ok, Mods} -> application:unload(?APPLICATION), nc(Mods); _ -> {error, not_found} end;nc(Mods) when list(Mods) -> [Mod || Mod <- Mods, ok /= load(Mod, compile)].ni() -> Mods = ms(), ni(Mods).ni(all) -> application:load(?APPLICATION), case application:get_key(?APPLICATION, modules) of {ok, Mods} -> application:unload(?APPLICATION), ni(Mods); _ -> {error, not_found} end;ni(Mods) when list(Mods) -> [Mod || Mod <- Mods, ok /= load(Mod, interpret)].load(Mod, How) when atom(Mod) -> case try_load(Mod, How) of ok -> ok; _ -> io:format( "~n RETRY ~p FROM: ", [Mod]), ModString = atom_to_list(Mod) ++ ".erl", LibDir = code:lib_dir(?APPLICATION), case find_file([LibDir], ModString) of {ok, Abs} -> load(Abs, How); {error, Reason} -> io:format( " *** ERROR *** ~p~n", [Reason]), {error, Reason} end end;load(Abs, How) -> case try_load(Abs, How) of ok -> ok; {error, Reason} -> io:format( " *** ERROR *** ~p~n", [Reason]), {error, Reason} end.try_load(Mod, How) -> io:format( " ~p ", [Mod]), Flags = [{d, debug}], case How of compile -> case catch c:nc(Mod, Flags) of {ok, _} -> ok; Other -> {error, Other} end; interpret -> case catch int:ni(Mod, Flags) of {module, _} -> ok; Other -> {error, Other} end end.find_file([Dir | Dirs], File) -> case file:list_dir(Dir) of {ok, List} -> case lists:member(File, List) of true -> {ok, filename:join([Dir, File])}; false -> SubDirs = [filename:join([Dir, Sub]) || Sub <- List], case find_file(SubDirs, File) of {ok, Abs} -> {ok, Abs}; {error, _Reason} -> find_file(Dirs, File) end end; {error, _Reason} -> find_file(Dirs, File) end;find_file([], File) -> {error, {no_such_file, File}}.%%-----------------------------------------------------------------%% -----------------------------%% These functions can be used instead of the et tool for%% managing trace of the megaco application.%%-----------------------------------------------------------------%% enable_trace(Level, Destination) -> void()%% %% Parameters:%% Level -> max | min | integer()%% Destination -> File | Port | io | {io, Verbosity} | HandlerSpec%% File -> string()%% Port -> integer()%% Verbosity -> true | false%% HandlerSpec = {function(), Data}%% Data = term()%%%% Description:%% This function is used to start tracing at level Level and send%% the result either to the file File or the port Port. Note that%% it starts a tracer server.%% When Destination is the atom io (or the tuple {io, Verbosity}), %% all (printable) megaco trace events (trace_ts events which has %% Severity withing Limit) will be written to stdout using io:format. %% %%-----------------------------------------------------------------enable_trace(Level, File) when list(File) -> case file:open(File, write) of {ok, Fd} -> HandleSpec = {fun handle_trace/2, Fd}, dbg:tracer(process, HandleSpec), set_trace(Level); Err -> Err end;enable_trace(Level, Port) when integer(Port) -> dbg:tracer(port, dbg:trace_port(ip, Port)), set_trace(Level);enable_trace(Level, io) -> HandleSpec = {fun handle_trace/2, standard_io}, dbg:tracer(process, HandleSpec), set_trace(Level);enable_trace(Level, {Fun, _Data} = HandleSpec) when function(Fun) -> dbg:tracer(process, HandleSpec), set_trace(Level).%%-----------------------------------------------------------------%% disable_trace() -> void()%% %% Description:%% This function is used to stop tracing.%%-----------------------------------------------------------------disable_trace() -> %% This is to make handle_trace/2 close the output file (if the %% event gets there before dbg closes) report_event(stop_trace, stop_trace, stop_trace, stop_trace, stop_trace), dbg:stop().%%-----------------------------------------------------------------%% set_trace(Level) -> void()%% %% Parameters:%% Level -> max | min | integer()%%%% Description:%% This function is used to change the trace level when tracing has%% already been started. %%-----------------------------------------------------------------set_trace(Level) -> Pat = et_selector:make_pattern({?MODULE, Level}), et_selector:change_pattern(Pat).report_event(DetailLevel, FromTo, Label, Contents) -> %% N.B External call ?MODULE:report_event(DetailLevel, FromTo, FromTo, Label, Contents).report_event(_DetailLevel, _From, _To, _Label, _Contents) -> hopefully_traced. %% ----------------------------------------------------------------------%% handle_trace(Event, Verbosity) -> Verbosity%% %% Parameters:%% Event -> The trace event (only megaco 'trace_ts' events are printed)%% Verbosity -> max | min | integer() (see Level above)%%%% Description:%% This function is "receive" and print the trace events. %% Events are printed if:%% - Verbosity is max%% - Severity is =< Verbosity (e.g. Severity = 30, and Verbosity = 40)%% Events are not printed if:%% - Verbosity is min%% - Severity is > Verbosity%%-----------------------------------------------------------------handle_trace(_, closed_file = Fd) -> Fd;handle_trace({trace_ts, _Who, call, {?MODULE, report_event, [stop_trace, stop_trace, stop_trace, stop_trace, stop_trace]}, _Timestamp}, standard_io = Fd) -> Fd;handle_trace({trace_ts, _Who, call, {?MODULE, report_event, [stop_trace, stop_trace, stop_trace, stop_trace, stop_trace]}, Timestamp}, Fd) -> (catch io:format(Fd, "stop trace at ~s~n", [format_timestamp(Timestamp)])), (catch file:close(Fd)), closed_file;handle_trace({trace_ts, Who, call, {?MODULE, report_event, [Sev, From, To, Label, Content]}, Timestamp}, Fd) -> (catch print_megaco_trace(Fd, Sev, Who, Timestamp, Label, From, To, Content)), Fd;handle_trace(Event, Fd) -> (catch print_trace(Fd, Event)), Fd.print_megaco_trace(Fd, Sev, Who, Timestamp, Label, From, To, Content) -> Ts = format_timestamp(Timestamp), io:format(Fd, "[megaco trace ~w ~w ~s] ~s " "~n From: ~p" "~n To: ~p" "~n Content: ~p" "~n", [Sev, Who, Ts, Label, From, To, Content]). print_trace(Fd, {trace, Who, What, Where}) -> io:format(Fd, "[trace]" "~n Who: ~p" "~n What: ~p" "~n Where: ~p" "~n", [Who, What, Where]);print_trace(Fd, {trace, Who, What, Where, Extra}) -> io:format(Fd, "[trace]" "~n Who: ~p" "~n What: ~p" "~n Where: ~p" "~n Extra: ~p" "~n", [Who, What, Where, Extra]);print_trace(Fd, {trace_ts, Who, What, Where, When}) -> Ts = format_timestamp(When), io:format(Fd, "[trace ~s]" "~n Who: ~p" "~n What: ~p" "~n Where: ~p" "~n", [Ts, Who, What, Where]);print_trace(Fd, {trace_ts, Who, What, Where, Extra, When}) -> Ts = format_timestamp(When), io:format(Fd, "[trace ~s]" "~n Who: ~p" "~n What: ~p" "~n Where: ~p" "~n Extra: ~p" "~n", [Ts, Who, What, Where, Extra]);print_trace(Fd, {seq_trace, What, Where}) -> io:format(Fd, "[seq trace]" "~n What: ~p" "~n Where: ~p" "~n", [What, Where]);print_trace(Fd, {seq_trace, What, Where, When}) -> Ts = format_timestamp(When), io:format(Fd, "[seq trace ~s]" "~n What: ~p" "~n Where: ~p" "~n", [Ts, What, Where]);print_trace(Fd, {drop, Num}) -> io:format(Fd, "[drop trace] ~p~n", [Num]);print_trace(Fd, Trace) -> io:format(Fd, "[trace] " "~n ~p" "~n", [Trace]).format_timestamp({_N1, _N2, N3} = Now) -> {Date, Time} = calendar:now_to_datetime(Now), {YYYY,MM,DD} = Date, {Hour,Min,Sec} = Time, FormatDate = io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), lists:flatten(FormatDate).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -