aboutsummaryrefslogtreecommitdiffstats
path: root/lib/os_mon/src/nteventlog.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/os_mon/src/nteventlog.erl')
-rw-r--r--lib/os_mon/src/nteventlog.erl162
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}.