Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
3381-kernel-Let-option-size-of-disk_log-open-1-...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3381-kernel-Let-option-size-of-disk_log-open-1-change-siz.patch of Package erlang
From 3e1b56171949dd6212d488d1cdbce2c935dda1fd Mon Sep 17 00:00:00 2001 From: Hans Bolinder <hasse@erlang.org> Date: Mon, 22 Feb 2021 10:35:20 +0100 Subject: [PATCH 1/2] kernel: Let option 'size' of disk_log:open/1 change size If the value of option 'size' does not match existing wrap log size, the 'size_mismatch' error is no longer returned, but the size of the log changed. This applies only if the disk log is not already open. We have made this incompatible modification to help customers handle upgrade scenarios. See also ERL-1418, GH-4469 and ERIERL-537. --- lib/kernel/doc/src/disk_log.xml | 23 ++++- lib/kernel/src/disk_log.erl | 44 +++++++--- lib/kernel/src/disk_log.hrl | 1 + lib/kernel/test/disk_log_SUITE.erl | 136 ++++++++++++++++++++++++++--- 4 files changed, 179 insertions(+), 25 deletions(-) diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index d8f5ee35dd..b6c4f2afa7 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -817,11 +817,28 @@ at least the header (if there is one) and one item are written on each wrap log file before wrapping to the next file.</p> + <p>The first time an existing wrap log is opened, that is, + when the disk log process is created, the value of the + option <c>size</c> is allowed to differ from the current + log size, and the size of the disk log is changed as per + <seemfa + marker="#change_size/2"><c>change_size/2</c></seemfa>. + </p> <p>When opening an existing wrap log, it is not - necessary to supply a value for option <c>Size</c>, but any - supplied value must equal the current log size, otherwise + necessary to supply a value for option <c>size</c>, + but if the log is already open, that is, the disk log + process exists, + the supplied value must equal the current log size, otherwise the tuple <c>{error, {size_mismatch, <anno>CurrentSize</anno>, - <anno>NewSize</anno>}}</c> is returned.</p> + <anno>NewSize</anno>}}</c> is returned.</p> + <note> + <p>Before Erlang/OTP 24.0, the supplied value of option + <c>size</c> was to be equal to the current log size when + opening an existing wrap log for the first time, that + is, when creating the disk log process.</p> + </note> + <p>When opening an already open halt log, option <c>size</c> + is ignored.</p> </item> <tag><c>{notify, boolean()}</c><marker id="notify"></marker></tag> <item> diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index 89a9bd2f51..bdbf877fab 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -648,17 +648,19 @@ check_arg(Arg, _) -> check_wrap_arg({ok, Res}, {0,0}, _Version) when Res#arg.size =:= infinity -> {error, {badarg, size}}; check_wrap_arg({ok, Res}, OldSize, Version) when Res#arg.size =:= infinity -> - NewRes = Res#arg{size = OldSize}, - check_wrap_arg({ok, NewRes}, OldSize, Version); + {ok, Res#arg{version = Version, old_size = OldSize, size = OldSize}}; check_wrap_arg({ok, Res}, {0,0}, Version) -> - {ok, Res#arg{version = Version}}; + {ok, Res#arg{version = Version, old_size = Res#arg.size}}; check_wrap_arg({ok, Res}, OldSize, Version) when OldSize =:= Res#arg.size -> - {ok, Res#arg{version = Version}}; -check_wrap_arg({ok, Res}, _OldSize, Version) when Res#arg.repair =:= truncate, - is_tuple(Res#arg.size) -> - {ok, Res#arg{version = Version}}; -check_wrap_arg({ok, Res}, OldSize, _Version) when is_tuple(Res#arg.size) -> + {ok, Res#arg{version = Version, old_size = OldSize}}; +check_wrap_arg({ok, Res}, OldSize, Version) when Res#arg.repair =:= truncate, + is_tuple(Res#arg.size) -> + {ok, Res#arg{version = Version, old_size = OldSize}}; +check_wrap_arg({ok, Res}, OldSize, _Version) when Res#arg.size =/= OldSize, + Res#arg.mode =:= read_only -> {error, {size_mismatch, OldSize, Res#arg.size}}; +check_wrap_arg({ok, Res}, OldSize, Version) when is_tuple(Res#arg.size) -> + {ok, Res#arg{version = Version, old_size = OldSize}}; check_wrap_arg({ok, _Res}, _OldSize, _Version) -> {error, {badarg, size}}; check_wrap_arg(Ret, _OldSize, _Version) -> @@ -946,7 +948,23 @@ handle({Server, {internal_open, A}}, S) -> case do_open(A) of % does the put {ok, Res, L, Cnt} -> put(log, opening_pid(A#arg.linkto, A#arg.notify, L)), - reply(Server, Res, S#state{args=A, cnt=Cnt}); + #arg{size = Size, old_size = OldSize} = A, + S1 = S#state{args=A, cnt=Cnt}, + case Size =:= OldSize of + true -> + reply(Server, Res, S1); + false -> + case catch do_change_size(get(log), Size) of % does the put + ok -> + reply(Server, Res, S1); + {big, _CurSize} -> + %% Note: halt logs are opened even if the + %% given size is too small. + reply(Server, Res, S1); + Else -> + reply(Server, Else, S1) + end + end; Res -> do_fast_exit(S, Server, Res) end; @@ -1273,6 +1291,10 @@ compare_arg(format, F, A) when F =/= A#arg.format -> compare_arg(repair, R, A) when R =/= A#arg.repair -> %% not used, but check it anyway... {not_ok, A#arg.repair}; +compare_arg(size, Sz, A) when Sz =/= A#arg.size, A#arg.type =:= wrap -> + %% Note: if the given size does not match the size of an open + %% halt log, the given size is ignored. + {error, {size_mismatch, A#arg.size, Sz}}; compare_arg(_Attr, _Val, _A) -> ok. @@ -1280,10 +1302,10 @@ compare_arg(_Attr, _Val, _A) -> do_open(A) -> #arg{type = Type, format = Format, name = Name, head = Head0, file = FName, repair = Repair, size = Size, mode = Mode, - quiet = Quiet, version = V} = A, + quiet = Quiet, version = V, old_size = OldSize} = A, disk_log_1:set_quiet(Quiet), Head = mk_head(Head0, Format), - case do_open2(Type, Format, Name, FName, Repair, Size, Mode, Head, V) of + case do_open2(Type, Format, Name, FName, Repair, OldSize, Mode, Head, V) of {ok, Ret, Extra, FormatType, NoItems} -> L = #log{name = Name, type = Type, format = Format, filename = FName, size = Size, diff --git a/lib/kernel/src/disk_log.hrl b/lib/kernel/src/disk_log.hrl index 3cd124b8a7..2307c6956a 100644 --- a/lib/kernel/src/disk_log.hrl +++ b/lib/kernel/src/disk_log.hrl @@ -95,6 +95,7 @@ file = none :: 'none' | file:filename(), repair = true :: dlog_repair(), size = infinity :: dlog_size(), + old_size = infinity :: dlog_size(), % read from size file type = halt :: dlog_type(), format = internal :: dlog_format(), linkto = self() :: 'none' | pid(), diff --git a/lib/kernel/test/disk_log_SUITE.erl b/lib/kernel/test/disk_log_SUITE.erl index 7cc6372de3..af048374f4 100644 --- a/lib/kernel/test/disk_log_SUITE.erl +++ b/lib/kernel/test/disk_log_SUITE.erl @@ -65,7 +65,8 @@ unblock/1, - open_overwrite/1, open_size/1, open_truncate/1, open_error/1, + open_overwrite/1, open_size/1, open_change_size/1, + open_truncate/1, open_error/1, close_race/1, close_block/1, close_deadlock/1, @@ -117,8 +118,8 @@ [halt_int, wrap_int, halt_ext, wrap_ext, read_mode, head, notif, new_idx_vsn, reopen, block, unblock, open, close, error, chunk, truncate, many_users, info, change_size, - change_attribute, otp_6278, otp_10131, otp_16768, - otp_16809]). + open_change_size, change_attribute, otp_6278, otp_10131, + otp_16768, otp_16809]). %% These tests should be skipped if the VxWorks card is configured *with* %% nfs cache. @@ -159,7 +160,8 @@ groups() -> [wrap_notif, full_notif, trunc_notif, blocked_notif]}, {block, [], [block_blocked, block_queue, block_queue2]}, {open, [], - [open_overwrite, open_size, open_truncate, open_error]}, + [open_overwrite, open_size, open_change_size, open_truncate, + open_error]}, {close, [], [close_race, close_block, close_deadlock]}, {error, [], [error_repair, error_log, error_index]}, {info, [], [info_current]}, @@ -1911,7 +1913,8 @@ open_size(Conf) when is_list(Conf) -> {mode, read_only}, {format, internal}, {size, {100, No + 1}}]), "The given size" ++ _ = format_error(Error1), - {ok, nn} = disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {ok, nn} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, {mode, read_only}, {format, internal},{size, {100, No}}]), [_, _, _, _] = get_all_terms1(nn, start, []), @@ -1919,21 +1922,132 @@ open_size(Conf) when is_list(Conf) -> ok = disk_log:unblock(n), ok = disk_log:close(n), + del(File, No), + + ok. + +%% OTP-17062. When opening a disk log for the first time, the 'size' +%% option can change the size of the file. +open_change_size(Conf) when is_list(Conf) -> + + %% wrap logs + + Dir = ?privdir(Conf), + File = filename:join(Dir, "n.LOG"), + + No = 4, + file:delete(File), + del(File, No), % cleanup + + {ok, n} = disk_log:open([{name, n}, {file, File}, {type, wrap}, + {format, internal},{size, {100, No}}]), + [n] = disk_log:all(), + 1 = curf(n), + B = mk_bytes(60), + ok = disk_log:log_terms(n, [B, B, B, B]), + 4 = curf(n), + disk_log:close(n), + + %% size option does not match existing size file, read_only + Error1 = {error, {size_mismatch, _, _}} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {mode, read_only}, {format, internal}, + {size, {100, No + 1}}]), + "The given size" ++ _ = format_error(Error1), + {ok, nn} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {mode, read_only}, + {format, internal},{size, {100, No}}]), + [_, _, _, _] = get_all_terms(nn), + {error, {size_mismatch, _, _}} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {mode, read_only}, {format, internal}, + {size, {100, No + 1}}]), + {error,{badarg,repair_read_only}} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {mode, read_only}, {format, internal}, + {repair, truncate}, {size, {100, No + 1}}]), + disk_log:close(nn), %% size option does not match existing size file, read_write + No1 = No + 1, + No2 = No + 2, + %% open/1 can change the size of a newly opened wrap log + {ok, nn} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {format, internal}, {size, {100, No1}}]), + {100, No1} = info(nn, size, foo), + 4 = curf(nn), + %% open/1 cannot change the size of an open wrap log {error, {size_mismatch, _, _}} = - disk_log:open([{name, nn}, {file, File}, {type, wrap}, - {format, internal}, {size, {100, No + 1}}]), + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {format, internal}, {size, {100, No2}}]), + ok = disk_log:close(nn), + + %% open/1 cannot change the size of a newly opened wrap log to 'infinity' + {ok, nn} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {format, internal}, {size, infinity}]), + {100, 5} = info(nn, size, foo), + 4 = curf(nn), + %% open/1 cannot change the size of an open wrap log + {error, {size_mismatch, {100,5}, infinity}} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {format, internal}, {size, infinity}]), + ok = disk_log:close(nn), + %% size option does not match existing size file, truncating {ok, nn} = - disk_log:open([{name, nn}, {file, File}, {type, wrap}, - {repair, truncate}, {format, internal}, - {size, {100, No + 1}}]), + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {repair, truncate}, {format, internal}, + {size, {100, No2}}]), + {100, No2} = info(nn, size, foo), + 1 = curf(nn), + [] = get_all_terms(nn), + %% open/1 cannot change the size of an open wrap log + {error, {size_mismatch, _, _}} = + disk_log:open([{name, nn}, {file, File}, {type, wrap}, + {repair, truncate}, {format, internal}, + {size, {100, No2 + 1}}]), ok = disk_log:close(nn), del(File, No), - ok. + %% halt logs + Name = 'log.LOG', + HFile = "log.LOG", + Finite = 10000, + {ok, _} = disk_log:open([{name,Name}, {type,halt}, {size,infinity}, + {format,internal}, {file,HFile}]), + ok = disk_log:blog(Name, B), + + %% open/1 ignores the given size if the halt log is open, + %% which is backwards compatible. + {ok, Name} = + disk_log:open([{name,Name}, {type,halt}, {size,Finite}, + {format,internal}, {file,HFile}]), + infinity = info(Name, size, foo), + ok = disk_log:close(Name), + %% open/1 can change the size of a newly opened halt log + {ok, Name} = + disk_log:open([{name,Name}, {type,halt}, {size,Finite}, + {format,internal}, {file,HFile}]), + Finite = info(Name, size, foo), + %% open/1 ignores the given size if the halt log is open, + %% which is backwards compatible. + {ok, Name} = + disk_log:open([{name,Name}, {type,halt}, {size,infinity}, + {format,internal}, {file,HFile}]), + Finite = info(Name, size, foo), + ok = disk_log:close(Name), + + %% open/1 can open a halt log even if the given size is too small, + %% which is backwards compatible. + {ok, Name} = + disk_log:open([{name,Name}, {type,halt}, {size,10}, + {format,internal}, {file,HFile}]), + file:delete(HFile), + ok. %% Test open/1 with {repair, truncate}. open_truncate(Conf) when is_list(Conf) -> -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor