webtool.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,205 行 · 第 1/3 页
ERL
1,205 行
%execute every start or stop data about a tool.%----------------------------------------------------------------------handle_apps2([{Name,Start_data}],State,Cmd)-> case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd) of ok-> Started = case Cmd of start -> [Name|State#state.started]; stop -> lists:delete(Name,State#state.started) end, {ok,#state{priv_dir=State#state.priv_dir, app_data=State#state.app_data, supvis=State#state.supvis, web_data=State#state.web_data, started=Started}}; _-> error end;handle_apps2([{Name,Start_data}|Rest],State,Cmd)-> case handle_app({Name,Start_data},State#state.app_data,State#state.supvis,Cmd)of ok-> handle_apps2(Rest,State,Cmd); _-> error end.%----------------------------------------------------------------------% Handle start and stop of applications%---------------------------------------------------------------------- handle_app({Name,{start,{func,Start,Stop}}},Data,_Pid,Cmd)-> Action = case Cmd of start -> Start; _ -> Stop end, case Action of {M,F,A} -> case catch apply(M,F,A) of {'EXIT',_} = Exit-> %%! Here the tool disappears from the webtool interface!! io:format("\n=======ERROR (webtool, line ~w) =======\n" "Could not start application \'~p\'\n\n" "~w:~w(~s) ->\n" "~p\n\n", [?LINE,Name,M,F,format_args(A),Exit]), ets:delete(Data,Name); _OK-> ok end; _NoStart -> ok end; handle_app({Name,{start,{child,ChildSpec}}},Data,Pid,Cmd)-> case Cmd of start -> case catch supervisor:start_child(Pid,ChildSpec) of {ok,_}-> ok; {ok,_,_}-> ok; {error,Reason}-> %%! Here the tool disappears from the webtool interface!! io:format("\n=======ERROR (webtool, line ~w) =======\n" "Could not start application \'~p\'\n\n" "supervisor:start_child(~p,~p) ->\n" "~p\n\n", [?LINE,Name,Pid,ChildSpec,{error,Reason}]), ets:delete(Data,Name); Error -> %%! Here the tool disappears from the webtool interface!! io:format("\n=======ERROR (webtool, line ~w) =======\n" "Could not start application \'~p\'\n\n" "supervisor:start_child(~p,~p) ->\n" "~p\n\n", [?LINE,Name,Pid,ChildSpec,Error]), ets:delete(Data,Name) end; stop -> case catch supervisor:terminate_child(websup,element(1,ChildSpec)) of ok -> supervisor:delete_child(websup,element(1,ChildSpec)); _ -> error end end;handle_app({Name,{start,{app,Real_name}}},Data,_Pid,Cmd)-> case Cmd of start -> case application:start(Real_name,temporary) of ok-> io:write(Name), ok; {error,{already_started,_}}-> %% Remove it from the database so we dont start %% anything already started ets:match_delete(Data,{Name,{start,{app,Real_name}}}), ok; {error,_Reason}=Error-> %%! Here the tool disappears from the webtool interface!! io:format("\n=======ERROR (webtool, line ~w) =======\n" "Could not start application \'~p\'\n\n" "application:start(~p,~p) ->\n" "~p\n\n", [?LINE,Name,Real_name,temporary,Error]), ets:delete(Data,Name) end; stop -> application:stop(Real_name) end;%----------------------------------------------------------------------% If the data is incorrect delete the app%----------------------------------------------------------------------handle_app({Name,Incorrect},Data,_Pid,Cmd)-> %%! Here the tool disappears from the webtool interface!! io:format("\n=======ERROR (webtool, line ~w) =======\n" "Could not ~w application \'~p\'\n\n" "Incorrect data: ~p\n\n", [?LINE,Cmd,Name,Incorrect]), ets:delete(Data,Name).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% this functions creates the page that shows the unstarted tools %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%reload_started_apps()-> "<script> function reloadCompiledList() { parent.parent.top1.document.location.href=\"/webtool/webtool/started_tools\"; } </script>".show_unstarted_apps(State)-> "<TABLE HEIGHT=100% WIDTH=100% BORDER=0> <TR HEIGHT=80%><TD ALIGN=\"center\" VALIGN=\"middle\"> <FORM NAME=\"stop_apps\" ACTION=\"/webtool/webtool/start_tools\" > <TABLE BORDER=1 WIDTH=60%> <TR BGCOLOR=\"#8899AA\"> <TD ALIGN=CENTER COLSPAN=2><FONT SIZE=4>Available Tools<FONT></TD> </TR> <TR> <TD WIDTH=50%> <TABLE BORDER=0> "++ list_available_apps(State)++" <TR><TD COLSPAN=2> </TD></TR> <TR> <TD COLSPAN=2 ALIGN=\"center\"> <INPUT TYPE=submit VALUE=\"Start\"> </TD> </TR> </TABLE> </TD> <TD> To Start a Tool: <UL> <LI>Select the checkbox for each tool to start.</LI> <LI>Click on the button marked <EM>Start</EM>.</LI></UL> </TD> </TR> </TABLE> </FORM> </TD></TR> <TR><TD> </TD></TR> </TABLE>".list_available_apps(State)-> MS = ets:fun2ms(fun({Tool,{web_data,{Name,_}}}) -> {Tool,Name} end), Unstarted_apps= lists:filter( fun({Tool,_})-> false==lists:member(Tool,State#state.started) end, ets:select(State#state.app_data,MS)), case Unstarted_apps of []-> "<TR><TD>All tools are started</TD></TR>"; _-> list_apps(Unstarted_apps) end.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% these functions creates the page that shows the started apps %%%% the user can select to shutdown %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%show_started_apps(State)-> "<TABLE HEIGHT=100% WIDTH=100% BORDER=0> <TR HEIGHT=80%><TD ALIGN=\"center\" VALIGN=\"middle\"> <FORM NAME=\"stop_apps\" ACTION=\"/webtool/webtool/stop_tools\" > <TABLE BORDER=1 WIDTH=60%> <TR BGCOLOR=\"#8899AA\"> <TD ALIGN=CENTER COLSPAN=2><FONT SIZE=4>Started Tools<FONT></TD> </TR> <TR> <TD WIDTH=50%> <TABLE BORDER=0> "++ list_started_apps(State)++" <TR><TD COLSPAN=2> </TD></TR> <TR> <TD COLSPAN=2 ALIGN=\"center\"> <INPUT TYPE=submit VALUE=\"Stop\"> </TD> </TR> </TABLE> </TD> <TD> Stop a Tool: <UL> <LI>Select the checkbox for each tool to stop.</LI> <LI>Click on the button marked <EM>Stop</EM>.</LI></UL> </TD> </TR> </TABLE> </FORM> </TD></TR> <TR><TD> </TD></TR> </TABLE>".list_started_apps(State)-> MS = lists:map(fun(A) -> {{A,{web_data,{'$1','_'}}},[],[{{A,'$1'}}]} end, State#state.started), Started_apps= ets:select(State#state.app_data,MS), case Started_apps of []-> "<TR><TD>No tool is started yet.</TD></TR>"; _-> list_apps(Started_apps) end.list_apps(Apps) -> lists:map(fun({Tool,Name})-> "<TR><TD> <INPUT TYPE=\"checkbox\" NAME=\"app\" VALUE=\"" ++ atom_to_list(Tool) ++ "\"> " ++ Name ++ " </TD></TR>" end, Apps).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Collecting the data from the *.tool files %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%----------------------------------------% get_tools(Dirs) => [{M,F,A},{M,F,A}...{M,F,A}]% Dirs - [string()] Directory names% Calls get_tools2/2 recursively for a number of directories% to retireve the configuration data for the web based tools.%----------------------------------------get_tools1(Dirs)-> get_tools1(Dirs,[]).get_tools1([Dir|Rest],Data) when is_list(Dir) -> Tools=case filename:basename(Dir) of %% Dir is an 'ebin' directory, check in '../priv' as well "ebin" -> [get_tools2(filename:join(filename:dirname(Dir),"priv")) | get_tools2(Dir)]; _ -> get_tools2(Dir) end, get_tools1(Rest,[Tools|Data]);get_tools1([],Data) -> lists:flatten(Data).%----------------------------------------% get_tools2(Directory) => DataList% DataList : [WebTuple]|[]% WebTuple: {tool,[{web,M,F,A}]}%%----------------------------------------get_tools2(Dir)-> get_tools2(tool_files(Dir),[]).get_tools2([ToolFile|Rest],Data) -> case get_tools3(ToolFile) of {tool,WebData} -> get_tools2(Rest,[{tool,WebData}|Data]); {error,_Reason} -> get_tools2(Rest,Data); nodata -> get_tools2(Rest,Data) end;get_tools2([],Data) -> Data.%----------------------------------------% get_tools3(ToolFile) => {ok,Tool}|{error,Reason}|nodata % Tool: {tool,[KeyValTuple]}% ToolFile - string() A .tool file% Now we have the file get the data and sort it out%----------------------------------------get_tools3(ToolFile) -> case file:consult(ToolFile) of {error,open} -> {error,nofile}; {error,read} -> {error,format}; {ok,[{version,"1.2"},ToolInfo]} when is_list(ToolInfo)-> webdata(ToolInfo); {ok,[{version,_Vsn},_Info]} -> {error,old_version}; {ok,_Other} -> {error,format} end.%----------------------------------------------------------------------% webdata(TupleList)-> ToolTuple| nodata% ToolTuple: {tool,[{config_func,{M,F,A}}]}%% There are a little unneccesary work in this format but it is extendable%----------------------------------------------------------------------webdata(TupleList)-> case httpd_util:key1search(TupleList,config_func,nodata) of {M,F,A} -> {tool,[{config_func,{M,F,A}}]}; _ -> nodata end.%=============================================================================% Functions for getting *.tool configuration files%=============================================================================%----------------------------------------% tool_files(Dir) => ToolFiles% Dir - string() Directory name% ToolFiles - [string()]% Return the list of all files in Dir ending with .tool (appended to Dir)%----------------------------------------tool_files(Dir) -> case file:list_dir(Dir) of {ok,Files} -> filter_tool_files(Dir,Files); {error,_Reason} -> [] end.%----------------------------------------% filter_tool_files(Dir,Files) => ToolFiles% Dir - string() Directory name% Files, ToolFiles - [string()] File names% Filters out the files in Files ending with .tool and append them to Dir%----------------------------------------filter_tool_files(_Dir,[]) -> [];filter_tool_files(Dir,[File|Rest]) -> case filename:extension(File) of ".tool" -> [filename:join(Dir,File)|filter_tool_files(Dir,Rest)]; _ -> filter_tool_files(Dir,Rest) end.%%%-----------------------------------------------------------------%%% format functionsffunc({M,F,A}) when is_list(A) -> io_lib:format("~w:~w(~s)\n",[M,F,format_args(A)]);ffunc({M,F,A}) when is_integer(A) -> io_lib:format("~w:~w/~w\n",[M,F,A]).format_args([]) -> "";format_args(Args) -> Str = lists:append(["~p"|lists:duplicate(length(Args)-1,",~p")]), io_lib:format(Str,Args).
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?