diff options
Diffstat (limited to 'lib/os_mon/src/nteventlog.erl')
-rw-r--r-- | lib/os_mon/src/nteventlog.erl | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/os_mon/src/nteventlog.erl b/lib/os_mon/src/nteventlog.erl new file mode 100644 index 0000000000..d624048c29 --- /dev/null +++ b/lib/os_mon/src/nteventlog.erl @@ -0,0 +1,162 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-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% +%% +-module(nteventlog). +-behaviour(gen_server). + +%% API +-export([start_link/2, start/2, stop/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-record(state, {port, mfa}). + +%%---------------------------------------------------------------------- +%% API +%%---------------------------------------------------------------------- + +start_link(Ident, MFA) -> + gen_server:start_link({local, nteventlog}, nteventlog, + [Ident, MFA], []). + +start(Ident, MFA) -> + gen_server:start({local, nteventlog}, nteventlog, [Ident, MFA], []). + +stop() -> + gen_server:call(nteventlog, stop). + +%%---------------------------------------------------------------------- +%% gen_server callbacks +%%---------------------------------------------------------------------- + +init([Identifier,MFA0]) -> + process_flag(trap_exit, true), + process_flag(priority, low), + + Port = case os:type() of + {win32, _OSname} -> start_portprogram(Identifier); + OS -> exit({unsupported_os, OS}) + end, + + %% If we're using os_sup:error_report/2, + %% the setting of os_sup_errortag should be used as argument + MFA = case MFA0 of + {os_sup, error_report, [_Tag]} -> + Tag = os_mon:get_env(os_sup, os_sup_errortag), + {os_sup, error_report, [Tag]}; + _ -> + MFA0 + end, + + {ok, #state{port=Port, mfa=MFA}}. + +handle_call(stop, _From, State) -> + {stop, normal, stopped, State}. + +handle_cast(_Msg, State) -> + {noreply, State}. + +handle_info({_Port, {data, Data}}, #state{mfa={M,F,A}} = State) -> + T = parse_log(Data), + apply(M, F, [T | A]), + State#state.port ! {self(), {command, "A"}}, + {noreply, State}; +handle_info({'EXIT', _Port, Reason}, State) -> + {stop, {port_died, Reason}, State#state{port=not_used}}; +handle_info(_Info, State) -> + {noreply, State}. + +terminate(_Reason, State) -> + case State#state.port of + not_used -> ignore; + Port -> + port_close(Port) + end, + ok. + +%% os_mon-2.0 +%% For live downgrade to/upgrade from os_mon-1.8[.1] +code_change(Vsn, PrevState, "1.8") -> + case Vsn of + + %% Downgrade from this version + {down, _Vsn} -> + process_flag(trap_exit, false), + + %% Downgrade to old State tuple + State = {PrevState#state.port, PrevState#state.mfa}, + {ok, State}; + + %% Upgrade to this version + _Vsn -> + process_flag(trap_exit, true), + + %% Upgrade to this state record + {Port, MFA} = PrevState, + State = #state{port=Port, mfa=MFA}, + {ok, State} + end; +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%%---------------------------------------------------------------------- +%% Internal functions +%%---------------------------------------------------------------------- + +start_portprogram(Identifier) -> + Command = + filename:join([code:priv_dir(os_mon),"bin","nteventlog.exe"]) ++ + " " ++ make_list(Identifier), + open_port({spawn,Command},[{packet,2}]). + +make_list(X) when is_atom(X) -> + atom_to_list(X); +make_list(X) -> + X. + +holl_len([$H | Rest], Sum) -> + {Sum, Rest}; +holl_len([ N | Rest], Sum) -> + NN = N - $0, + holl_len(Rest, Sum * 10 + NN). +holl_len(L) -> + holl_len(L,0). + +splitlist(L,N) -> + {lists:sublist(L,N),lists:nthtail(N,L)}. + +hollerith(Str) -> + {Len, Rest} = holl_len(Str), + splitlist(Rest,Len). + +holl_time(Str) -> + {Holl,Rest} = hollerith(Str), + Rev = lists:reverse(Holl), + B = list_to_integer(lists:reverse(lists:sublist(Rev,6))), + A = list_to_integer(lists:reverse(lists:nthtail(6,Rev))), + {{A,B,0},Rest}. + +parse_log(Str) -> + {Time, Rest1} = holl_time(Str), + {Category,Rest2} = hollerith(Rest1), + {Facility,Rest3} = hollerith(Rest2), + {Severity,Rest4} = hollerith(Rest3), + {Message,_} = hollerith(Rest4), + {Time,Category,Facility,Severity,Message}. |