diff options
Diffstat (limited to 'lib/mnesia/src/mnesia_monitor.erl')
-rw-r--r-- | lib/mnesia/src/mnesia_monitor.erl | 98 |
1 files changed, 71 insertions, 27 deletions
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl index 438da65158..6fc1a394a6 100644 --- a/lib/mnesia/src/mnesia_monitor.erl +++ b/lib/mnesia/src/mnesia_monitor.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. 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 @@ -44,6 +44,7 @@ set_env/2, start/0, start_proc/4, + sync_log/1, terminate_proc/3, unsafe_close_dets/1, unsafe_close_log/1, @@ -78,7 +79,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}). @@ -118,6 +119,9 @@ open_log(Args) -> reopen_log(Name, Fname, Head) -> unsafe_call({reopen_log, Name, Fname, Head}). +sync_log(Name) -> + unsafe_call({sync_log, Name}). + close_log(Name) -> unsafe_call({close_log, Name}). @@ -202,7 +206,7 @@ needs_protocol_conversion(Node) -> cast(Msg) -> case whereis(?MODULE) of - undefined -> ignore; + undefined -> ok; Pid -> gen_server:cast(Pid, Msg) end. @@ -382,6 +386,9 @@ handle_call({reopen_log, Name, Fname, Head}, _From, State) -> {noreply, State} end; +handle_call({sync_log, Name}, _From, State) -> + {reply, disk_log:sync(Name), State}; + handle_call({close_log, Name}, _From, State) -> case disk_log:close(Name) of ok -> @@ -395,7 +402,7 @@ handle_call({close_log, Name}, _From, State) -> end; handle_call({unsafe_close_log, Name}, _From, State) -> - disk_log:close(Name), + _ = disk_log:close(Name), {reply, ok, State}; handle_call({negotiate_protocol, Mon, _Version, _Protocols}, _From, State) @@ -439,7 +446,7 @@ handle_call({negotiate_protocol, Nodes}, From, State) -> end; handle_call(init, _From, State) -> - net_kernel:monitor_nodes(true), + _ = net_kernel:monitor_nodes(true), EarlyNodes = State#state.early_connects, State2 = State#state{tm_started = true}, {reply, EarlyNodes, State2}; @@ -488,17 +495,18 @@ handle_cast({mnesia_down, mnesia_tm, Node}, State) -> 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) -> @@ -564,27 +572,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 @@ -826,3 +825,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. |