aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mnesia/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mnesia/src')
-rw-r--r--lib/mnesia/src/mnesia.appup.src14
-rw-r--r--lib/mnesia/src/mnesia_locker.erl32
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl89
-rw-r--r--lib/mnesia/src/mnesia_tm.erl6
4 files changed, 84 insertions, 57 deletions
diff --git a/lib/mnesia/src/mnesia.appup.src b/lib/mnesia/src/mnesia.appup.src
index 355aafb215..c245299740 100644
--- a/lib/mnesia/src/mnesia.appup.src
+++ b/lib/mnesia/src/mnesia.appup.src
@@ -1,22 +1,16 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"4.7.1", [{restart_application, mnesia}]},
- {"4.7", [{restart_application, mnesia}]},
- {"4.6", [{restart_application, mnesia}]},
- {"4.5.1", [{restart_application, mnesia}]},
- {"4.5", [{restart_application, mnesia}]},
+ {<<"4\\.1[0-9].*">>, [{restart_application, mnesia}]},
+ {<<"4\\.[5-9].*">>, [{restart_application, mnesia}]},
{"4.4.19", [{restart_application, mnesia}]},
{"4.4.18", [{restart_application, mnesia}]},
{"4.4.17", [{restart_application, mnesia}]},
{"4.4.16", [{restart_application, mnesia}]}
],
[
- {"4.7.1", [{restart_application, mnesia}]},
- {"4.7", [{restart_application, mnesia}]},
- {"4.6", [{restart_application, mnesia}]},
- {"4.5.1", [{restart_application, mnesia}]},
- {"4.5", [{restart_application, mnesia}]},
+ {<<"4\\.1[0-9].*">>, [{restart_application, mnesia}]},
+ {<<"4\\.[5-9].*">>, [{restart_application, mnesia}]},
{"4.4.19", [{restart_application, mnesia}]},
{"4.4.18", [{restart_application, mnesia}]},
{"4.4.17", [{restart_application, mnesia}]},
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index 14011003d3..c4fe370ec1 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2012. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2013. 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
@@ -26,8 +26,8 @@
global_lock/5,
ixrlock/5,
init/1,
- mnesia_down/2,
release_tid/1,
+ mnesia_down/2,
async_release_tid/2,
send_release_tid/2,
receive_release_tid_acc/2,
@@ -137,6 +137,17 @@ receive_release_tid_acc([Node | Nodes], Tid) ->
receive_release_tid_acc([], _Tid) ->
ok.
+mnesia_down(Node, Pending) ->
+ case whereis(?MODULE) of
+ undefined -> {error, node_not_running};
+ Pid ->
+ Ref = make_ref(),
+ Pid ! {{self(), Ref}, {release_remote_non_pending, Node, Pending}},
+ receive %% No need to wait for anything else if process dies we die soon
+ {Ref,ok} -> ok
+ end
+ end.
+
loop(State) ->
receive
{From, {write, Tid, Oid}} ->
@@ -213,9 +224,9 @@ loop(State) ->
reply(From, {tid_released, Tid}),
loop(State);
- {release_remote_non_pending, Node, Pending} ->
+ {{From, Ref},{release_remote_non_pending, Node, Pending}} ->
release_remote_non_pending(Node, Pending),
- mnesia_monitor:mnesia_down(?MODULE, Node),
+ From ! {Ref, ok},
loop(State);
{'EXIT', Pid, _} when Pid == State#state.supervisor ->
@@ -653,19 +664,6 @@ ix_read_res(Tab,IxKey,Pos) ->
%% ********************* end server code ********************
%% The following code executes at the client side of a transactions
-mnesia_down(N, Pending) ->
- case whereis(?MODULE) of
- undefined ->
- %% Takes care of mnesia_down's in early startup
- mnesia_monitor:mnesia_down(?MODULE, N);
- Pid ->
- %% Syncronously call needed in order to avoid
- %% race with mnesia_tm's coordinator processes
- %% that may restart and acquire new locks.
- %% mnesia_monitor ensures the sync.
- Pid ! {release_remote_non_pending, N, Pending}
- end.
-
%% Aquire a write lock, but do a read, used by
%% mnesia:wread/1
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index 7a788238fc..c7b905a1bf 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -78,7 +78,7 @@
-record(state, {supervisor, pending_negotiators = [],
going_down = [], tm_started = false, early_connects = [],
- connecting, mq = []}).
+ connecting, mq = [], remote_node_status = []}).
-define(current_protocol_version, {8,1}).
@@ -482,27 +482,24 @@ handle_cast({mnesia_down, mnesia_controller, Node}, State) ->
mnesia_tm:mnesia_down(Node),
{noreply, State};
-handle_cast({mnesia_down, mnesia_tm, {Node, Pending}}, State) ->
- mnesia_locker:mnesia_down(Node, Pending),
- {noreply, State};
-
-handle_cast({mnesia_down, mnesia_locker, Node}, State) ->
+handle_cast({mnesia_down, mnesia_tm, Node}, State) ->
Down = {mnesia_down, Node},
mnesia_lib:report_system_event(Down),
GoingDown = lists:delete(Node, State#state.going_down),
State2 = State#state{going_down = GoingDown},
Pending = State#state.pending_negotiators,
+ State3 = check_raise_conditon_nodeup(Node, State2),
case lists:keysearch(Node, 1, Pending) of
{value, {Node, Mon, ReplyTo, Reply}} ->
%% Late reply to remote monitor
link(Mon), %% link to remote Monitor
gen_server:reply(ReplyTo, Reply),
P2 = lists:keydelete(Node, 1,Pending),
- State3 = State2#state{pending_negotiators = P2},
- process_q(State3);
+ State4 = State3#state{pending_negotiators = P2},
+ process_q(State4);
false ->
%% No pending remote monitors
- process_q(State2)
+ process_q(State3)
end;
handle_cast({disconnect, Node}, State) ->
@@ -568,27 +565,18 @@ handle_info({protocol_negotiated, From,Res}, State) ->
gen_server:reply(From, Res),
process_q(State#state{connecting = undefined});
-handle_info({nodeup, Node}, State) ->
- %% Ok, we are connected to yet another Erlang node
- %% Let's check if Mnesia is running there in order
- %% to detect if the network has been partitioned
- %% due to communication failure.
-
- HasDown = mnesia_recover:has_mnesia_down(Node),
- ImRunning = mnesia_lib:is_running(),
+handle_info({check_nodeup, Node}, State) ->
+ State2 = check_mnesia_down(Node, State),
+ {noreply, State2};
- if
- %% If I'm not running the test will be made later.
- HasDown == true, ImRunning == yes ->
- spawn_link(?MODULE, detect_partitioned_network, [self(), Node]);
- true ->
- ignore
- end,
- {noreply, State};
+handle_info({nodeup, Node}, State) ->
+ State2 = remote_node_status(Node, up, State),
+ State3 = check_mnesia_down(Node, State2),
+ {noreply, State3};
-handle_info({nodedown, _Node}, State) ->
- %% Ignore, we are only caring about nodeup's
- {noreply, State};
+handle_info({nodedown, Node}, State) ->
+ State2 = remote_node_status(Node, down, State),
+ {noreply, State2};
handle_info({disk_log, _Node, Log, Info}, State) ->
case Info of
@@ -830,3 +818,48 @@ report_inconsistency([{badrpc, _Reason} | Replies], Context, Status) ->
report_inconsistency(Replies, Context, Status);
report_inconsistency([], _Context, Status) ->
Status.
+
+remote_node_status(Node, Status, State) ->
+ {ok, Nodes} = mnesia_schema:read_nodes(),
+ case lists:member(Node, Nodes) of
+ true ->
+ update_node_status({Node, Status}, State);
+ _ ->
+ State
+ end.
+
+update_node_status({Node, down}, State = #state{remote_node_status = RNodeS}) ->
+ RNodeS2 = lists:ukeymerge(1, [{Node, down}], RNodeS),
+ State#state{remote_node_status = RNodeS2};
+update_node_status({Node, up}, State = #state{remote_node_status = RNodeS}) ->
+ case lists:keyfind(Node, 1, RNodeS) of
+ {Node, down} ->
+ RNodeS2 = lists:ukeymerge(1, [{Node, up}], RNodeS),
+ State#state{remote_node_status = RNodeS2};
+ _ ->
+ State
+ end.
+
+check_raise_conditon_nodeup(Node, State = #state{remote_node_status = RNodeS}) ->
+ case lists:keyfind(Node, 1, RNodeS) of
+ {Node, up} ->
+ self() ! {check_nodeup, Node};
+ _ ->
+ ignore
+ end,
+ State#state{remote_node_status = lists:keydelete(Node, 1, RNodeS)}.
+
+check_mnesia_down(Node, State = #state{remote_node_status = RNodeS}) ->
+ %% Check if the network has been partitioned
+ %% due to communication failure.
+
+ HasDown = mnesia_recover:has_mnesia_down(Node),
+ ImRunning = mnesia_lib:is_running(),
+ if
+ %% If I'm not running the test will be made later.
+ HasDown == true, ImRunning == yes ->
+ spawn_link(?MODULE, detect_partitioned_network, [self(), Node]),
+ State#state{remote_node_status = lists:keydelete(Node, 1, RNodeS)};
+ true ->
+ State
+ end.
diff --git a/lib/mnesia/src/mnesia_tm.erl b/lib/mnesia/src/mnesia_tm.erl
index e54e5c4e88..17af0cad44 100644
--- a/lib/mnesia/src/mnesia_tm.erl
+++ b/lib/mnesia/src/mnesia_tm.erl
@@ -181,7 +181,7 @@ mnesia_down(Node) ->
%% mnesia_monitor takes care of the sync
case whereis(?MODULE) of
undefined ->
- mnesia_monitor:mnesia_down(?MODULE, {Node, []});
+ mnesia_monitor:mnesia_down(?MODULE, Node);
Pid ->
Pid ! {mnesia_down, Node}
end.
@@ -403,7 +403,9 @@ doit_loop(#state{coordinators=Coordinators,participants=Participants,supervisor=
Tids = gb_trees:keys(Participants),
reconfigure_participants(N, gb_trees:values(Participants)),
NewState = clear_fixtable(N, State),
- mnesia_monitor:mnesia_down(?MODULE, {N, Tids}),
+
+ mnesia_locker:mnesia_down(N, Tids),
+ mnesia_monitor:mnesia_down(?MODULE, N),
doit_loop(NewState);
{From, {unblock_me, Tab}} ->