Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
0964-mnesia-Fix-add_table_copy.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0964-mnesia-Fix-add_table_copy.patch of Package erlang
From 6213b70b2aba47cc60306bdafc3ef01862d532bd Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson <dgud@erlang.org> Date: Mon, 28 Mar 2022 15:35:29 +0200 Subject: [PATCH] mnesia: Fix add_table_copy add_table_copy done at the same time as a node started could lead to mnesia hanging or looping forever. --- lib/mnesia/src/mnesia_controller.erl | 29 +++++++++++++---------- lib/mnesia/src/mnesia_loader.erl | 10 ++++---- lib/mnesia/src/mnesia_schema.erl | 6 +++-- lib/mnesia/test/ext_test.erl | 2 +- lib/mnesia/test/mnesia_isolation_test.erl | 18 +++++++++----- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl index 5ea3a896e1..4ab32a9efa 100644 --- a/lib/mnesia/src/mnesia_controller.erl +++ b/lib/mnesia/src/mnesia_controller.erl @@ -46,7 +46,7 @@ %% Mnesia internal stuff -export([ start/0, - i_have_tab/1, + i_have_tab/2, info/0, get_info/1, get_workers/1, @@ -354,7 +354,7 @@ get_network_copy(Tid, Tab, Cs) -> Tab = Res#loader_done.table_name, case Res#loader_done.needs_announce of true -> - i_have_tab(Tab); + i_have_tab(Tab, Cs); false -> ignore end, @@ -378,10 +378,12 @@ get_network_copy(Tid, Tab, Cs) -> %% is synchronously started from mnesia_controller create_table(Tab) -> - {loaded, ok} = mnesia_loader:disc_load_table(Tab, {dumper,create_table}). + Cs = val({Tab, cstruct}), + {loaded, ok} = mnesia_loader:disc_load_table(Tab, {dumper,create_table}, Cs). get_disc_copy(Tab) -> - disc_load_table(Tab, {dumper,change_table_copy_type}, undefined). + Cs = val({Tab, cstruct}), + disc_load_table(Tab, {dumper,change_table_copy_type}, undefined, Cs). %% Returns ok instead of yes force_load_table(Tab) when is_atom(Tab), Tab /= schema -> @@ -1811,13 +1813,16 @@ user_sync_tab(Tab) -> end. i_have_tab(Tab) -> + i_have_tab(Tab, val({Tab, cstruct})). + +i_have_tab(Tab, Cs) -> case val({Tab, local_content}) of true -> mnesia_lib:set_local_content_whereabouts(Tab); false -> set({Tab, where_to_read}, node()) end, - add_active_replica(Tab, node()). + add_active_replica(Tab, node(), Cs). sync_and_block_table_whereabouts(Tab, ToNode, RemoteS, AccessMode) when Tab /= schema -> Current = val({current, db_nodes}), @@ -2199,13 +2204,13 @@ load_table_fun(#net_load{cstruct=Cs, table=Tab, reason=Reason, opt_reply_to=Repl fun() -> Done end; LocalC == true -> fun() -> - Res = mnesia_loader:disc_load_table(Tab, load_local_content), + Res = mnesia_loader:disc_load_table(Tab, load_local_content, Cs), Done#loader_done{reply = Res, needs_announce = true, needs_sync = true} end; AccessMode == read_only, not AddTableCopy -> - fun() -> disc_load_table(Tab, Reason, ReplyTo) end; + fun() -> disc_load_table(Tab, Reason, ReplyTo, Cs) end; Active =:= [], AddTableCopy, OnlyRamCopies -> - fun() -> disc_load_table(Tab, Reason, ReplyTo) end; + fun() -> disc_load_table(Tab, Reason, ReplyTo, Cs) end; true -> fun() -> %% Either we cannot read the table yet @@ -2231,13 +2236,13 @@ load_table_fun(#disc_load{table=Tab, reason=Reason, opt_reply_to=ReplyTo}) -> needs_sync = false, needs_reply = false }, + Cs = val({Tab, cstruct}), if Active == [], ReadNode == nowhere -> %% Not loaded anywhere, lets load it from disc - fun() -> disc_load_table(Tab, Reason, ReplyTo) end; + fun() -> disc_load_table(Tab, Reason, ReplyTo, Cs) end; ReadNode == nowhere -> %% Already loaded on other node, lets get it - Cs = val({Tab, cstruct}), fun() -> case mnesia_loader:net_load_table(Tab, Reason, Active, Cs) of {loaded, ok} -> @@ -2254,7 +2259,7 @@ load_table_fun(#disc_load{table=Tab, reason=Reason, opt_reply_to=ReplyTo}) -> fun() -> Done end end. -disc_load_table(Tab, Reason, ReplyTo) -> +disc_load_table(Tab, Reason, ReplyTo, Cs) -> Done = #loader_done{is_loaded = true, table_name = Tab, needs_announce = false, @@ -2263,7 +2268,7 @@ disc_load_table(Tab, Reason, ReplyTo) -> reply_to = ReplyTo, reply = {loaded, ok} }, - Res = mnesia_loader:disc_load_table(Tab, Reason), + Res = mnesia_loader:disc_load_table(Tab, Reason, Cs), if Res == {loaded, ok} -> Done#loader_done{needs_announce = true, diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl index da43a521a4..632c31e64e 100644 --- a/lib/mnesia/src/mnesia_loader.erl +++ b/lib/mnesia/src/mnesia_loader.erl @@ -24,7 +24,7 @@ -module(mnesia_loader). %% Mnesia internal stuff --export([disc_load_table/2, +-export([disc_load_table/3, net_load_table/4, send_table/4]). @@ -44,8 +44,8 @@ val(Var) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Load a table from local disc -disc_load_table(Tab, Reason) -> - Storage = val({Tab, storage_type}), +disc_load_table(Tab, Reason, Cs) -> + Storage = mnesia_lib:cs_to_storage_type(node(), Cs), Type = val({Tab, setorbag}), dbg_out("Getting table ~tp (~p) from disc: ~tp~n", [Tab, Storage, Reason]), @@ -222,7 +222,7 @@ do_get_network_copy(Tab, Reason, Ns, Storage, Cs) -> ok -> set({Tab, load_node}, Node), set({Tab, load_reason}, Reason), - mnesia_controller:i_have_tab(Tab), + mnesia_controller:i_have_tab(Tab, Cs), dbg_out("Table ~tp copied from ~p to ~p~n", [Tab, Node, node()]), {loaded, ok}; Err = {error, _} when element(1, Reason) == dumper -> @@ -383,9 +383,11 @@ do_init_table(Tab,Storage,Cs,SenderPid, Reason -> Msg = "[d]ets:init table failed", verbose("~ts: ~tp: ~tp~n", [Msg, Tab, Reason]), + SenderPid ! {copier_done, node()}, down(Tab, Storage) end; Error -> + SenderPid ! {copier_done, node()}, Error end. diff --git a/lib/mnesia/src/mnesia_schema.erl b/lib/mnesia/src/mnesia_schema.erl index ed7f362cf6..5ee3265613 100644 --- a/lib/mnesia/src/mnesia_schema.erl +++ b/lib/mnesia/src/mnesia_schema.erl @@ -2466,10 +2466,12 @@ prepare_op(Tid, {op, add_table_copy, Storage, Node, TabDef}, _WaitFor) -> _ -> ok end, - %% Tables are created by mnesia_loader get_network code - insert_cstruct(Tid, Cs, true), + mnesia_lib:verbose("~w:~w Adding table~n",[?MODULE,?LINE]), + case mnesia_controller:get_network_copy(Tid, Tab, Cs) of {loaded, ok} -> + %% Tables are created by mnesia_loader get_network code + insert_cstruct(Tid, Cs, true), {true, optional}; {not_loaded, ErrReason} -> Reason = {system_limit, Tab, {Node, ErrReason}}, diff --git a/lib/mnesia/test/ext_test.erl b/lib/mnesia/test/ext_test.erl index 98a425277c..dfa6d7da04 100644 --- a/lib/mnesia/test/ext_test.erl +++ b/lib/mnesia/test/ext_test.erl @@ -72,7 +72,7 @@ init_backend() -> ?DBG(init_backend), %% cheat and stuff a marker in mnesia_gvar K = backend_init_marker(), - case try mnesia_lib:val(K) catch _:_ -> error end of + case try ets:lookup_element(mnesia_gvar, K, 2) catch _:_ -> error end of error -> mnesia_lib:set(K, true); Other -> diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl index b3cb26831c..601f46e45f 100644 --- a/lib/mnesia/test/mnesia_isolation_test.erl +++ b/lib/mnesia/test/mnesia_isolation_test.erl @@ -1118,16 +1118,22 @@ add_table_copy(Config) when is_list(Config) -> end), receive {New,ok} -> ok end, - Add = fun Add() -> + Add = fun Add(N) -> case mnesia:add_table_copy(Tab, Node2, disc_copies) of {atomic, ok} -> ok; - _R -> io:format(user, "aborted with reason ~p~n", [_R]), - timer:sleep(10), - Add() + _R -> + case N > 0 of + true -> + timer:sleep(25), + Add(N-1); + false -> + io:format(user, "aborted with reason ~p~n", [_R]), + fail + end end end, - - ?match(ok, Add()), + + ?match(ok, Add(200)), ?match_receive({New,ok}), sys:get_status(whereis(mnesia_locker)), % Explicit sync, release locks is async -- 2.34.1
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