diff options
Diffstat (limited to 'lib/kernel/src/disk_log.erl')
-rw-r--r-- | lib/kernel/src/disk_log.erl | 168 |
1 files changed, 78 insertions, 90 deletions
diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 5b1efcd395..9b44021872 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1,18 +1,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% Copyright Ericsson AB 1997-2015. 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. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% @@ -44,6 +45,8 @@ %% To be used for debugging only: -export([pid2name/1]). +-export_type([continuation/0]). + -type dlog_state_error() :: 'ok' | {'error', term()}. -record(state, {queue = [], @@ -1074,13 +1077,13 @@ log_end(S, [], [], Sync) -> log_end(S, Pids, Bins, Sync) -> case do_log(get(log), rflat(Bins)) of N when is_integer(N) -> - replies(Pids, ok), + ok = replies(Pids, ok), S1 = (state_ok(S))#state{cnt = S#state.cnt+N}, log_end_sync(S1, Sync); {error, {error, {full, _Name}}, N} when Pids =:= [] -> log_end_sync(state_ok(S#state{cnt = S#state.cnt + N}), Sync); {error, Error, N} -> - replies(Pids, Error), + ok = replies(Pids, Error), state_err(S#state{cnt = S#state.cnt + N}, Error) end. @@ -1089,7 +1092,7 @@ log_end_sync(S, []) -> S; log_end_sync(S, Sync) -> Res = do_sync(get(log)), - replies(Sync, Res), + ok = replies(Sync, Res), state_err(S, Res). %% Inlined. @@ -1181,7 +1184,7 @@ do_exit(S, From, Message0, Reason) -> _ -> Message0 end, _ = disk_log_server:close(self()), - replies(From, Message), + ok = replies(From, Message), ?PROFILE(ep:done()), exit(Reason). @@ -1307,13 +1310,20 @@ compare_arg(_Attr, _Val, _A) -> %% -> {ok, Res, log(), Cnt} | Error do_open(A) -> - L = #log{name = A#arg.name, - filename = A#arg.file, - size = A#arg.size, - head = mk_head(A#arg.head, A#arg.format), - mode = A#arg.mode, - version = A#arg.version}, - do_open2(L, A). + #arg{type = Type, format = Format, name = Name, head = Head0, + file = FName, repair = Repair, size = Size, mode = Mode, + version = V} = A, + Head = mk_head(Head0, Format), + case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of + {ok, Ret, Extra, FormatType, NoItems} -> + L = #log{name = Name, type = Type, format = Format, + filename = FName, size = Size, + format_type = FormatType, head = Head, mode = Mode, + version = V, extra = Extra}, + {ok, Ret, L, NoItems}; + Error -> + Error + end. mk_head({head, Term}, internal) -> {ok, term_to_binary(Term)}; mk_head({head, Bytes}, external) -> {ok, check_bytes(Bytes)}; @@ -1429,57 +1439,44 @@ do_inc_wrap_file(L) -> %%----------------------------------------------------------------- %% -> {ok, Reply, log(), Cnt} | Error %% Note: the header is always written, even if the log size is too small. -do_open2(L, #arg{type = halt, format = internal, name = Name, - file = FName, repair = Repair, size = Size, mode = Mode}) -> - case catch disk_log_1:int_open(FName, Repair, Mode, L#log.head) of +do_open2(halt, internal, Name, FName, Repair, Size, Mode, Head, _V) -> + case catch disk_log_1:int_open(FName, Repair, Mode, Head) of {ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, - {ok, {ok, Name}, L#log{format_type = halt_int, extra = Halt}, - NoItems}; + {ok, {ok, Name}, Halt, halt_int, NoItems}; {repaired, FdC, Rec, Bad, FileSize} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, {ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}}, - L#log{format_type = halt_int, extra = Halt}, - Rec}; + Halt, halt_int, Rec}; Error -> Error end; -do_open2(L, #arg{type = wrap, format = internal, size = {MaxB, MaxF}, - name = Name, repair = Repair, file = FName, mode = Mode, - version = V}) -> +do_open2(wrap, internal, Name, FName, Repair, Size, Mode, Head, V) -> + {MaxB, MaxF} = Size, case catch - disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of + disk_log_1:mf_int_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of {ok, Handle, Cnt} -> - {ok, {ok, Name}, L#log{type = wrap, - format_type = wrap_int, - extra = Handle}, Cnt}; + {ok, {ok, Name}, Handle, wrap_int, Cnt}; {repaired, Handle, Rec, Bad, Cnt} -> {ok, {repaired, Name, {recovered, Rec}, {badbytes, Bad}}, - L#log{type = wrap, format_type = wrap_int, extra = Handle}, Cnt}; + Handle, wrap_int, Cnt}; Error -> Error end; -do_open2(L, #arg{type = halt, format = external, file = FName, name = Name, - size = Size, repair = Repair, mode = Mode}) -> - case catch disk_log_1:ext_open(FName, Repair, Mode, L#log.head) of +do_open2(halt, external, Name, FName, Repair, Size, Mode, Head, _V) -> + case catch disk_log_1:ext_open(FName, Repair, Mode, Head) of {ok, {_Alloc, FdC, {NoItems, _NoBytes}, FileSize}} -> Halt = #halt{fdc = FdC, curB = FileSize, size = Size}, - {ok, {ok, Name}, - L#log{format_type = halt_ext, format = external, extra = Halt}, - NoItems}; + {ok, {ok, Name}, Halt, halt_ext, NoItems}; Error -> Error end; -do_open2(L, #arg{type = wrap, format = external, size = {MaxB, MaxF}, - name = Name, file = FName, repair = Repair, mode = Mode, - version = V}) -> +do_open2(wrap, external, Name, FName, Repair, Size, Mode, Head, V) -> + {MaxB, MaxF} = Size, case catch - disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, L#log.head, V) of + disk_log_1:mf_ext_open(FName, MaxB, MaxF, Repair, Mode, Head, V) of {ok, Handle, Cnt} -> - {ok, {ok, Name}, L#log{type = wrap, - format_type = wrap_ext, - extra = Handle, - format = external}, Cnt}; + {ok, {ok, Name}, Handle, wrap_ext, Cnt}; Error -> Error end. @@ -1525,48 +1522,48 @@ do_format_error({size_mismatch, OldSize, ArgSize}) -> io_lib:format("The given size ~p does not match the size ~p found on " "the disk log size file~n", [ArgSize, OldSize]); do_format_error({read_only_mode, Log}) -> - io_lib:format("The disk log ~p has been opened read-only, but the " + io_lib:format("The disk log ~tp has been opened read-only, but the " "requested operation needs read-write access~n", [Log]); do_format_error({format_external, Log}) -> io_lib:format("The requested operation can only be applied on internally " - "formatted disk logs, but ~p is externally formatted~n", + "formatted disk logs, but ~tp is externally formatted~n", [Log]); do_format_error({blocked_log, Log}) -> - io_lib:format("The blocked disk log ~p does not queue requests, or " + io_lib:format("The blocked disk log ~tp does not queue requests, or " "the log has been blocked by the calling process~n", [Log]); do_format_error({full, Log}) -> - io_lib:format("The halt log ~p is full~n", [Log]); + io_lib:format("The halt log ~tp is full~n", [Log]); do_format_error({not_blocked, Log}) -> - io_lib:format("The disk log ~p is not blocked~n", [Log]); + io_lib:format("The disk log ~tp is not blocked~n", [Log]); do_format_error({not_owner, Pid}) -> - io_lib:format("The pid ~p is not an owner of the disk log~n", [Pid]); + io_lib:format("The pid ~tp is not an owner of the disk log~n", [Pid]); do_format_error({not_blocked_by_pid, Log}) -> - io_lib:format("The disk log ~p is blocked, but only the blocking pid " + io_lib:format("The disk log ~tp is blocked, but only the blocking pid " "can unblock a disk log~n", [Log]); do_format_error({new_size_too_small, Log, CurrentSize}) -> - io_lib:format("The current size ~p of the halt log ~p is greater than the " + io_lib:format("The current size ~p of the halt log ~tp is greater than the " "requested new size~n", [CurrentSize, Log]); do_format_error({halt_log, Log}) -> - io_lib:format("The halt log ~p cannot be wrapped~n", [Log]); + io_lib:format("The halt log ~tp cannot be wrapped~n", [Log]); do_format_error({same_file_name, Log}) -> - io_lib:format("Current and new file name of the disk log ~p " + io_lib:format("Current and new file name of the disk log ~tp " "are the same~n", [Log]); do_format_error({arg_mismatch, Option, FirstValue, ArgValue}) -> - io_lib:format("The value ~p of the disk log option ~p does not match " - "the current value ~p~n", [ArgValue, Option, FirstValue]); + io_lib:format("The value ~tp of the disk log option ~p does not match " + "the current value ~tp~n", [ArgValue, Option, FirstValue]); do_format_error({name_already_open, Log}) -> - io_lib:format("The disk log ~p has already opened another file~n", [Log]); + io_lib:format("The disk log ~tp has already opened another file~n", [Log]); do_format_error({node_already_open, Log}) -> - io_lib:format("The distribution option of the disk log ~p does not match " + io_lib:format("The distribution option of the disk log ~tp does not match " "already open log~n", [Log]); do_format_error({open_read_write, Log}) -> - io_lib:format("The disk log ~p has already been opened read-write~n", + io_lib:format("The disk log ~tp has already been opened read-write~n", [Log]); do_format_error({open_read_only, Log}) -> - io_lib:format("The disk log ~p has already been opened read-only~n", + io_lib:format("The disk log ~tp has already been opened read-only~n", [Log]); do_format_error({not_internal_wrap, Log}) -> - io_lib:format("The requested operation cannot be applied since ~p is not " + io_lib:format("The requested operation cannot be applied since ~tp is not " "an internally formatted disk log~n", [Log]); do_format_error(no_such_log) -> io_lib:format("There is no disk log with the given name~n", []); @@ -1577,13 +1574,13 @@ do_format_error(nodedown) -> io_lib:format("There seems to be no node up that can handle " "the request~n", []); do_format_error({corrupt_log_file, FileName}) -> - io_lib:format("The disk log file \"~s\" contains corrupt data~n", + io_lib:format("The disk log file \"~ts\" contains corrupt data~n", [FileName]); do_format_error({need_repair, FileName}) -> - io_lib:format("The disk log file \"~s\" has not been closed properly and " + io_lib:format("The disk log file \"~ts\" has not been closed properly and " "needs repair~n", [FileName]); do_format_error({not_a_log_file, FileName}) -> - io_lib:format("The file \"~s\" is not a wrap log file~n", [FileName]); + io_lib:format("The file \"~ts\" is not a wrap log file~n", [FileName]); do_format_error({invalid_header, InvalidHeader}) -> io_lib:format("The disk log header is not wellformed: ~p~n", [InvalidHeader]); @@ -1591,14 +1588,14 @@ do_format_error(end_of_log) -> io_lib:format("An attempt was made to step outside a not yet " "full wrap log~n", []); do_format_error({invalid_index_file, FileName}) -> - io_lib:format("The wrap log index file \"~s\" cannot be used~n", + io_lib:format("The wrap log index file \"~ts\" cannot be used~n", [FileName]); do_format_error({no_continuation, BadCont}) -> io_lib:format("The term ~p is not a chunk continuation~n", [BadCont]); do_format_error({file_error, FileName, Reason}) -> - io_lib:format("\"~s\": ~p~n", [FileName, file:format_error(Reason)]); + io_lib:format("\"~ts\": ~tp~n", [FileName, file:format_error(Reason)]); do_format_error(E) -> - io_lib:format("~p~n", [E]). + io_lib:format("~tp~n", [E]). do_info(L, Cnt) -> #log{name = Name, type = Type, mode = Mode, filename = File, @@ -1879,7 +1876,8 @@ replies(Pids, Reply) -> send_reply(Pids, M). send_reply(Pid, M) when is_pid(Pid) -> - Pid ! M; + Pid ! M, + ok; send_reply([Pid | Pids], M) -> Pid ! M, send_reply(Pids, M); @@ -1912,13 +1910,8 @@ multi_req(Msg, Pids) -> {'DOWN', Ref, process, Pid, _Info} -> Reply; {disk_log, Pid, _Reply} -> - erlang:demonitor(Ref), - receive - {'DOWN', Ref, process, Pid, _Reason} -> - ok - after 0 -> - ok - end + erlang:demonitor(Ref, [flush]), + ok end end, {error, nonode}, Refs). @@ -1963,13 +1956,8 @@ monitor_request(Pid, Req) -> {error, no_such_log}; {disk_log, Pid, Reply} when not is_tuple(Reply) orelse element(2, Reply) =/= disk_log_stopped -> - erlang:demonitor(Ref), - receive - {'DOWN', Ref, process, Pid, _Reason} -> - Reply - after 0 -> - Reply - end + erlang:demonitor(Ref, [flush]), + Reply end. req2(Pid, R) -> @@ -2030,7 +2018,7 @@ notify_owners(Note) -> cache_error(S, Pids) -> Error = S#state.cache_error, - replies(Pids, Error), + ok = replies(Pids, Error), state_err(S#state{cache_error = ok}, Error). state_ok(S) -> |