diff options
Diffstat (limited to 'lib/runtime_tools/src/inviso_autostart_server.erl')
-rw-r--r-- | lib/runtime_tools/src/inviso_autostart_server.erl | 311 |
1 files changed, 0 insertions, 311 deletions
diff --git a/lib/runtime_tools/src/inviso_autostart_server.erl b/lib/runtime_tools/src/inviso_autostart_server.erl deleted file mode 100644 index 1e352822f4..0000000000 --- a/lib/runtime_tools/src/inviso_autostart_server.erl +++ /dev/null @@ -1,311 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2006-2010. 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% -%% -%% Author: Lennart �hman, [email protected] -%% --module(inviso_autostart_server). --export([init/1]). - -%% ----------------------------------------------------------------------------- -%% Internal exports -%% ----------------------------------------------------------------------------- --export([cmd_file_interpreter_init/4]). -%% ----------------------------------------------------------------------------- - - -%% This module provides a (well working) example of how to program an -%% autostart server responsible for initializing trace, setting patterns -%% and flags. -%% -%% The general idea is that this code spawns interpreter processes in order to -%% execute commands concurrently. Each of the interpreter processes opens one or -%% several files (in sequence) containing erlang function calls which are evaluated -%% in the interpreter process context. -%% The argument provided to init shall be a list of options controlling -%% how to initialize tracing, which file(s) to open and variable bindings. -%% -%% This autostart_server interpreters understands standard inviso trace case files. -%% -%% The runtime component provides an API very similar to the API provided -%% by the control component. It is therefore easy to translate inviso calls to -%% inviso_rt calls. -%% -%% This process may be killed by the inviso_rt process if stop_tracing is called. -%% The reason is that there is no time limit to the interpreter processes. Hence -%% they should be killed if tracing is not possible anylonger. -%% ============================================================================= - - -%% ----------------------------------------------------------------------------- - -%% The independent autostart process spawned by the runtime component to carry -%% out initializations is spawened on this function (if using the example -%% autostart which comes with inviso). -%% ArgsFromConfig is as can be heard from the name comming from a paramater in -%% the autostart configuration file. Here it is supposed to be: -%% ArgsFromConfig=[ServerParam,...] -%% ServerParam={tracerdata,TracerData}|{cmdfiles,Files}|{bindings,Bindings}| -%% {translations,Translations}|{debug,DbgLevel} -%% TracerData=tracerdata given to inviso_rt:init_tracing/1 function. -%% Files=[FileNameSpecs,...] where each FileNameSpecs will be executed in -%% a separate process. Making each FileNameSpec parallel. -%% FileNameSpecs=[FileNameSpec,...] -%% FileNameSpec=FileName | {FileName,Bindings} -%% Bindings=[{Var,Value},...] variable environment understood by -%% erl_eval:exprs/2. -%% Translations=[Translation,...] -%% A translation file is a text-file with following tuples -%% Translation={{Mod,Func,Arity,{Mod2,Func2,ParamMF}}}| -%% {{Func,Arity,{Mod2,Func2,ParamMF}}} -%% ParamMF={M,F} | any() -%% Translates Mod:Func/Arity to Mod2:Func2 with the arguments to -%% Mod:Func translated using M:F/1. Note that ParamMF is not -%% necessarily an MF. If no translation shall be done, ParamMF -%% shall be anything else but an MF. -%% Also note that Mod is optional in a Translation. That means that -%% function calls without a module in the trace case file will -%% be translated according to that translation. -init(ArgsFromConfig) -> - case get_tracerdata_opts(ArgsFromConfig) of - {ok,TracerData} -> % Otherwise we can not start a trace! - case inviso_rt:init_tracing(TracerData) of - {ok,_Response} -> % Ok, tracing has been initiated. - case get_cmdfiles_opts(ArgsFromConfig) of - {ok,CmdFiles} -> % List of cmd-files. - Bindings=get_initialbindings_opts(ArgsFromConfig), - Translations=get_translations_opts(ArgsFromConfig), - Dbg=get_dbg_opts(ArgsFromConfig), - Procs=start_cmd_file_interpreters(CmdFiles, - Bindings, - Translations, - Dbg), - loop(Procs,Dbg); % Wait for procs to be done. - false -> % Then we can terminate normally. - true - end; - {error,Reason} -> % This is fault, lets terminate abnormally. - exit({inviso,{error,Reason}}) - end; - false -> % Then there is not much use then. - true % Just terminate normally. - end. -%% ----------------------------------------------------------------------------- - -%% Help function which starts a process for each item found in the FileNames -%% list. The idea is that each item will be processed concurrently. The items -%% them selves may be a sequence of filenames. -%% Returns a list of spawned interpret processes. -start_cmd_file_interpreters([FileNames|Rest],Bindings,Translations,Dbg) -> - P=spawn_link(?MODULE,cmd_file_interpreter_init,[FileNames,Bindings,Translations,Dbg]), - MRef=erlang:monitor(process,P), % Can't trap exits in this process. - [{P,MRef}|start_cmd_file_interpreters(Rest,Bindings,Translations,Dbg)]; -start_cmd_file_interpreters([],_,_,_) -> - []. -%% ----------------------------------------------------------------------------- - - -%% The loop where this process simply waits for all of the interpreters to be -%% done. Note that that may take som time. An interpreter may take as long time -%% necessary to do its task. -loop(Procs,Dbg) -> - receive - {'DOWN',MRef,process,Pid,_Reason} -> - case lists:keysearch(MRef,1,Procs) of - {value,{Pid,_}} -> % It was an interpreter that terminated. - case lists:keydelete(MRef,1,Procs) of - [] -> % No more interpreters. - true; % Then terminate. - NewProcs -> - loop(NewProcs,Dbg) - end; - false -> - loop(Procs,Dbg) - end; - _ -> - loop(Procs,Dbg) - end. - - -%% ----------------------------------------------------------------------------- -%% The interpret process. -%% -%% An interpreter process executes trace case files. Several interpreter processes -%% may be running in parallel. It is not within the scoop of this implementation -%% of an autostart server to solve conflicts. (You may implement your own autostart -%% server!). -%% An interpret process may run for as long as necessary. Hence the function called -%% within the trace case file can contain wait functions, waiting for a certain -%% system state to occure before continuing. -%% Note that this process also mixes global and local bindings. GlobalBindings -%% is a binding() structure, where LocalBindings is a list of {Var,Value}. -%% Further it is possible to let FileName be a {inviso,Func,Args} tuple instead. -%% ----------------------------------------------------------------------------- - -%% Init function for an interpreter process instance. -cmd_file_interpreter_init(FileNames,GlobalBindings,Translations,Dbg) -> - interpret_cmd_files(FileNames,GlobalBindings,Translations,Dbg). - -interpret_cmd_files([{FileName,LocalBindings}|Rest],GlobalBindings,Translations,Dbg) -> - Bindings=join_local_and_global_vars(LocalBindings,GlobalBindings), - interpret_cmd_files_1(FileName,Bindings,Translations,Dbg), - interpret_cmd_files(Rest,GlobalBindings,Translations,Dbg); -interpret_cmd_files([],_,_,_) -> % Done, return nothing significant! - true; -interpret_cmd_files(FileName,GlobalBindings,Translations,Dbg) -> - interpret_cmd_files_1(FileName,GlobalBindings,Translations,Dbg). -% interpret_cmd_files(Rest,GlobalBindings,Translations,Dbg). - -%% This is "inline" inviso calls. -interpret_cmd_files_1({inviso,F,Args},Bindings,Translations,Dbg) -> - {ok,Tokens1,_}=erl_scan:string("inviso:"++atom_to_list(F)++"("), - Tokens2=tokenize_args(Args), - {ok,Tokens3,_}=erl_scan:string(")."), - case erl_parse:parse_exprs(Tokens1++Tokens2++Tokens3) of - {ok,Exprs} -> - interpret_cmd_files_3(Bindings,Exprs,Translations,Dbg); - {error,_Reason} -> - error - end; -interpret_cmd_files_1({Mod,Func,Args},_Bindings,_Translations,_Dbg) -> - catch apply(Mod,Func,Args); -%% This is the case when it actually is a trace case file. -interpret_cmd_files_1(FileName,Bindings,Translations,Dbg) -> - case file:open(FileName,[read]) of - {ok,FD} -> - interpret_cmd_files_2(FD,Bindings,io:parse_erl_exprs(FD,""),Translations,Dbg), - file:close(FD); - {error,Reason} -> % Something wrong with the file. - inviso_rt_lib:debug(Dbg,interpret_cmd_files,[FileName,{error,Reason}]) - end. - -%% Help function which handles Exprs returned from io:parse_erl_exprs and -%% tries to eval them. It is the side-effects we are interested in, like -%% setting flags and patterns. Note that we will get a failure should there -%% be a variable conflict. -%% Also note that there is logic to translate control component API calls to -%% corresponding runtime component calls. -%% Returns nothing significant. -interpret_cmd_files_2(FD,Bindings,{ok,Exprs,_},Translations,Dbg) -> - {next,NewBindings}=interpret_cmd_files_3(Bindings,Exprs,Translations,Dbg), - interpret_cmd_files_2(FD,NewBindings,io:parse_erl_exprs(FD,""),Translations,Dbg); -interpret_cmd_files_2(FD,Bindings,{error,ErrorInfo,Line},Translations,Dbg) -> - inviso_rt_lib:debug(Dbg,parse_erl_exprs,[ErrorInfo,Line]), - interpret_cmd_files_2(FD,Bindings,io:parse_erl_exprs(FD,""),Translations,Dbg); -interpret_cmd_files_2(_,_,{eof,_},_,_) -> % End of file. - true. - -interpret_cmd_files_3(Bindings,Exprs,Translations,Dbg) -> - case catch inviso_rt_lib:transform(Exprs,Translations) of - NewExprs when is_list(NewExprs) -> % We may have translated the API. - case catch erl_eval:exprs(NewExprs,Bindings) of - {'EXIT',Reason} -> - inviso_rt_lib:debug(Dbg,exprs,[Exprs,Bindings,{'EXIT',Reason}]), - {next,Bindings}; - {value,_Val,NewBindings} -> % Only interested in the side effects! - {next,NewBindings} - end; - {'EXIT',Reason} -> - inviso_rt_lib:debug(Dbg,translate2runtime_funcs,[Exprs,Reason]), - {next,Bindings} - end. - -%% Help function adding variables to a bindings structure. If the variable already -%% is assigned in the structure, it will be overridden. Returns a new -%% bindings structure. -join_local_and_global_vars([{Var,Val}|Rest],Bindings) when is_atom(Var) -> - join_local_and_global_vars(Rest,erl_eval:add_binding(Var,Val,Bindings)); -join_local_and_global_vars([_|Rest],Bindings) -> - join_local_and_global_vars(Rest,Bindings); -join_local_and_global_vars([],Bindings) -> - Bindings. - -%% Help function returning a string of tokens, including "," separation -%% between the arguments. -tokenize_args(Args=[Arg|Rest]) when length(Args)>1 -> - AbsTerm=erl_parse:abstract(Arg), - Tokens=erl_parse:tokens(AbsTerm), - {ok,Token,_}=erl_scan:string(","), - Tokens++Token++tokenize_args(Rest); -tokenize_args([Arg]) -> - AbsTerm=erl_parse:abstract(Arg), - erl_parse:tokens(AbsTerm); -tokenize_args([]) -> - "". -%% ----------------------------------------------------------------------------- - - -%% ----------------------------------------------------------------------------- -%% Help functions working on the options given as argument to init during spawn. -%% ----------------------------------------------------------------------------- - -get_tracerdata_opts(ArgsFromConfig) -> - case lists:keysearch(tracerdata,1,ArgsFromConfig) of - {value,{_,{mfa,{M,F,CompleteTDGargs}}}} -> % Dynamic tracerdata. - case catch apply(M,F,CompleteTDGargs) of - {'EXIT',_Reason} -> - false; - TracerData -> - {ok,TracerData} - end; - {value,{_,TracerData}} -> % Interpret this as static tracerdata. - {ok,TracerData}; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -get_cmdfiles_opts(ArgsFromConfig) -> - case lists:keysearch(cmdfiles,1,ArgsFromConfig) of - {value,{_,CmdFiles}} -> - {ok,CmdFiles}; - false -> - false - end. -%% ----------------------------------------------------------------------------- - -get_initialbindings_opts(ArgsFromConfig) -> - case lists:keysearch(bindings,1,ArgsFromConfig) of - {value,{_,Bindings}} -> - Bindings; - false -> % Then we use empty bindings. - erl_eval:new_bindings() - end. -%% ----------------------------------------------------------------------------- - -get_translations_opts(ArgsFromConfig) -> - case lists:keysearch(translations,1,ArgsFromConfig) of - {value,{_,Translations}} -> - Translations; - false -> % This becomes nearly point less. - [] - end. -%% ----------------------------------------------------------------------------- - -get_dbg_opts(ArgsFromConfig) -> - case lists:keysearch(debug,1,ArgsFromConfig) of - {value,{_,DbgLevel}} -> - DbgLevel; - false -> - off - end. -%% ----------------------------------------------------------------------------- - -%% EOF - - - |