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' " | ||||
|                             "queries properties from node '~ts'", | ||||
|                             [node(), Node]], FromNode), | ||||
|                          StartTime = get_node_start_time( | ||||
|                                        Node, microsecond, FromNode), | ||||
|                          StartTime = get_node_start_time(Node, FromNode), | ||||
|                          IsReady = is_node_db_ready(Node, FromNode), | ||||
|                          NodeAndProps = {Node, Members, StartTime, IsReady}, | ||||
|                          NodesAndProps1 = [NodeAndProps | NodesAndProps], | ||||
|  | @ -666,9 +665,8 @@ query_node_props2([], NodesAndProps, _FromNode) -> | |||
|     ?assert(length(NodesAndProps1) =< length(nodes(hidden))), | ||||
|     NodesAndProps1. | ||||
| 
 | ||||
| -spec get_node_start_time(Node, Unit, FromNode) -> StartTime when | ||||
| -spec get_node_start_time(Node, FromNode) -> StartTime when | ||||
|       Node :: node(), | ||||
|       Unit :: erlang:time_unit(), | ||||
|       FromNode :: node(), | ||||
|       StartTime :: non_neg_integer(). | ||||
| %% @doc Returns the start time of the given `Node' in `Unit'. | ||||
|  | @ -689,15 +687,21 @@ query_node_props2([], NodesAndProps, _FromNode) -> | |||
| %% | ||||
| %% @private | ||||
| 
 | ||||
| get_node_start_time(Node, Unit, FromNode) -> | ||||
| get_node_start_time(Node, FromNode) -> | ||||
|     try | ||||
|         erpc_call(Node,rabbit_boot_state, get_start_time, [], FromNode) | ||||
|     catch | ||||
|         error:{exception, _, _} -> | ||||
|             NativeStartTime = erpc_call( | ||||
|                         Node, erlang, system_info, [start_time], FromNode), | ||||
|                                 Node, erlang, system_info, [start_time], | ||||
|                                 FromNode), | ||||
|             TimeOffset = erpc_call(Node, erlang, time_offset, [], FromNode), | ||||
|             SystemStartTime = NativeStartTime + TimeOffset, | ||||
|             StartTime = erpc_call( | ||||
|                           Node, erlang, convert_time_unit, | ||||
|                   [SystemStartTime, native, Unit], FromNode), | ||||
|     StartTime. | ||||
|                           [SystemStartTime, native, microsecond], FromNode), | ||||
|             StartTime | ||||
|     end. | ||||
| 
 | ||||
| -spec is_node_db_ready(Node, FromNode) -> IsReady when | ||||
|       Node :: node(), | ||||
|  |  | |||
|  | @ -17,9 +17,12 @@ | |||
|          set/1, | ||||
|          wait_for/2, | ||||
|          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_START_TIME, {?MODULE, start_time}). | ||||
| 
 | ||||
| -type boot_state() :: stopped | | ||||
|                       booting | | ||||
|  | @ -95,3 +98,56 @@ has_reached_and_is_active(TargetBootState) -> | |||
|             andalso | ||||
|             not has_reached(CurrentBootState, stopping) | ||||
|     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() -> | ||||
|     %% Indicate RabbitMQ is booting. | ||||
|     clear_stop_reason(), | ||||
|     rabbit_boot_state:record_start_time(), | ||||
|     rabbit_boot_state:set(booting), | ||||
| 
 | ||||
|     %% Configure dbg if requested. | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue