From 995ab280a4dd050acbac0d2b824bcb3178811ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= Date: Tue, 23 Aug 2016 18:07:30 +0200 Subject: mnesia: Remove mnesia_frag_old_hash hash module The module mnesia_frag_old_hash utilized the broken erlang:hash/2 function which has been deprecated for a long time. Since erlang:hash/2 is now removed there is no point in having this module any more. --- lib/mnesia/doc/src/Mnesia_chap5.xmlsrc | 5 -- lib/mnesia/src/Makefile | 1 - lib/mnesia/src/mnesia.app.src | 1 - lib/mnesia/src/mnesia.erl | 1 - lib/mnesia/src/mnesia.hrl | 7 +- lib/mnesia/src/mnesia_frag.erl | 76 ++++++++---------- lib/mnesia/src/mnesia_frag_old_hash.erl | 133 -------------------------------- 7 files changed, 34 insertions(+), 190 deletions(-) delete mode 100644 lib/mnesia/src/mnesia_frag_old_hash.erl (limited to 'lib/mnesia') diff --git a/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc b/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc index a83d1d77d2..62759c624b 100644 --- a/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc +++ b/lib/mnesia/doc/src/Mnesia_chap5.xmlsrc @@ -362,11 +362,6 @@ ok mnesia_frag_hash callback behavior. This property can explicitly be set at table creation. Default is mnesia_frag_hash.

-

Older tables, that were created before the concept of - user-defined hash modules was introduced, use module - mnesia_frag_old_hash to be backwards compatible. - mnesia_frag_old_hash still uses the poor - deprecated function erlang:hash/1.

{hash_state, Term} diff --git a/lib/mnesia/src/Makefile b/lib/mnesia/src/Makefile index 5206e469a5..b68fc7d3d0 100644 --- a/lib/mnesia/src/Makefile +++ b/lib/mnesia/src/Makefile @@ -55,7 +55,6 @@ MODULES= \ mnesia_ext_sup \ mnesia_frag \ mnesia_frag_hash \ - mnesia_frag_old_hash \ mnesia_index \ mnesia_kernel_sup \ mnesia_late_loader \ diff --git a/lib/mnesia/src/mnesia.app.src b/lib/mnesia/src/mnesia.app.src index af14826c90..a5d74d2d36 100644 --- a/lib/mnesia/src/mnesia.app.src +++ b/lib/mnesia/src/mnesia.app.src @@ -15,7 +15,6 @@ mnesia_ext_sup, mnesia_frag, mnesia_frag_hash, - mnesia_frag_old_hash, mnesia_index, mnesia_kernel_sup, mnesia_late_loader, diff --git a/lib/mnesia/src/mnesia.erl b/lib/mnesia/src/mnesia.erl index 6de7214776..dece995d39 100644 --- a/lib/mnesia/src/mnesia.erl +++ b/lib/mnesia/src/mnesia.erl @@ -316,7 +316,6 @@ ms() -> mnesia_loader, mnesia_frag, mnesia_frag_hash, - mnesia_frag_old_hash, mnesia_index, mnesia_kernel_sup, mnesia_late_loader, diff --git a/lib/mnesia/src/mnesia.hrl b/lib/mnesia/src/mnesia.hrl index 0716dd87c8..da7e662288 100644 --- a/lib/mnesia/src/mnesia.hrl +++ b/lib/mnesia/src/mnesia.hrl @@ -49,12 +49,12 @@ %% It's important that counter is first, since we compare tid's --record(tid, +-record(tid, {counter, %% serial no for tid pid}). %% owner of tid --record(tidstore, +-record(tidstore, {store, %% current ets table for tid up_stores = [], %% list of upper layer stores for nested trans level = 1}). %% transaction level @@ -128,5 +128,4 @@ mnesia_lib:eval_debug_fun(I, C, ?FILE, ?LINE)). -else. -define(eval_debug_fun(I, C), ok). --endif. - +-endif. diff --git a/lib/mnesia/src/mnesia_frag.erl b/lib/mnesia/src/mnesia_frag.erl index c6e812b36d..c39f30e140 100644 --- a/lib/mnesia/src/mnesia_frag.erl +++ b/lib/mnesia/src/mnesia_frag.erl @@ -58,9 +58,7 @@ -include("mnesia.hrl"). --define(OLD_HASH_MOD, mnesia_frag_old_hash). -define(DEFAULT_HASH_MOD, mnesia_frag_hash). -%%-define(DEFAULT_HASH_MOD, ?OLD_HASH_MOD). %% BUGBUG: New should be default -record(frag_state, {foreign_key, @@ -80,7 +78,7 @@ lock(ActivityId, Opaque, {table , Tab}, LockKind) -> case frag_names(Tab) of [Tab] -> - mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind); + mnesia:lock(ActivityId, Opaque, {table, Tab}, LockKind); Frags -> DeepNs = [mnesia:lock(ActivityId, Opaque, {table, F}, LockKind) || F <- Frags], @@ -321,7 +319,7 @@ init_select(Tid,Opaque,Tab,Pat,Limit,LockKind) -> {'EXIT', _} -> mnesia:select(Tid, Opaque, Tab, Pat, Limit,LockKind); FH -> - FragNumbers = verify_numbers(FH,Pat), + FragNumbers = verify_numbers(FH,Pat), Fun = fun(Num) -> Name = n_to_frag_name(Tab, Num), Node = val({Name, where_to_read}), @@ -336,19 +334,19 @@ init_select(Tid,Opaque,Tab,Pat,Limit,LockKind) -> end. select_cont(_Tid,_,{frag_cont, '$end_of_table', [],_}) -> '$end_of_table'; -select_cont(Tid,Ts,{frag_cont, '$end_of_table', [{Tab,Node,Type}|Rest],Args}) -> +select_cont(Tid,Ts,{frag_cont, '$end_of_table', [{Tab,Node,Type}|Rest],Args}) -> {Spec,LockKind,Limit} = Args, InitFun = fun(FixedSpec) -> mnesia:dirty_sel_init(Node,Tab,FixedSpec,Limit,Type) end, Res = mnesia:fun_select(Tid,Ts,Tab,Spec,LockKind,Tab,InitFun,Limit,Node,Type), frag_sel_cont(Res, Rest, Args); -select_cont(Tid,Ts,{frag_cont, Cont, TabL, Args}) -> +select_cont(Tid,Ts,{frag_cont, Cont, TabL, Args}) -> frag_sel_cont(mnesia:select_cont(Tid,Ts,Cont),TabL,Args); select_cont(Tid,Ts,Else) -> %% Not a fragmented table mnesia:select_cont(Tid,Ts,Else). frag_sel_cont('$end_of_table', [],_) -> '$end_of_table'; -frag_sel_cont('$end_of_table', TabL,Args) -> +frag_sel_cont('$end_of_table', TabL,Args) -> {[], {frag_cont, '$end_of_table', TabL,Args}}; frag_sel_cont({Recs,Cont}, TabL,Args) -> {Recs, {frag_cont, Cont, TabL,Args}}. @@ -358,9 +356,9 @@ do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind) -> {'EXIT', _} -> mnesia:select(ActivityId, Opaque, Tab, MatchSpec, LockKind); FH -> - FragNumbers = verify_numbers(FH,MatchSpec), + FragNumbers = verify_numbers(FH,MatchSpec), Fun = fun(Num) -> - Name = n_to_frag_name(Tab, Num), + Name = n_to_frag_name(Tab, Num), Node = val({Name, where_to_read}), mnesia:lock(ActivityId, Opaque, {table, Name}, LockKind), {Name, Node} @@ -398,7 +396,7 @@ do_select(ActivityId, Opaque, Tab, MatchSpec, LockKind) -> verify_numbers(FH,MatchSpec) -> HashState = FH#frag_state.hash_state, - FragNumbers = + FragNumbers = case FH#frag_state.hash_module of HashMod when HashMod == ?DEFAULT_HASH_MOD -> ?DEFAULT_HASH_MOD:match_spec_to_frag_numbers(HashState, MatchSpec); @@ -434,7 +432,7 @@ local_select(ReplyTo, Ref, RemoteNameNodes, MatchSpec) -> end, unlink(ReplyTo), exit(normal). - + remote_select(ReplyTo, Ref, NameNodes, MatchSpec) -> do_remote_select(ReplyTo, Ref, NameNodes, MatchSpec). @@ -805,22 +803,22 @@ make_deactivate(Tab) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Add a fragment to a fragmented table and fill it with half of %% the records from one of the old fragments - + make_multi_add_frag(Tab, SortedNs) when is_list(SortedNs) -> verify_multi(Tab), Ops = make_add_frag(Tab, SortedNs), %% Propagate to foreigners MoreOps = [make_add_frag(T, SortedNs) || T <- lookup_foreigners(Tab)], - [Ops | MoreOps]; + [Ops | MoreOps]; make_multi_add_frag(Tab, SortedNs) -> mnesia:abort({bad_type, Tab, SortedNs}). verify_multi(Tab) -> FH = lookup_frag_hash(Tab), ForeignKey = FH#frag_state.foreign_key, - mnesia_schema:verify(undefined, ForeignKey, - {combine_error, Tab, + mnesia_schema:verify(undefined, ForeignKey, + {combine_error, Tab, "Op only allowed via foreign table", {foreign_key, ForeignKey}}). @@ -839,7 +837,7 @@ make_frag_names_and_acquire_locks(Tab, N, FragIndecies, DoNotLockN) -> end, FragNames = erlang:make_tuple(N, undefined), lists:foldl(Fun, FragNames, FragIndecies). - + make_add_frag(Tab, SortedNs) -> Cs = mnesia_schema:incr_version(val({Tab, cstruct})), mnesia_schema:ensure_active(Cs), @@ -849,8 +847,8 @@ make_add_frag(Tab, SortedNs) -> FragNames = make_frag_names_and_acquire_locks(Tab, N, WriteIndecies, true), NewFrag = element(N, FragNames), - NR = length(Cs#cstruct.ram_copies), - ND = length(Cs#cstruct.disc_copies), + NR = length(Cs#cstruct.ram_copies), + ND = length(Cs#cstruct.disc_copies), NDO = length(Cs#cstruct.disc_only_copies), NExt = length(Cs#cstruct.external_copies), NewCs = Cs#cstruct{name = NewFrag, @@ -859,7 +857,7 @@ make_add_frag(Tab, SortedNs) -> disc_copies = [], disc_only_copies = [], external_copies = []}, - + {NewCs2, _, _} = set_frag_nodes(NR, ND, NDO, NExt, NewCs, SortedNs, []), [NewOp] = mnesia_schema:make_create_table(NewCs2), @@ -944,7 +942,7 @@ do_split(FH, OldN, FragNames, [Rec | Recs], Ops) -> Key = element(2, Rec), NewOid = {NewFrag, Key}, OldOid = {OldFrag, Key}, - Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}}, + Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}}, {op, rec, unknown, {OldOid, [OldOid], delete}} | Ops], do_split(FH, OldN, FragNames, Recs, Ops2); _NewFrag -> @@ -958,7 +956,7 @@ do_split(_FH, _OldN, _FragNames, [], Ops) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Delete a fragment from a fragmented table %% and merge its records with another fragment - + make_multi_del_frag(Tab) -> verify_multi(Tab), Ops = make_del_frag(Tab), @@ -1064,7 +1062,7 @@ do_merge(FH, OldN, FragNames, [Rec | Recs], Ops) -> Key = element(2, Rec), NewOid = {NewFrag, Key}, OldOid = {OldFrag, Key}, - Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}}, + Ops2 = [{op, rec, unknown, {NewOid, [Rec], write}}, {op, rec, unknown, {OldOid, [OldOid], delete}} | Ops], do_merge(FH, OldN, FragNames, Recs, Ops2); _NewFrag -> @@ -1077,7 +1075,7 @@ do_merge(FH, OldN, FragNames, [Rec | Recs], Ops) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Add a node to the node pool of a fragmented table - + make_multi_add_node(Tab, Node) -> verify_multi(Tab), Ops = make_add_node(Tab, Node), @@ -1085,7 +1083,7 @@ make_multi_add_node(Tab, Node) -> %% Propagate to foreigners MoreOps = [make_add_node(T, Node) || T <- lookup_foreigners(Tab)], [Ops | MoreOps]. - + make_add_node(Tab, Node) when is_atom(Node) -> Pool = lookup_prop(Tab, node_pool), case lists:member(Node, Pool) of @@ -1114,7 +1112,7 @@ make_multi_del_node(Tab, Node) -> %% Propagate to foreigners MoreOps = [make_del_node(T, Node) || T <- lookup_foreigners(Tab)], [Ops | MoreOps]. - + make_del_node(Tab, Node) when is_atom(Node) -> Cs = mnesia_schema:incr_version(val({Tab, cstruct})), mnesia_schema:ensure_active(Cs), @@ -1147,8 +1145,8 @@ remove_node(Node, Cs) -> case lists:member(Node, Pool) of true -> Pool2 = Pool -- [Node], - Props = lists:keyreplace(node_pool, 1, - Cs#cstruct.frag_properties, + Props = lists:keyreplace(node_pool, 1, + Cs#cstruct.frag_properties, {node_pool, Pool2}), {Cs#cstruct{frag_properties = Props}, true}; false -> @@ -1180,18 +1178,10 @@ props_to_frag_hash(Tab, Props) -> T when T == Tab -> Foreign = mnesia_schema:pick(Tab, foreign_key, Props, must), N = mnesia_schema:pick(Tab, n_fragments, Props, must), - case mnesia_schema:pick(Tab, hash_module, Props, undefined) of undefined -> - Split = mnesia_schema:pick(Tab, next_n_to_split, Props, must), - Doubles = mnesia_schema:pick(Tab, n_doubles, Props, must), - FH = {frag_hash, Foreign, N, Split, Doubles}, - HashState = ?OLD_HASH_MOD:init_state(Tab, FH), - #frag_state{foreign_key = Foreign, - n_fragments = N, - hash_module = ?OLD_HASH_MOD, - hash_state = HashState}; - HashMod -> + no_hash; + HashMod -> HashState = mnesia_schema:pick(Tab, hash_state, Props, must), #frag_state{foreign_key = Foreign, n_fragments = N, @@ -1216,13 +1206,9 @@ lookup_frag_hash(Tab) -> case ?catch_val({Tab, frag_hash}) of FH when is_record(FH, frag_state) -> FH; - {frag_hash, K, N, _S, _D} = FH -> + {frag_hash, _K, _N, _S, _D} -> %% Old style. Kept for backwards compatibility. - HashState = ?OLD_HASH_MOD:init_state(Tab, FH), - #frag_state{foreign_key = K, - n_fragments = N, - hash_module = ?OLD_HASH_MOD, - hash_state = HashState}; + mnesia:abort({no_hash, Tab, frag_properties, frag_hash}); {'EXIT', _} -> mnesia:abort({no_exists, Tab, frag_properties, frag_hash}) end. @@ -1249,10 +1235,10 @@ key_pos(FH) -> case FH#frag_state.foreign_key of undefined -> 2; - {_ForeignTab, Pos} -> + {_ForeignTab, Pos} -> Pos end. - + %% Returns name of fragment table key_to_frag_name({BaseTab, _} = Tab, Key) -> N = key_to_frag_number(Tab, Key), diff --git a/lib/mnesia/src/mnesia_frag_old_hash.erl b/lib/mnesia/src/mnesia_frag_old_hash.erl deleted file mode 100644 index b246c76236..0000000000 --- a/lib/mnesia/src/mnesia_frag_old_hash.erl +++ /dev/null @@ -1,133 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2016. All Rights Reserved. -%% -%% 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% -%% - -%% -%%%---------------------------------------------------------------------- -%%% Purpose : Implements hashing functionality for fragmented tables -%%%---------------------------------------------------------------------- - --module(mnesia_frag_old_hash). -%%-behaviour(mnesia_frag_hash). - --compile({nowarn_deprecated_function, {erlang,hash,2}}). - -%% Hashing callback functions --export([ - init_state/2, - add_frag/1, - del_frag/1, - key_to_frag_number/2, - match_spec_to_frag_numbers/2 - ]). - --record(old_hash_state, - {n_fragments, - next_n_to_split, - n_doubles}). - -%% Old style. Kept for backwards compatibility. --record(frag_hash, - {foreign_key, - n_fragments, - next_n_to_split, - n_doubles}). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -init_state(_Tab, InitialState) when InitialState == undefined -> - #old_hash_state{n_fragments = 1, - next_n_to_split = 1, - n_doubles = 0}; -init_state(_Tab, FH) when is_record(FH, frag_hash) -> - %% Old style. Kept for backwards compatibility. - #old_hash_state{n_fragments = FH#frag_hash.n_fragments, - next_n_to_split = FH#frag_hash.next_n_to_split, - n_doubles = FH#frag_hash.n_doubles}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -add_frag(State) when is_record(State, old_hash_state) -> - SplitN = State#old_hash_state.next_n_to_split, - P = SplitN + 1, - L = State#old_hash_state.n_doubles, - NewN = State#old_hash_state.n_fragments + 1, - State2 = case trunc(math:pow(2, L)) + 1 of - P2 when P2 == P -> - State#old_hash_state{n_fragments = NewN, - next_n_to_split = 1, - n_doubles = L + 1}; - _ -> - State#old_hash_state{n_fragments = NewN, - next_n_to_split = P} - end, - {State2, [SplitN], [NewN]}. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -del_frag(State) when is_record(State, old_hash_state) -> - P = State#old_hash_state.next_n_to_split - 1, - L = State#old_hash_state.n_doubles, - N = State#old_hash_state.n_fragments, - if - P < 1 -> - L2 = L - 1, - MergeN = trunc(math:pow(2, L2)), - State2 = State#old_hash_state{n_fragments = N - 1, - next_n_to_split = MergeN, - n_doubles = L2}, - {State2, [N], [MergeN]}; - true -> - MergeN = P, - State2 = State#old_hash_state{n_fragments = N - 1, - next_n_to_split = MergeN}, - {State2, [N], [MergeN]} - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -key_to_frag_number(State, Key) when is_record(State, old_hash_state) -> - L = State#old_hash_state.n_doubles, - A = erlang:hash(Key, trunc(math:pow(2, L))), - P = State#old_hash_state.next_n_to_split, - if - A < P -> - erlang:hash(Key, trunc(math:pow(2, L + 1))); - true -> - A - end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -match_spec_to_frag_numbers(State, MatchSpec) when is_record(State, old_hash_state) -> - case MatchSpec of - [{HeadPat, _, _}] when is_tuple(HeadPat), tuple_size(HeadPat) > 2 -> - KeyPat = element(2, HeadPat), - case has_var(KeyPat) of - false -> - [key_to_frag_number(State, KeyPat)]; - true -> - lists:seq(1, State#old_hash_state.n_fragments) - end; - _ -> - lists:seq(1, State#old_hash_state.n_fragments) - end. - -has_var(Pat) -> - mnesia:has_var(Pat). -- cgit v1.2.3 From 230358701da9764fa4c637e9e781668276f14938 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson Date: Thu, 26 Jan 2017 12:43:36 +0100 Subject: Fixed crash when a table was deleted during checkpoint traversal Set fixtable false will fail on deleted tables, catch that and also report checkpoint deactivate error, so user can see why checkpoint was deactivated and backup fails. --- lib/mnesia/src/mnesia_checkpoint.erl | 7 +++--- lib/mnesia/src/mnesia_event.erl | 3 ++- lib/mnesia/test/mnesia_evil_backup.erl | 43 +++++++++++++++++++++++++--------- 3 files changed, 38 insertions(+), 15 deletions(-) (limited to 'lib/mnesia') diff --git a/lib/mnesia/src/mnesia_checkpoint.erl b/lib/mnesia/src/mnesia_checkpoint.erl index 9eb939e8d3..fc626940b4 100644 --- a/lib/mnesia/src/mnesia_checkpoint.erl +++ b/lib/mnesia/src/mnesia_checkpoint.erl @@ -909,7 +909,7 @@ retainer_loop(Cp = #checkpoint_args{name=Name}) -> retainer_loop(Cp2); {From, {iter_end, Iter}} -> - retainer_fixtable(Iter#iter.oid_tab, false), + ?SAFE(retainer_fixtable(Iter#iter.oid_tab, false)), Iters = Cp#checkpoint_args.iterators -- [Iter], reply(From, Name, ok), retainer_loop(Cp#checkpoint_args{iterators = Iters}); @@ -971,7 +971,8 @@ do_stop(Cp) -> unset({checkpoint, Name}), lists:foreach(fun deactivate_tab/1, Cp#checkpoint_args.retainers), Iters = Cp#checkpoint_args.iterators, - lists:foreach(fun(I) -> retainer_fixtable(I#iter.oid_tab, false) end, Iters). + [?SAFE(retainer_fixtable(Tab, false)) || #iter{main_tab=Tab} <- Iters], + ok. deactivate_tab(R) -> Name = R#retainer.cp_name, @@ -1151,7 +1152,7 @@ do_change_copy(Cp, Tab, FromType, ToType) -> Cp#checkpoint_args{retainers = Rs, nodes = writers(Rs)}. check_iter(From, Iter) when Iter#iter.pid == From -> - retainer_fixtable(Iter#iter.oid_tab, false), + ?SAFE(retainer_fixtable(Iter#iter.oid_tab, false)), false; check_iter(_From, _Iter) -> true. diff --git a/lib/mnesia/src/mnesia_event.erl b/lib/mnesia/src/mnesia_event.erl index 7320d381ea..6f7531245f 100644 --- a/lib/mnesia/src/mnesia_event.erl +++ b/lib/mnesia/src/mnesia_event.erl @@ -114,7 +114,8 @@ handle_table_event({Oper, Record, TransId}, State) -> handle_system_event({mnesia_checkpoint_activated, _Checkpoint}, State) -> {ok, State}; -handle_system_event({mnesia_checkpoint_deactivated, _Checkpoint}, State) -> +handle_system_event({mnesia_checkpoint_deactivated, Checkpoint}, State) -> + report_error("Checkpoint '~p' has been deactivated, last table copy deleted.\n",[Checkpoint]), {ok, State}; handle_system_event({mnesia_up, Node}, State) -> diff --git a/lib/mnesia/test/mnesia_evil_backup.erl b/lib/mnesia/test/mnesia_evil_backup.erl index e745ec9b04..044cf501fd 100644 --- a/lib/mnesia/test/mnesia_evil_backup.erl +++ b/lib/mnesia/test/mnesia_evil_backup.erl @@ -723,18 +723,18 @@ bup_records(File, Mod) -> exit(Reason) end. -sops_with_checkpoint(doc) -> +sops_with_checkpoint(doc) -> ["Test schema operations during a checkpoint"]; sops_with_checkpoint(suite) -> []; sops_with_checkpoint(Config) when is_list(Config) -> - Ns = ?acquire_nodes(2, Config), - + Ns = [N1,N2] = ?acquire_nodes(2, Config), + ?match({ok, cp1, Ns}, mnesia:activate_checkpoint([{name, cp1},{max,mnesia:system_info(tables)}])), - Tab = tab, + Tab = tab, ?match({atomic, ok}, mnesia:create_table(Tab, [{disc_copies,Ns}])), OldRecs = [{Tab, K, -K} || K <- lists:seq(1, 5)], [mnesia:dirty_write(R) || R <- OldRecs], - + ?match({ok, cp2, Ns}, mnesia:activate_checkpoint([{name, cp2},{max,mnesia:system_info(tables)}])), File1 = "cp1_delete_me.BUP", ?match(ok, mnesia:dirty_write({Tab,6,-6})), @@ -742,16 +742,16 @@ sops_with_checkpoint(Config) when is_list(Config) -> ?match(ok, mnesia:dirty_write({Tab,7,-7})), File2 = "cp2_delete_me.BUP", ?match(ok, mnesia:backup_checkpoint(cp2, File2)), - + ?match(ok, mnesia:deactivate_checkpoint(cp1)), ?match(ok, mnesia:backup_checkpoint(cp2, File1)), ?match(ok, mnesia:dirty_write({Tab,8,-8})), - + ?match({atomic,ok}, mnesia:delete_table(Tab)), ?match({error,_}, mnesia:backup_checkpoint(cp2, File2)), ?match({'EXIT',_}, mnesia:dirty_write({Tab,9,-9})), - ?match({atomic,_}, mnesia:restore(File1, [{default_op, recreate_tables}])), + ?match({atomic,_}, mnesia:restore(File1, [{default_op, recreate_tables}])), Test = fun(N) when N > 5 -> ?error("To many records in backup ~p ~n", [N]); (N) -> case mnesia:dirty_read(Tab,N) of [{Tab,N,B}] when -B =:= N -> ok; @@ -759,8 +759,29 @@ sops_with_checkpoint(Config) when is_list(Config) -> end end, [Test(N) || N <- mnesia:dirty_all_keys(Tab)], - ?match({aborted,enoent}, mnesia:restore(File2, [{default_op, recreate_tables}])), - + ?match({aborted,enoent}, mnesia:restore(File2, [{default_op, recreate_tables}])), + + %% Mnesia crashes when deleting a table during backup + ?match([], mnesia_test_lib:stop_mnesia([N2])), + Tab2 = ram, + ?match({atomic, ok}, mnesia:create_table(Tab2, [{ram_copies,[N1]}])), + ?match({ok, cp3, _}, mnesia:activate_checkpoint([{name, cp3}, + {ram_overrides_dump,true}, + {min,[Tab2]}])), + Write = fun Loop (N) -> + case N > 0 of + true -> + mnesia:dirty_write({Tab2, N+100, N+100}), + Loop(N-1); + false -> + ok + end + end, + ok = Write(100000), + spawn_link(fun() -> ?match({atomic, ok},mnesia:delete_table(Tab2)) end), + + %% We don't check result here, depends on timing of above call + mnesia:backup_checkpoint(cp3, File2), file:delete(File1), file:delete(File2), - ?verify_mnesia(Ns, []). + ?verify_mnesia([N1], [N2]). -- cgit v1.2.3 From 21d3a8020bde075f04441a9741b8276c27d48009 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Tue, 31 Jan 2017 15:08:44 +0100 Subject: Prepare release --- lib/mnesia/doc/src/notes.xml | 18 +++++++++++++++++- lib/mnesia/vsn.mk | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'lib/mnesia') diff --git a/lib/mnesia/doc/src/notes.xml b/lib/mnesia/doc/src/notes.xml index 51c98d0d3e..9f59759cb6 100644 --- a/lib/mnesia/doc/src/notes.xml +++ b/lib/mnesia/doc/src/notes.xml @@ -39,7 +39,23 @@ thus constitutes one section in this document. The title of each section is the version number of Mnesia.

-
Mnesia 4.14.2 +
Mnesia 4.14.3 + +
Fixed Bugs and Malfunctions + + +

+ Fixed crash in checkpoint handling when table was deleted + during backup.

+

+ Own Id: OTP-14167

+
+
+
+ +
+ +
Mnesia 4.14.2
Fixed Bugs and Malfunctions diff --git a/lib/mnesia/vsn.mk b/lib/mnesia/vsn.mk index 439b21e58c..e272a469bb 100644 --- a/lib/mnesia/vsn.mk +++ b/lib/mnesia/vsn.mk @@ -1 +1 @@ -MNESIA_VSN = 4.14.2 +MNESIA_VSN = 4.14.3 -- cgit v1.2.3 From fbfb4bb051eb54e43a91042b10250fcca177f521 Mon Sep 17 00:00:00 2001 From: Andrew Dryga Date: Sun, 12 Feb 2017 19:48:38 +0200 Subject: Fixed typos in lib/mnesia --- lib/mnesia/src/mnesia_monitor.erl | 2 +- lib/mnesia/src/mnesia_schema.erl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/mnesia') diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl index ab78c9b13e..ff58974aba 100644 --- a/lib/mnesia/src/mnesia_monitor.erl +++ b/lib/mnesia/src/mnesia_monitor.erl @@ -169,7 +169,7 @@ check_protocol([{Node, {accept, Mon, Version, Protocol}} | Tail], Protocols) -> verbose("Failed to connect with ~p. ~p protocols rejected. " "expected version = ~p, expected protocol = ~p~n", [Node, Protocols, Version, Protocol]), - unlink(Mon), % Get rid of unneccessary link + unlink(Mon), % Get rid of unnecessary link check_protocol(Tail, Protocols) end; check_protocol([{Node, {reject, _Mon, Version, Protocol}} | Tail], Protocols) -> diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl index 0e4017e4c3..b0d7965886 100644 --- a/lib/mnesia/src/mnesia_schema.erl +++ b/lib/mnesia/src/mnesia_schema.erl @@ -1941,7 +1941,7 @@ make_change_table_copy_type(Tab, Node, ToS) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% change index functions .... -%% Pos is allready added by 1 in both of these functions +%% Pos is already added by 1 in both of these functions add_table_index(Tab, Pos) -> schema_transaction(fun() -> do_add_table_index(Tab, Pos) end). -- cgit v1.2.3