diff options
Diffstat (limited to 'src/p1_fsm.erl')
-rw-r--r-- | src/p1_fsm.erl | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/src/p1_fsm.erl b/src/p1_fsm.erl index 03ff7f8ce..9ca924112 100644 --- a/src/p1_fsm.erl +++ b/src/p1_fsm.erl @@ -517,6 +517,25 @@ print_event(Dev, return, {Name, StateName}) -> io:format(Dev, "*DBG* ~p switched to state ~w~n", [Name, StateName]). +relay_messages(MRef, TRef, Clone, Queue) -> + lists:foreach( + fun(Msg) -> Clone ! Msg end, + queue:to_list(Queue)), + relay_messages(MRef, TRef, Clone). + +relay_messages(MRef, TRef, Clone) -> + receive + {'DOWN', MRef, process, Clone, Reason} -> + Reason; + {'EXIT', _Parent, _Reason} -> + {migrated, Clone}; + {timeout, TRef, timeout} -> + {migrated, Clone}; + Msg -> + Clone ! Msg, + relay_messages(MRef, TRef, Clone) + end. + handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, Limits, Queue, QueueLen) -> %No debug here From = from(Msg), @@ -535,6 +554,23 @@ handle_msg(Msg, Parent, Name, StateName, StateData, Mod, _Time, reply(From, Reply), loop(Parent, Name, NStateName, NStateData, Mod, Time1, [], Limits, Queue, QueueLen); + {migrate, NStateData, {Node, M, F, A}, Time1} -> + Reason = case catch rpc:call(Node, M, F, A, 5000) of + {badrpc, _} = Err -> + {migration_error, Err}; + {'EXIT', _} = Err -> + {migration_error, Err}; + {error, _} = Err -> + {migration_error, Err}; + {ok, Clone} -> + process_flag(trap_exit, true), + MRef = erlang:monitor(process, Clone), + TRef = erlang:start_timer(Time1, self(), timeout), + relay_messages(MRef, TRef, Clone, Queue); + Reply -> + {migration_error, {bad_reply, Reply}} + end, + terminate(Reason, Name, Msg, Mod, StateName, NStateData, []); {stop, Reason, NStateData} -> terminate(Reason, Name, Msg, Mod, StateName, NStateData, []); {stop, Reason, Reply, NStateData} when From =/= undefined -> @@ -571,6 +607,23 @@ handle_msg(Msg, Parent, Name, StateName, StateData, Debug1 = reply(Name, From, Reply, Debug, NStateName), loop(Parent, Name, NStateName, NStateData, Mod, Time1, Debug1, Limits, Queue, QueueLen); + {migrate, NStateData, {Node, M, F, A}, Time1} -> + Reason = case catch rpc:call(Node, M, F, A, Time1) of + {badrpc, R} -> + {migration_error, R}; + {'EXIT', R} -> + {migration_error, R}; + {error, R} -> + {migration_error, R}; + {ok, Clone} -> + process_flag(trap_exit, true), + MRef = erlang:monitor(process, Clone), + TRef = erlang:start_timer(Time1, self(), timeout), + relay_messages(MRef, TRef, Clone, Queue); + Reply -> + {migration_error, {bad_reply, Reply}} + end, + terminate(Reason, Name, Msg, Mod, StateName, NStateData, Debug); {stop, Reason, NStateData} -> terminate(Reason, Name, Msg, Mod, StateName, NStateData, Debug); {stop, Reason, Reply, NStateData} when From =/= undefined -> @@ -633,12 +686,10 @@ terminate(Reason, Name, Msg, Mod, StateName, StateData, Debug) -> %% Priority shutdown should be considered as %% shutdown by SASL exit(shutdown); - {process_limit, Limit} -> - %% Priority shutdown should be considered as - %% shutdown by SASL - error_logger:error_msg("FSM limit reached (~p): ~p~n", - [self(), Limit]), - exit(shutdown); + {process_limit, _Limit} -> + exit(Reason); + {migrated, _Clone} -> + exit(normal); _ -> error_info(Mod, Reason, Name, Msg, StateName, StateData, Debug), exit(Reason) @@ -705,7 +756,12 @@ get_msg(Msg) -> Msg. format_status(Opt, StatusData) -> [PDict, SysState, Parent, Debug, [Name, StateName, StateData, Mod, _Time]] = StatusData, - Header = lists:concat(["Status for state machine ", Name]), + NameTag = if is_pid(Name) -> + pid_to_list(Name); + is_atom(Name) -> + Name + end, + Header = lists:concat(["Status for state machine ", NameTag]), Log = sys:get_debug(log, Debug, []), Specfic = case erlang:function_exported(Mod, format_status, 2) of |