multiuser report browser enhancements [rb.erl]
Vance Shipley
vances@REDACTED
Sat Apr 10 00:12:11 CEST 2004
The attached patch to rb.erl allows users from other nodes
to use the report browser and have the output associated
with their commands go to their screen. It determines the
group leader of the requesting user and passes this along
to the print functions.
-Vance
Vance Shipley
Motivity Telecom Inc.
+1 519 240 3684
vances@REDACTED
-------------- next part --------------
*** rb.erl Fri Apr 9 17:57:51 2004
--- /Users/otpuser/otp_src_R9C-0/lib/sasl/src/rb.erl Mon Jul 7 07:59:50 2003
***************
*** 132,221 ****
init(Options) ->
process_flag(priority, low),
process_flag(trap_exit, true),
Log = get_option(Options, start_log, standard_io),
! Device = open_log_file(Log, group_leader()),
Dir = get_report_dir(Options),
Max = get_option(Options, max, all),
Type = get_option(Options, type, all),
! Data = scan_files(Dir ++ "/", Max, Type, group_leader()),
{ok, #state{dir = Dir ++ "/", data = Data, device = Device,
max = Max, type = Type}}.
%% (All those 'catch' are probably unnecessary now that we catch the
%% formatting in read_rep/4.)
! handle_call({rescan, Options}, {Pid, _Ref}, State) ->
! {group_leader, Leader} = case is_alive() of
! true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
! false -> process_info(Pid, group_leader)
! end,
Device =
case get_option(Options, start_log, {undefined}) of
{undefined} -> State#state.device;
Log ->
close_device(State#state.device),
! open_log_file(Log, Leader)
end,
Max = get_option(Options, max, State#state.max),
Type = get_option(Options, type, State#state.type),
! Data = scan_files(State#state.dir, Max, Type, Leader),
NewState = State#state{data = Data, max = Max, type = Type,
device = Device},
{reply, ok, NewState};
handle_call(stop, _From, State) ->
{stop, normal, stopped, State};
handle_call(_, _From, #state{data = undefined}) ->
{reply, {error, no_data}, #state{}};
! handle_call({list, Type}, {Pid, _Ref}, State) ->
! {group_leader, Leader} = case is_alive() of
! true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
! false -> process_info(Pid, group_leader)
! end,
! print_list(State#state.data, Type, Leader),
{reply, ok, State};
! handle_call({start_log, FileName}, {Pid, _Ref}, State) ->
! {group_leader, Leader} = case is_alive() of
! true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
! false -> process_info(Pid, group_leader)
! end,
! NewDevice = open_log_file(FileName, Leader),
{reply, ok, State#state{device = NewDevice}};
handle_call(stop_log, _From, State) ->
close_device(State#state.device),
{reply, ok, State#state{device = standard_io}};
! handle_call({show_number, Number}, {Pid, _Ref}, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! {group_leader, Leader} = case is_alive() of
! true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
! false -> process_info(Pid, group_leader)
! end,
! catch print_report(Dir, Data, Number, Device, Leader),
{reply, ok, State};
! handle_call({show_type, Type}, {Pid, _Ref}, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! {group_leader, Leader} = case is_alive() of
! true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
! false -> process_info(Pid, group_leader)
! end,
! catch print_typed_reports(Dir, Data, Type, Device, Leader),
{reply, ok, State};
! handle_call(show, {Pid, _Ref}, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! {group_leader, Leader} = case is_alive() of
! true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
! false -> process_info(Pid, group_leader)
! end,
! catch print_all_reports(Dir, Data, Device, Leader),
{reply, ok, State};
! handle_call({grep, RegExp}, {Pid, _Ref}, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! {group_leader, Leader} = case is_alive() of
! true -> rpc:call(node(Pid), erlang, process_info, [Pid, group_leader]);
! false -> process_info(Pid, group_leader)
! end,
! catch print_grep_reports(Dir, Data, RegExp, Device, Leader),
{reply, ok, State}.
terminate(_Reason, #state{device = Device}) ->
close_device(Device).
--- 132,193 ----
init(Options) ->
process_flag(priority, low),
process_flag(trap_exit, true),
Log = get_option(Options, start_log, standard_io),
! Device = open_log_file(Log),
Dir = get_report_dir(Options),
Max = get_option(Options, max, all),
Type = get_option(Options, type, all),
! Data = scan_files(Dir ++ "/", Max, Type),
{ok, #state{dir = Dir ++ "/", data = Data, device = Device,
max = Max, type = Type}}.
%% (All those 'catch' are probably unnecessary now that we catch the
%% formatting in read_rep/4.)
! handle_call({rescan, Options}, _From, State) ->
Device =
case get_option(Options, start_log, {undefined}) of
{undefined} -> State#state.device;
Log ->
close_device(State#state.device),
! open_log_file(Log)
end,
Max = get_option(Options, max, State#state.max),
Type = get_option(Options, type, State#state.type),
! Data = scan_files(State#state.dir, Max, Type),
NewState = State#state{data = Data, max = Max, type = Type,
device = Device},
{reply, ok, NewState};
handle_call(stop, _From, State) ->
{stop, normal, stopped, State};
handle_call(_, _From, #state{data = undefined}) ->
{reply, {error, no_data}, #state{}};
! handle_call({list, Type}, _From, State) ->
! print_list(State#state.data, Type),
{reply, ok, State};
! handle_call({start_log, FileName}, _From, State) ->
! NewDevice = open_log_file(FileName),
{reply, ok, State#state{device = NewDevice}};
handle_call(stop_log, _From, State) ->
close_device(State#state.device),
{reply, ok, State#state{device = standard_io}};
! handle_call({show_number, Number}, _From, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! catch print_report(Dir, Data, Number, Device),
{reply, ok, State};
! handle_call({show_type, Type}, _From, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! catch print_typed_reports(Dir, Data, Type, Device),
{reply, ok, State};
! handle_call(show, _From, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! catch print_all_reports(Dir, Data, Device),
{reply, ok, State};
! handle_call({grep, RegExp}, _From, State) ->
#state{dir = Dir, data = Data, device = Device} = State,
! catch print_grep_reports(Dir, Data, RegExp, Device),
{reply, ok, State}.
terminate(_Reason, #state{device = Device}) ->
close_device(Device).
***************
*** 225,247 ****
{noreply, State}.
code_change(OldVsn, State, Extra) ->
{ok, State}.
%%-----------------------------------------------------------------
! %% Func: open_log_file/2
%% Args: FileName | standard_io
- %% Leader ::= pid(), the group_leader to send io to
%% Returns: A Device for later use in call to io:format
%%-----------------------------------------------------------------
! open_log_file(standard_io, _Leader) -> standard_io;
! open_log_file(FileName, Leader) ->
case file:open(FileName, write) of
{ok, Fd} -> Fd;
Error ->
! io:format(Leader, "rb: Cannot open file '~s' (~w).~n",
[FileName, Error]),
! io:format(Leader, "rb: Using standard_io~n", []),
standard_io
end.
close_device(Fd) when pid(Fd) ->
catch file:close(Fd);
--- 197,218 ----
{noreply, State}.
code_change(OldVsn, State, Extra) ->
{ok, State}.
%%-----------------------------------------------------------------
! %% Func: open_log_file/1
%% Args: FileName | standard_io
%% Returns: A Device for later use in call to io:format
%%-----------------------------------------------------------------
! open_log_file(standard_io) -> standard_io;
! open_log_file(FileName) ->
case file:open(FileName, write) of
{ok, Fd} -> Fd;
Error ->
! io:format("rb: Cannot open file '~s' (~w).~n",
[FileName, Error]),
! io:format("rb: Using standard_io~n"),
standard_io
end.
close_device(Fd) when pid(Fd) ->
catch file:close(Fd);
***************
*** 263,290 ****
exit("cannot locate report directory")
end
end.
%%-----------------------------------------------------------------
! %% Func: scan_files(RptDir, Max, Type, Leader)
%% Args: RptDir ::= string().
%% Max ::= integer() | all, describing how many reports
%5 to read.
%% Type ::= atom(), describing which reports to read.
- %% Leader ::= pid(), the group_leader to send io to
%% Purpose: Scan all report files one time, and build a list of
%% small elements
%% Returns: Data, where Data is a list of
%% {Number, Type, ShortDescr, Date, Fname, FilePosition}.
%%-----------------------------------------------------------------
! scan_files(RptDir, Max, Type, Leader) ->
case file:open(RptDir ++ "/index", [raw, read]) of
{ok, Fd} ->
case catch file:read(Fd, 1) of
{ok, [LastWritten]} ->
Files = make_file_list(RptDir, LastWritten),
! scan_files(RptDir, Files, Max, Type, Leader);
_ -> exit("cannot read the index file")
end;
_ -> exit("cannot read the index file")
end.
--- 234,260 ----
exit("cannot locate report directory")
end
end.
%%-----------------------------------------------------------------
! %% Func: scan_files(RptDir, Max, Type)
%% Args: RptDir ::= string().
%% Max ::= integer() | all, describing how many reports
%5 to read.
%% Type ::= atom(), describing which reports to read.
%% Purpose: Scan all report files one time, and build a list of
%% small elements
%% Returns: Data, where Data is a list of
%% {Number, Type, ShortDescr, Date, Fname, FilePosition}.
%%-----------------------------------------------------------------
! scan_files(RptDir, Max, Type) ->
case file:open(RptDir ++ "/index", [raw, read]) of
{ok, Fd} ->
case catch file:read(Fd, 1) of
{ok, [LastWritten]} ->
Files = make_file_list(RptDir, LastWritten),
! scan_files(RptDir, Files, Max, Type);
_ -> exit("cannot read the index file")
end;
_ -> exit("cannot read the index file")
end.
***************
*** 318,387 ****
%% Func: scan_files(Dir, Files, Max, Type)
%% Args: Files is a list of FileName.
%% Purpose: Scan the report files in the index variable.
%% Returns: {Number, Type, ShortDescr, Date, FileName, FilePosition}
%%-----------------------------------------------------------------
! scan_files(Dir, Files, Max, Type, Leader) ->
! scan_files(Dir, 1, Files, [], Max, Type, Leader).
! scan_files(Dir, _, [], Res, Max, Type, Leader) -> Res;
! scan_files(Dir, _, Files, Res, Max, Type, Leader) when Max =< 0 -> Res;
! scan_files(Dir, No, [H|T], Res, Max, Type, Leader) ->
! Data = get_report_data_from_file(Dir, No, H, Max, Type, Leader),
Len = length(Data),
NewMax = dec_max(Max, Len),
NewNo = No + Len,
NewData = Data ++ Res,
! scan_files(Dir, NewNo, T, NewData, NewMax, Type, Leader).
dec_max(all, _) -> all;
dec_max(X,Y) -> X-Y.
! get_report_data_from_file(Dir, No, FileNr, Max, Type, Leader) ->
Fname = integer_to_list(FileNr),
FileName = lists:concat([Dir, Fname]),
case file:open(FileName, read) of
! {ok, Fd} when pid(Fd) -> read_reports(No, Fd, Fname, Max, Type, Leader);
_ -> [{No, unknown, "Can't open file " ++ Fname, "???", Fname, 0}]
end.
%%-----------------------------------------------------------------
! %% Func: read_reports(No, Fd, Fname, Max, Type, Leader)
%% Purpose: Read reports from one report file.
%% Returns: A list of {No, Type, ShortDescr, Date, FileName, FilePosition}
%% Note: We have to read all reports, and then check the max-
%% variable, because the reports are reversed on the file, and
%% we may need the last ones.
%%-----------------------------------------------------------------
! read_reports(No, Fd, Fname, Max, Type, Leader) ->
! io:format(Leader, "rb: reading report...", []),
case catch read_reports(Fd, [], Type) of
{ok, Res} ->
file:close(Fd),
! io:format(Leader, "done.~n", []),
NewRes =
if
length(Res) > Max ->
lists:sublist(Res, 1, Max);
true ->
Res
end,
add_report_data(NewRes, No, Fname);
{error, [Problem | Res]} ->
file:close(Fd),
! io:format(Leader, "Error: ~p~n",[Problem]),
! io:format(Leader, "Salvaged ~p entries from corrupt report file ~s...~n",
[length(Res),Fname]),
NewRes =
if
length([Problem|Res]) > Max ->
lists:sublist([Problem|Res], 1, Max);
true ->
[Problem|Res]
end,
add_report_data(NewRes, No, Fname);
Else ->
! io:format(Leader, "err ~p~n", [Else]),
[{No, unknown, "Can't read reports from file " ++ Fname,
"???", Fname, 0}]
end.
%%-----------------------------------------------------------------
--- 288,357 ----
%% Func: scan_files(Dir, Files, Max, Type)
%% Args: Files is a list of FileName.
%% Purpose: Scan the report files in the index variable.
%% Returns: {Number, Type, ShortDescr, Date, FileName, FilePosition}
%%-----------------------------------------------------------------
! scan_files(Dir, Files, Max, Type) ->
! scan_files(Dir, 1, Files, [], Max, Type).
! scan_files(Dir, _, [], Res, Max, Type) -> Res;
! scan_files(Dir, _, Files, Res, Max, Type) when Max =< 0 -> Res;
! scan_files(Dir, No, [H|T], Res, Max, Type) ->
! Data = get_report_data_from_file(Dir, No, H, Max, Type),
Len = length(Data),
NewMax = dec_max(Max, Len),
NewNo = No + Len,
NewData = Data ++ Res,
! scan_files(Dir, NewNo, T, NewData, NewMax, Type).
dec_max(all, _) -> all;
dec_max(X,Y) -> X-Y.
! get_report_data_from_file(Dir, No, FileNr, Max, Type) ->
Fname = integer_to_list(FileNr),
FileName = lists:concat([Dir, Fname]),
case file:open(FileName, read) of
! {ok, Fd} when pid(Fd) -> read_reports(No, Fd, Fname, Max, Type);
_ -> [{No, unknown, "Can't open file " ++ Fname, "???", Fname, 0}]
end.
%%-----------------------------------------------------------------
! %% Func: read_reports(No, Fd, Fname, Max, Type)
%% Purpose: Read reports from one report file.
%% Returns: A list of {No, Type, ShortDescr, Date, FileName, FilePosition}
%% Note: We have to read all reports, and then check the max-
%% variable, because the reports are reversed on the file, and
%% we may need the last ones.
%%-----------------------------------------------------------------
! read_reports(No, Fd, Fname, Max, Type) ->
! io:format("rb: reading report..."),
case catch read_reports(Fd, [], Type) of
{ok, Res} ->
file:close(Fd),
! io:format("done.~n"),
NewRes =
if
length(Res) > Max ->
lists:sublist(Res, 1, Max);
true ->
Res
end,
add_report_data(NewRes, No, Fname);
{error, [Problem | Res]} ->
file:close(Fd),
! io:format("Error: ~p~n",[Problem]),
! io:format("Salvaged ~p entries from corrupt report file ~s...~n",
[length(Res),Fname]),
NewRes =
if
length([Problem|Res]) > Max ->
lists:sublist([Problem|Res], 1, Max);
true ->
[Problem|Res]
end,
add_report_data(NewRes, No, Fname);
Else ->
! io:format("err ~p~n", [Else]),
[{No, unknown, "Can't read reports from file " ++ Fname,
"???", Fname, 0}]
end.
%%-----------------------------------------------------------------
***************
*** 509,530 ****
end.
! print_list(Data, Type, Leader) ->
Header = {"No", "Type", "Process", "Date Time"},
Width = find_width([Header | Data], 0)+1,
DateWidth = find_date_width([Header | Data], 0) +1,
Format = lists:concat(["~4s~20s ~", Width, "s~20s~n"]),
! io:format(Leader, Format, tuple_to_list(Header)),
! io:format(Leader, Format, ["==", "====", "=======", "==== ===="]),
! print_list(Data, Type, Width, DateWidth, Leader).
! print_list([], _, _, _, _) -> true;
! print_list([H|T], Type, Width, DateWidth, Leader) ->
! print_one_report(H, Type, Width, DateWidth, Leader),
! print_list(T, Type, Width, DateWidth, Leader).
find_width([], Width) -> Width;
find_width([H|T], Width) ->
Try = length(element(3, H)),
if
--- 479,500 ----
end.
! print_list(Data, Type) ->
Header = {"No", "Type", "Process", "Date Time"},
Width = find_width([Header | Data], 0)+1,
DateWidth = find_date_width([Header | Data], 0) +1,
Format = lists:concat(["~4s~20s ~", Width, "s~20s~n"]),
! io:format(Format, tuple_to_list(Header)),
! io:format(Format, ["==", "====", "=======", "==== ===="]),
! print_list(Data, Type, Width, DateWidth).
! print_list([], _, _, _) -> true;
! print_list([H|T], Type, Width, DateWidth) ->
! print_one_report(H, Type, Width, DateWidth),
! print_list(T, Type, Width, DateWidth).
find_width([], Width) -> Width;
find_width([H|T], Width) ->
Try = length(element(3, H)),
if
***************
*** 539,643 ****
true -> find_date_width(T, Width)
end.
print_one_report({No, RealType, ShortDescr, Date, Fname, FilePosition},
WantedType,
! Width, DateWidth, Leader) ->
if
WantedType == all ->
print_short_descr(No, RealType, ShortDescr, Date, Width,
! DateWidth, Leader);
WantedType == RealType ->
print_short_descr(No, RealType, ShortDescr, Date, Width,
! DateWidth, Leader);
true -> ok
end.
! print_short_descr(No, Type, ShortDescr, Date, Width, DateWidth, Leader) ->
Format = lists:concat(["~4w~20w ~", Width, "s~", DateWidth,"s~n"]),
! io:format(Leader, Format, [No,
Type,
io_lib:format("~s", [ShortDescr]),
Date]).
! print_typed_reports(Dir, [], _Type, _Device, _Leader) ->
ok;
! print_typed_reports(Dir, Data, Type, Device, Leader) ->
case element(2, hd(Data)) of
! Type -> print_report(Dir, Data, element(1, hd(Data)), Device, Leader);
_ -> ok
end,
! print_typed_reports(Dir, tl(Data), Type, Device, Leader).
! print_all_reports(Dir, [], _Device, _Leader) ->
ok;
! print_all_reports(Dir, Data, Device, Leader) ->
! print_report(Dir, Data, element(1, hd(Data)), Device, Leader),
! print_all_reports(Dir, tl(Data), Device, Leader).
! print_report(Dir, Data, Number, Device, Leader) ->
{Fname, FilePosition, Type} = find_report(Data, Number),
FileName = lists:concat([Dir, Fname]),
case file:open(FileName, read) of
! {ok, Fd} -> read_rep(Fd, FilePosition, Type, Device, Leader);
! _ -> io:format(Leader, "rb: can't open file ~p~n", [Fname])
end.
find_report([{No, Type, ShortDescr, Date, Fname, FilePosition}|T], No) ->
{Fname, FilePosition, Type};
find_report([H|T], No) -> find_report(T, No);
find_report([], No) ->
io:format("There is no report with number ~p.~n", [No]).
! print_grep_reports(_Dir, [], _RegExp, _Device, _Leader) ->
ok;
! print_grep_reports(Dir, Data, RegExp, Device, Leader) ->
! print_grep_report(Dir, Data, element(1, hd(Data)), Device, Leader, RegExp),
! print_grep_reports(Dir, tl(Data), RegExp, Device, Leader).
! print_grep_report(Dir, Data, Number, Device, Leader, RegExp) ->
{Fname, FilePosition, Type} = find_report(Data, Number),
FileName = lists:concat([Dir, Fname]),
case file:open(FileName, read) of
{ok, Fd} when pid(Fd) ->
! check_rep(Fd, FilePosition, Type, Device, Leader, RegExp, Number);
_ ->
! io:format(Leader, "rb: can't open file ~p~n", [Fname])
end.
! check_rep(Fd, FilePosition, Type, Device, Leader, RegExp, Number) ->
case read_rep_msg(Fd, FilePosition, Type) of
{Date, Msg} ->
MsgStr = lists:flatten(io_lib:format("~p",[Msg])),
case regexp:match(MsgStr, RegExp) of
! {match, _, _} ->
! io:format(Leader, "Found match in report number ~w~n", [Number]),
! case Device of
! standard_io -> rb_format_supp:print(Date, Msg, Leader);
! _ -> rb_format_supp:print(Date, Msg, Device)
! end;
! _ -> false
end;
_ ->
! io:format(Leader, "rb: Cannot read from file~n", [])
end.
! read_rep(Fd, FilePosition, Type, Device, Leader) ->
case read_rep_msg(Fd, FilePosition, Type) of
{Date, Msg} ->
! Log = case Device of
! standard_io -> Leader;
! _ ->Device
! end,
! case catch rb_format_supp:print(Date, Msg, Log) of
{'EXIT', _} ->
io:format(Device, "ERROR: ~p ~p~n", [Date, Msg]);
_ ->
ok
end;
_ ->
! io:format(Leader, "rb: Cannot read from file~n", [])
end.
read_rep_msg(Fd, FilePosition, Type) ->
file:position(Fd, {bof, FilePosition}),
Res =
--- 509,606 ----
true -> find_date_width(T, Width)
end.
print_one_report({No, RealType, ShortDescr, Date, Fname, FilePosition},
WantedType,
! Width, DateWidth) ->
if
WantedType == all ->
print_short_descr(No, RealType, ShortDescr, Date, Width,
! DateWidth);
WantedType == RealType ->
print_short_descr(No, RealType, ShortDescr, Date, Width,
! DateWidth);
true -> ok
end.
! print_short_descr(No, Type, ShortDescr, Date, Width, DateWidth) ->
Format = lists:concat(["~4w~20w ~", Width, "s~", DateWidth,"s~n"]),
! io:format(Format, [No,
Type,
io_lib:format("~s", [ShortDescr]),
Date]).
! print_typed_reports(Dir, [], Type, Device) ->
ok;
! print_typed_reports(Dir, Data, Type, Device) ->
case element(2, hd(Data)) of
! Type -> print_report(Dir, Data, element(1, hd(Data)), Device);
_ -> ok
end,
! print_typed_reports(Dir, tl(Data), Type, Device).
! print_all_reports(Dir, [], Device) ->
ok;
! print_all_reports(Dir, Data, Device) ->
! print_report(Dir, Data, element(1, hd(Data)), Device),
! print_all_reports(Dir, tl(Data), Device).
! print_report(Dir, Data, Number, Device) ->
{Fname, FilePosition, Type} = find_report(Data, Number),
FileName = lists:concat([Dir, Fname]),
case file:open(FileName, read) of
! {ok, Fd} -> read_rep(Fd, FilePosition, Type, Device);
! _ -> io:format("rb: can't open file ~p~n", [Fname])
end.
find_report([{No, Type, ShortDescr, Date, Fname, FilePosition}|T], No) ->
{Fname, FilePosition, Type};
find_report([H|T], No) -> find_report(T, No);
find_report([], No) ->
io:format("There is no report with number ~p.~n", [No]).
! print_grep_reports(Dir, [], RegExp, Device) ->
ok;
! print_grep_reports(Dir, Data, RegExp, Device) ->
! print_grep_report(Dir, Data, element(1, hd(Data)), Device, RegExp),
! print_grep_reports(Dir, tl(Data), RegExp, Device).
! print_grep_report(Dir, Data, Number, Device, RegExp) ->
{Fname, FilePosition, Type} = find_report(Data, Number),
FileName = lists:concat([Dir, Fname]),
case file:open(FileName, read) of
{ok, Fd} when pid(Fd) ->
! check_rep(Fd, FilePosition, Type, Device, RegExp, Number);
_ ->
! io:format("rb: can't open file ~p~n", [Fname])
end.
! check_rep(Fd, FilePosition, Type, Device, RegExp, Number) ->
case read_rep_msg(Fd, FilePosition, Type) of
{Date, Msg} ->
MsgStr = lists:flatten(io_lib:format("~p",[Msg])),
case regexp:match(MsgStr, RegExp) of
! {match, _, _} ->
! io:format("Found match in report number ~w~n", [Number]),
! rb_format_supp:print(Date, Msg, Device);
! _ -> false
end;
_ ->
! io:format("rb: Cannot read from file~n")
end.
! read_rep(Fd, FilePosition, Type, Device) ->
case read_rep_msg(Fd, FilePosition, Type) of
{Date, Msg} ->
! case catch rb_format_supp:print(Date, Msg, Device) of
{'EXIT', _} ->
io:format(Device, "ERROR: ~p ~p~n", [Date, Msg]);
_ ->
ok
end;
_ ->
! io:format("rb: Cannot read from file~n")
end.
read_rep_msg(Fd, FilePosition, Type) ->
file:position(Fd, {bof, FilePosition}),
Res =
More information about the erlang-patches
mailing list