%%-------------------------------------------------------------------- %% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1999-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% %% %% %%---------------------------------------------------------------------- %% File : etrap_logmgr.erl %% Purpose : Make it easier to use disk_log. %%---------------------------------------------------------------------- -module(etrap_logmgr). %%--------------- INCLUDES ----------------------------------- %% Local -include_lib("ETraP_Common.hrl"). %%--------------- IMPORTS------------------------------------- %%--------------- EXPORTS------------------------------------- -export([start/1, stop/1, log_safe/2, log_lazy/2, get_next/2]). %%------------------------------------------------------------ %% function : start %% Arguments: LogName - name of the disk_log. %% Returns : %% Effect : creating linked log %%------------------------------------------------------------ start(LogName) -> case catch disk_log:open([{name, LogName}, {file, LogName}, {type, halt}, {size, infinity}]) of {ok, LogName} -> ok; {error, Reason} -> ?tr_error_msg("Initiating internal log failed: ~p", [Reason]), exit({error, Reason}); {repaired, LogName, {recovered, _Rec}, {badbytes, _Bad}} -> ok; Other -> ?tr_error_msg("Initiating internal log failed: ~p", [Other]), exit({error, Other}) end. %%------------------------------------------------------------ %% function : stop %% Arguments: LogName - name of the disk_log. %% Returns : %% Effect : %%------------------------------------------------------------ stop(LogName) -> case catch disk_log:close(LogName) of ok -> ok; {error, Reason} -> ?tr_error_msg("Stopping internal log failed: ~p", [Reason]), {error, Reason}; Other -> ?tr_error_msg("Stopping internal log failed: ~p", [Other]), {error, Other} end. %%------------------------------------------------------------ %% function : log_safe %% Arguments: LogName - name of the disk_log. If 'dummy' is %% used nothing should be logged. Reason, reuse code. %% LogRecord - record to store in the log. %% Returns : %% Effect : Writes a logrecord and synchronizes to make sure %% that the record is stored. %%------------------------------------------------------------ log_safe(dummy, _) -> ok; log_safe(LogName, LogRecord) -> case write_safe(LogName, LogRecord) of ok -> ok; _ -> %% We have to catch the exit because in some cases %% it's not possible to abort action in the 2PC-protocol. case catch start(LogName) of ok -> write_safe(LogName, LogRecord); {'EXIT', Reason} -> {error, Reason} end end. write_safe(LogName, LogRecord) -> case catch disk_log:log(LogName, LogRecord) of ok -> % wrote to kernel successfully case catch disk_log:sync(LogName) of ok -> % Written to disk successfully ok; {error, Reason} -> ?tr_error_msg("Internal log write failed: ~p ~p", [Reason, LogName]), {error, Reason}; Other -> ?tr_error_msg("Internal log write failed: ~p ~p", [Other, LogName]), {error, Other} end; {error, Reason} -> ?tr_error_msg("Internal log write failed: ~p ~p", [Reason, LogName]), {error, Reason}; Other -> ?tr_error_msg("Internal log write failed: ~p ~p", [Other, LogName]), {error, Other} end. %%------------------------------------------------------------ %% function : log_lazy %% Arguments: LogName - name of the disk_log. If 'dummy' is %% used nothing should be logged. Reason, reuse code. %% LogRecord - record to store in the log. %% Returns : %% Effect : Writes a logrecord. The record may be lost. %%------------------------------------------------------------ log_lazy(dummy, _LogRecord) -> ok; log_lazy(LogName, LogRecord) -> case write_lazy(LogName, LogRecord) of ok -> ok; _ -> %% We have to catch the exit because in some cases %% it's not possible to abort action in the 2PC-protocol. case catch start(LogName) of ok -> write_lazy(LogName, LogRecord); {'EXIT', Reason} -> {error, Reason} end end. write_lazy(LogName, LogRecord) -> case catch disk_log:log(LogName, LogRecord) of ok -> %% wrote to kernel successfully ok; {error, Reason} -> %% Write to kernel failed with Reason ?tr_error_msg("Internal log write failed: ~p", [Reason]), {error, Reason}; Other -> %% unknown message received. ?tr_error_msg("Internal log write failed: ~p", [Other]), {error, Other} end. %%------------------------------------------------------------ %% function : get_next %% Arguments: LogName - name of the disk_log. %% Cursor - place to read from. %% Returns : {Cursor, LogRecs} - A cursor and up to N logrecords. %% eof - the atom 'eof', indicating logfile empty. %% {error, Reason} - error. %% Effect : %% Purpose : Used when performing a REDO scan %%------------------------------------------------------------ get_next(LogName, Cursor) -> case catch disk_log:chunk(LogName, Cursor, 1) of {NewCursor, [Data]} -> {Data, NewCursor}; eof -> eof; {error, Reason} -> ?tr_error_msg("Internal log '~p' read failed: ~p", [LogName, Reason]), exit({error, Reason}); _Other -> ?tr_error_msg("Internal log '~p' read failed: 'log_corrupt'", [LogName]), exit({error, "log_corrupt"}) end. %%--------------- END OF MODULE ------------------------------