inviso_lfm_tpfreader.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 385 行 · 第 1/2 页
ERL
385 行
%% ``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 via the world wide web 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.
%%
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
%% AB. All Rights Reserved.''
%%
%% $Id$
%%
%% Author: Lennart 謍man, lennart.ohman@st.se
%%
%% INVISO LogFileMerger TracePort File READER.
%%
%% This module implements a reader process capable of reading traceport files
%% and feeding them according to the logfile merger process message protocoll
%% to the logfile merger process.
%% This module can also serve as example for writing file readers for other
%% file formats.
%%
%% A reader process must:
%% Support the reader-receiver protocoll.
%% receive next_entry message: {get_next_entry,ReceiverPid}
%% recieve stop message should the receiver wish to quit: {stop,ReceiverPid}.
%% send next_entry message, either with entry or fault-code.
%% next_entry message contains:{next_entry,self(),PidMappings,Timestamp,Term}
%% {next_entry,self(),Error}
%% recognize receiver termination (EXIT-signal).
%% Understand logfile structure, both filename structure and content.
%% Understand content (log-entry) details to extract the entry and entry
%% components as timestamp and originating pid (to make pid-mappings).
%% Understand any trace information files (ti).
%%
%% The logfile structure written by inviso_rt_meta is:
%% {Pid,Alias,Op,TimeStamp} where:
%% Pid=pid(), if Alias==unalias: pid()|other_than_pid()
%% Op=alias|unalias,
%% TimeStamp=now()
%% -----------------------------------------------------------------------------
-module(inviso_lfm_tpfreader).
-export([init/2]).
%% -----------------------------------------------------------------------------
-export([handle_logfile_sort_wrapset/1]). % Exported as a service to other readers.
%% -----------------------------------------------------------------------------
%% init(RecPid,FileStruct)=N/A
%% RecPid=pid(), the process id of the log file merger.
%% FileStruct=LogFiles | [LogFiles,...]
%% LogFiles=[{trace_log,[File,...]} [,{ti_log,[File]}] ]
%% File=string()
%% Spawn on this function to start a reader process for trace-port generated
%% logfiles, possibly with inviso-generated ti-files.
init(RecPid,LogFiles=[Tuple|_]) when tuple(Tuple) -> % Only one LogFiles.
init(RecPid,[LogFiles]);
init(RecPid,FileStruct) when list(FileStruct) ->
logfiles_loop(RecPid,FileStruct).
%% -----------------------------------------------------------------------------
logfiles_loop(RecPid,[LogFiles|Rest]) ->
{TIalias,TIunalias}=handle_ti_file(LogFiles),% If there is a ti-file, read it.
Files=handle_logfiles(LogFiles), % Returns a sorted list of logfiles.
case open_next_file(Files) of
{ok,FileName,FD,NewFiles} ->
case loop(RecPid,FileName,NewFiles,TIalias,TIunalias,FD) of
next ->
logfiles_loop(RecPid,Rest);
stop ->
true % Terminate normally.
end;
done -> % Hmm, already out of files.
true; % Then lets terminate normally.
{error,Reason} -> % Couldn't even open the first file.
exit(Reason)
end;
logfiles_loop(_RecPid,[]) -> % No more files in LogFiles.
true. % Terminate normally.
%% This workloop reads an entry from the input file upon request from the merger
%% process and sends it back to the merger process (Parent). If the file ends
%% there are more files to open and read in Files, the next file will be opened.
loop(RecPid,FileName,Files,TIalias,TIunalias,FD) ->
receive
{get_next_entry,RecPid} -> % The receiver request the next entry.
case fetch_next(FileName,FD,Files) of
{ok,Term,NewCurrFile,NewFiles,NewFD} ->
TS=find_timestamp_in_term(Term),
PidMappings=make_pid_mappings(Term,TIalias,TIunalias,TS),
RecPid ! {next_entry,self(),PidMappings,TS,Term},
loop(RecPid,NewCurrFile,NewFiles,TIalias,TIunalias,NewFD);
{error,Reason} -> % Not a properly formatted entry.
RecPid ! {next_entry,self(),{error,Reason}},
loop(RecPid,FileName,Files,TIalias,TIunalias,FD);
done -> % No more files to read in this LogFiles.
next % Are there more Files in FileStruct?
end;
{stop,RecPid} -> % The receiver process is done.
file:close(FD), % Close file and terminate normally.
stop
end.
%% -----------------------------------------------------------------------------
%% Function which reads the next trace-entry from the file handled by FD, or if
%% that file reaches EOF opens the next file in Files. Files must be sorted in
%% the correct order.
%% Returns {ok,Term,NewFileName,NewFiles,NewFD}, {error,Reason} or 'done'.
fetch_next(FileName,FD,Files) ->
case read_traceport_file(FileName,FD) of
{ok,Term} -> % There were more terms in the file.
{ok,Term,FileName,Files,FD}; % No changes necessary then.
eof -> % This file is empty, try next file!
file:close(FD),
case open_next_file(Files) of
{ok,NewFileName,NewFD,NewFiles} -> % A new file has been opened.
fetch_next(NewFileName,NewFD,NewFiles); % Try again.
done -> % No more files.
done;
{error,Reason} -> % Problems opening files.
{error,Reason}
end;
{error,Reason} -> % Problems reading the file.
{error,Reason}
end.
read_traceport_file(FileName,FD) ->
case file:read(FD,5) of % Trace-port file entries start with 5 bytes.
{ok,<<0,Size:32>>} -> % Each entry in a traceport file begins.
case file:read(FD,Size) of
{ok,Bin} when binary(Bin),size(Bin)=:=Size ->
try binary_to_term(Bin) of
Term -> % Bin was a properly formatted term!
{ok,Term}
catch
error:_Reason -> % Not a properly formatted term!
{error,{binary_to_term,[FileName,Bin]}}
end;
{ok,Bin} -> % Incorrect length.
{error,{faulty_length,[FileName,Size,Bin]}};
eof -> % This is premature end of file!
{error,{premature_eof,FileName}}
end;
{ok,<<1,DroppedMsgs:32>>} ->
{ok,{drop,DroppedMsgs}};
{ok,JunkBin} -> % Don't understand, report it as error.
{error,{junk,[FileName,JunkBin]}};
eof -> % A correct end of file!
eof
end.
%% Help function which opens a file in raw binary mode and returns
%% {ok,FileName,FD,Rest} or {error,Reason}.
open_next_file([]) -> % There are no more files to open.
done;
open_next_file([FileName|Rest]) ->
case file:open(FileName,[read,raw,binary]) of
{ok,FD} ->
{ok,FileName,FD,Rest};
{error,Reason} ->
{error,{open,[FileName,Reason]}}
end.
%% ------------------------------------------------------------------------------
%% ==============================================================================
%% Help functions.
%% ==============================================================================
%% Help function which extract the originating process id from the log entry
%% Term and returns a list of all associations to the PID found in TIalias.
make_pid_mappings(_,void,_,_) -> % Trace Information is not used.
[]; % Simply no pid mappings then!
make_pid_mappings(Term,TIalias,TIunalias,TS)
when element(1,Term)==trace;element(1,Term)==trace_ts ->
Pid=element(2,Term), % The pid.
TempAliases=find_aliases(ets:lookup(TIalias,Pid),TS),
remove_expired_aliases(TempAliases,TIalias,TIunalias,TS),
lists:map(fun({_,_,Alias})->Alias end,
find_aliases(ets:lookup(TIalias,Pid),TS));
make_pid_mappings(_Term,_TIalias,_TIunalias,_TS) -> % Don't understand Term.
[]. % Simply no translations then!
%% Help function traversing a list of ets-alias-table entries and returning a
%% list of those old enough to have happend before TS.
find_aliases(List,TS) ->
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?