Merge pull request #13490 from rabbitmq/cache-start-time
rabbit_peer_discovery: Compute start time once
This commit is contained in:
		
						commit
						ac4261b208
					
				|  | @ -637,8 +637,7 @@ query_node_props2([{Node, Members} | Rest], NodesAndProps, FromNode) -> | ||||||
|                            ["Peer discovery: temporary hidden node '~ts' " |                            ["Peer discovery: temporary hidden node '~ts' " | ||||||
|                             "queries properties from node '~ts'", |                             "queries properties from node '~ts'", | ||||||
|                             [node(), Node]], FromNode), |                             [node(), Node]], FromNode), | ||||||
|                          StartTime = get_node_start_time( |                          StartTime = get_node_start_time(Node, FromNode), | ||||||
|                                        Node, microsecond, FromNode), |  | ||||||
|                          IsReady = is_node_db_ready(Node, FromNode), |                          IsReady = is_node_db_ready(Node, FromNode), | ||||||
|                          NodeAndProps = {Node, Members, StartTime, IsReady}, |                          NodeAndProps = {Node, Members, StartTime, IsReady}, | ||||||
|                          NodesAndProps1 = [NodeAndProps | NodesAndProps], |                          NodesAndProps1 = [NodeAndProps | NodesAndProps], | ||||||
|  | @ -666,9 +665,8 @@ query_node_props2([], NodesAndProps, _FromNode) -> | ||||||
|     ?assert(length(NodesAndProps1) =< length(nodes(hidden))), |     ?assert(length(NodesAndProps1) =< length(nodes(hidden))), | ||||||
|     NodesAndProps1. |     NodesAndProps1. | ||||||
| 
 | 
 | ||||||
| -spec get_node_start_time(Node, Unit, FromNode) -> StartTime when | -spec get_node_start_time(Node, FromNode) -> StartTime when | ||||||
|       Node :: node(), |       Node :: node(), | ||||||
|       Unit :: erlang:time_unit(), |  | ||||||
|       FromNode :: node(), |       FromNode :: node(), | ||||||
|       StartTime :: non_neg_integer(). |       StartTime :: non_neg_integer(). | ||||||
| %% @doc Returns the start time of the given `Node' in `Unit'. | %% @doc Returns the start time of the given `Node' in `Unit'. | ||||||
|  | @ -689,15 +687,21 @@ query_node_props2([], NodesAndProps, _FromNode) -> | ||||||
| %% | %% | ||||||
| %% @private | %% @private | ||||||
| 
 | 
 | ||||||
| get_node_start_time(Node, Unit, FromNode) -> | get_node_start_time(Node, FromNode) -> | ||||||
|     NativeStartTime = erpc_call( |     try | ||||||
|                         Node, erlang, system_info, [start_time], FromNode), |         erpc_call(Node,rabbit_boot_state, get_start_time, [], FromNode) | ||||||
|     TimeOffset = erpc_call(Node, erlang, time_offset, [], FromNode), |     catch | ||||||
|     SystemStartTime = NativeStartTime + TimeOffset, |         error:{exception, _, _} -> | ||||||
|     StartTime = erpc_call( |             NativeStartTime = erpc_call( | ||||||
|                   Node, erlang, convert_time_unit, |                                 Node, erlang, system_info, [start_time], | ||||||
|                   [SystemStartTime, native, Unit], FromNode), |                                 FromNode), | ||||||
|     StartTime. |             TimeOffset = erpc_call(Node, erlang, time_offset, [], FromNode), | ||||||
|  |             SystemStartTime = NativeStartTime + TimeOffset, | ||||||
|  |             StartTime = erpc_call( | ||||||
|  |                           Node, erlang, convert_time_unit, | ||||||
|  |                           [SystemStartTime, native, microsecond], FromNode), | ||||||
|  |             StartTime | ||||||
|  |     end. | ||||||
| 
 | 
 | ||||||
| -spec is_node_db_ready(Node, FromNode) -> IsReady when | -spec is_node_db_ready(Node, FromNode) -> IsReady when | ||||||
|       Node :: node(), |       Node :: node(), | ||||||
|  |  | ||||||
|  | @ -17,9 +17,12 @@ | ||||||
|          set/1, |          set/1, | ||||||
|          wait_for/2, |          wait_for/2, | ||||||
|          has_reached/1, |          has_reached/1, | ||||||
|          has_reached_and_is_active/1]). |          has_reached_and_is_active/1, | ||||||
|  |          get_start_time/0, | ||||||
|  |          record_start_time/0]). | ||||||
| 
 | 
 | ||||||
| -define(PT_KEY_BOOT_STATE, {?MODULE, boot_state}). | -define(PT_KEY_BOOT_STATE, {?MODULE, boot_state}). | ||||||
|  | -define(PT_KEY_START_TIME, {?MODULE, start_time}). | ||||||
| 
 | 
 | ||||||
| -type boot_state() :: stopped | | -type boot_state() :: stopped | | ||||||
|                       booting | |                       booting | | ||||||
|  | @ -95,3 +98,56 @@ has_reached_and_is_active(TargetBootState) -> | ||||||
|             andalso |             andalso | ||||||
|             not has_reached(CurrentBootState, stopping) |             not has_reached(CurrentBootState, stopping) | ||||||
|     end. |     end. | ||||||
|  | 
 | ||||||
|  | -spec get_start_time() -> StartTime when | ||||||
|  |       StartTime :: integer(). | ||||||
|  | %% @doc Returns the start time of the Erlang VM. | ||||||
|  | %% | ||||||
|  | %% This time was recorded by {@link record_start_time/0} as early as possible | ||||||
|  | %% and is immutable. | ||||||
|  | 
 | ||||||
|  | get_start_time() -> | ||||||
|  |     persistent_term:get(?PT_KEY_START_TIME). | ||||||
|  | 
 | ||||||
|  | -spec record_start_time() -> ok. | ||||||
|  | %% @doc Records the start time of the Erlang VM. | ||||||
|  | %% | ||||||
|  | %% The time is expressed in microseconds since Epoch. It can be compared to | ||||||
|  | %% other non-native times. This is used by the Peer Discovery subsystem to | ||||||
|  | %% sort nodes and select a seed node if the peer discovery backend did not | ||||||
|  | %% select one. | ||||||
|  | %% | ||||||
|  | %% This time is recorded once. Calling this function multiple times won't | ||||||
|  | %% overwrite the value. | ||||||
|  | 
 | ||||||
|  | record_start_time() -> | ||||||
|  |     Key = ?PT_KEY_START_TIME, | ||||||
|  |     try | ||||||
|  |         %% Check if the start time was recorded. | ||||||
|  |         _ = persistent_term:get(Key), | ||||||
|  |         ok | ||||||
|  |     catch | ||||||
|  |         error:badarg -> | ||||||
|  |             %% The start time was not recorded yet. Acquire a lock and check | ||||||
|  |             %% again in case another process got the lock first and recorded | ||||||
|  |             %% the start time. | ||||||
|  |             Node = node(), | ||||||
|  |             LockId = {?PT_KEY_START_TIME, self()}, | ||||||
|  |             true = global:set_lock(LockId, [Node]), | ||||||
|  |             try | ||||||
|  |                 _ = persistent_term:get(Key), | ||||||
|  |                 ok | ||||||
|  |             catch | ||||||
|  |                 error:badarg -> | ||||||
|  |                     %% We are really the first to get the lock and we can | ||||||
|  |                     %% record the start time. | ||||||
|  |                     NativeStartTime = erlang:system_info(start_time), | ||||||
|  |                     TimeOffset = erlang:time_offset(), | ||||||
|  |                     SystemStartTime = NativeStartTime + TimeOffset, | ||||||
|  |                     StartTime = erlang:convert_time_unit( | ||||||
|  |                                   SystemStartTime, native, microsecond), | ||||||
|  |                     persistent_term:put(Key, StartTime) | ||||||
|  |             after | ||||||
|  |                 global:del_lock(LockId, [Node]) | ||||||
|  |             end | ||||||
|  |     end. | ||||||
|  |  | ||||||
|  | @ -48,6 +48,7 @@ run_prelaunch_first_phase() -> | ||||||
| do_run() -> | do_run() -> | ||||||
|     %% Indicate RabbitMQ is booting. |     %% Indicate RabbitMQ is booting. | ||||||
|     clear_stop_reason(), |     clear_stop_reason(), | ||||||
|  |     rabbit_boot_state:record_start_time(), | ||||||
|     rabbit_boot_state:set(booting), |     rabbit_boot_state:set(booting), | ||||||
| 
 | 
 | ||||||
|     %% Configure dbg if requested. |     %% Configure dbg if requested. | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue