diff options
Diffstat (limited to 'lib/cosTransactions/src/etrap_logmgr.erl')
-rw-r--r-- | lib/cosTransactions/src/etrap_logmgr.erl | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/lib/cosTransactions/src/etrap_logmgr.erl b/lib/cosTransactions/src/etrap_logmgr.erl new file mode 100644 index 0000000000..a418d782e3 --- /dev/null +++ b/lib/cosTransactions/src/etrap_logmgr.erl @@ -0,0 +1,200 @@ +%%-------------------------------------------------------------------- +%% +%% %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 ------------------------------ |