Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
1350-Fix-del_table_copy-loading-loop.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 1350-Fix-del_table_copy-loading-loop.patch of Package erlang
From 89f849fbe14e89a7578c0513cfddeab3f5dbfc87 Mon Sep 17 00:00:00 2001 From: Dan Gudmundsson <dgud@erlang.org> Date: Wed, 24 Apr 2024 10:54:59 +0200 Subject: [PATCH] Fix del_table_copy loading loop When a local table copy was deleted but not yet loaded mnesia could try to load it in a loop, which later when a table copy was added again could result in a crash, since we don't have locks on the receiver anymore. Tables can be simultaneously loaded and added. Fixed by removing the table from the loader queue when it is determined that the local copy is removed. Also don't 'fatal' crash mnesia if table couldn't be loaded due to table already existing. --- lib/mnesia/src/mnesia_controller.erl | 29 +++++++++++++--------- lib/mnesia/src/mnesia_event.erl | 11 +++++---- lib/mnesia/src/mnesia_loader.erl | 36 ++++++++++++++++++---------- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl index f19960360f..1e38be6ba7 100644 --- a/lib/mnesia/src/mnesia_controller.erl +++ b/lib/mnesia/src/mnesia_controller.erl @@ -1121,6 +1121,10 @@ handle_cast({adopt_orphans, Node, Tabs}, State) -> end, noreply(State2); +handle_cast({del_table_copy, Tab}, #state{late_loader_queue = LLQ0, loader_queue = LQ0} = State0) -> + noreply(State0#state{late_loader_queue = gb_trees:delete_any(Tab, LLQ0), + loader_queue = gb_trees:delete_any(Tab, LQ0)}); + handle_cast(Msg, State) -> error("~p got unexpected cast: ~tp~n", [?SERVER_NAME, Msg]), noreply(State). @@ -1224,19 +1228,19 @@ handle_info(Done = #loader_done{worker_pid=WPid, table_name=Tab}, State0) -> false -> ignore end, - case ?catch_val({Tab, active_replicas}) of - [_|_] -> % still available elsewhere + + case {?catch_val({Tab, storage_type}), val({Tab, active_replicas})} of + {unknown, _} -> %% Should not have a local copy anymore + State1#state{late_loader_queue=gb_trees:delete_any(Tab, LateQueue0)}; + {_, [_|_]} -> % still available elsewhere {value,{_,Worker}} = lists:keysearch(WPid,1,get_loaders(State0)), add_loader(Tab,Worker,State1); - _ -> + {ram_copies, []} -> DelState = State1#state{late_loader_queue=gb_trees:delete_any(Tab, LateQueue0)}, - case ?catch_val({Tab, storage_type}) of - ram_copies -> - cast({disc_load, Tab, ram_only}), - DelState; - _ -> - DelState - end + cast({disc_load, Tab, ram_only}), + DelState; + {_, []} -> %% Table deleted or not loaded anywhere + State1#state{late_loader_queue=gb_trees:delete_any(Tab, LateQueue0)} end end, State3 = opt_start_worker(State2), @@ -1764,6 +1768,10 @@ del_active_replica(Tab, Node) -> set(Var, mark_blocked_tab(Blocked, New)), % where_to_commit mnesia_lib:del({Tab, active_replicas}, Node), mnesia_lib:del({Tab, where_to_write}, Node), + case Node =:= node() of + true -> cast({del_table_copy, Tab}); + false -> ok + end, update_where_to_wlock(Tab). change_table_access_mode(Cs) -> @@ -2098,7 +2106,6 @@ opt_start_loader(State = #state{loader_queue = LoaderQ}) -> true -> opt_start_loader(State#state{loader_queue = Rest}); false -> - %% Start worker but keep him in the queue Pid = load_and_reply(self(), Worker), State#state{loader_pid=[{Pid,Worker}|get_loaders(State)], loader_queue = Rest} diff --git a/lib/mnesia/src/mnesia_event.erl b/lib/mnesia/src/mnesia_event.erl index 282c2c2c15..f89ecbadb1 100644 --- a/lib/mnesia/src/mnesia_event.erl +++ b/lib/mnesia/src/mnesia_event.erl @@ -109,7 +109,7 @@ handle_any_event(Msg, State) -> {ok, State}. handle_table_event({Oper, Record, TransId}, State) -> - report_info("~p performed by ~p on record:~n\t~tp~n", + report_info("~p performed by ~p on record:~n\t~0tp~n", [Oper, TransId, Record]), {ok, State}. @@ -160,9 +160,12 @@ handle_system_event({mnesia_overload, Details}, State) -> report_warning("Mnesia is overloaded: ~tw~n", [Details]), {ok, State}; -handle_system_event({mnesia_info, Format, Args}, State) -> - report_info(Format, Args), - {ok, State}; +handle_system_event({mnesia_info, Format, Args} = Event, State) -> + case put(last, Event) of + Event -> ok; + _ -> report_info(Format, Args) + end, + {ok, State}; handle_system_event({mnesia_warning, Format, Args}, State) -> report_warning(Format, Args), diff --git a/lib/mnesia/src/mnesia_loader.erl b/lib/mnesia/src/mnesia_loader.erl index 1a65dac222..827ca46c2b 100644 --- a/lib/mnesia/src/mnesia_loader.erl +++ b/lib/mnesia/src/mnesia_loader.erl @@ -47,7 +47,7 @@ val(Var) -> 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", + dbg_out("Getting table ~0tp (~0p) from disc: ~0tp~n", [Tab, Storage, Reason]), ?eval_debug_fun({?MODULE, do_get_disc_copy}, [{tab, Tab}, @@ -56,9 +56,9 @@ disc_load_table(Tab, Reason, Cs) -> {type, Type}]), do_get_disc_copy2(Tab, Reason, Storage, Type). -do_get_disc_copy2(Tab, _Reason, Storage, _Type) when Storage == unknown -> - verbose("Local table copy of ~tp has recently been deleted, ignored.~n", - [Tab]), +do_get_disc_copy2(Tab, Reason, Storage, _Type) when Storage == unknown -> + verbose("Local table copy of ~0tp ~0p has recently been deleted, ignored.~n", + [Tab, Reason]), {not_loaded, storage_unknown}; do_get_disc_copy2(Tab, Reason, Storage, Type) when Storage == disc_copies -> %% NOW we create the actual table @@ -206,14 +206,14 @@ try_net_load_table(Tab, Reason, Ns, Cs) -> end, do_get_network_copy(Tab, Reason, Ns, Storage, Cs). -do_get_network_copy(Tab, _Reason, _Ns, unknown, _Cs) -> - verbose("Local table copy of ~tp has recently been deleted, ignored.~n", [Tab]), +do_get_network_copy(Tab, Reason, _Ns, unknown, _Cs) -> + verbose("Local table copy of ~0tp (~0p) has recently been deleted, ignored.~n", [Tab,Reason]), {not_loaded, storage_unknown}; do_get_network_copy(Tab, Reason, Ns, Storage, Cs) -> [Node | Tail] = Ns, case lists:member(Node,val({current, db_nodes})) of true -> - dbg_out("Getting table ~tp (~p) from node ~p: ~tp~n", + dbg_out("Getting table ~0tp (~0p) from node ~0p: ~0tp~n", [Tab, Storage, Node, Reason]), ?eval_debug_fun({?MODULE, do_get_network_copy}, [{tab, Tab}, {reason, Reason}, @@ -289,6 +289,14 @@ init_receiver(Node, Tab,Storage,Cs,Reason) -> {atomic, {error,Result}} when element(1,Reason) == dumper -> {error,Result}; + {atomic, {error,{mktab, _} = Reason}} -> + case val({Tab,where_to_read}) == node() of + true -> %% Already loaded + ok; + false -> + fatal("Cannot create table ~tp: ~tp~n", + [[Tab, Storage], Reason]) + end; {atomic, {error,Result}} -> fatal("Cannot create table ~tp: ~tp~n", [[Tab, Storage], Result]); @@ -415,9 +423,9 @@ create_table(Tab, TabSize, Storage, Cs) -> {ok, _} -> mnesia_lib:unlock_table(Tab), {Storage, Tab}; - Else -> + {error, Reason} -> mnesia_lib:unlock_table(Tab), - Else + {error, {mktab, Reason}} end; (Storage == ram_copies) or (Storage == disc_copies) -> EtsOpts = proplists:get_value(ets, StorageProps, []), @@ -425,16 +433,18 @@ create_table(Tab, TabSize, Storage, Cs) -> case mnesia_monitor:unsafe_mktab(Tab, Args) of Tab -> {Storage, Tab}; - Else -> - Else + {error, Reason} -> + {error, {mktab, Reason}} end; element(1, Storage) == ext -> {_, Alias, Mod} = Storage, case mnesia_monitor:unsafe_create_external(Tab, Alias, Mod, Cs) of ok -> {Storage, Tab}; - Else -> - Else + {error, Reason} -> + {error, {mktab, Reason}}; + Reason -> + {error, {mktab, Reason}} end end. -- 2.35.3
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