1%% This Source Code Form is subject to the terms of the Mozilla Public 2%% License, v. 2.0. If a copy of the MPL was not distributed with this 3%% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4%% 5%% Copyright (c) 2007-2021 VMware, Inc. or its affiliates. All rights reserved. 6%% 7 8-module(background_gc). 9 10-behaviour(gen_server2). 11 12-export([start_link/0, run/0]). 13-export([gc/0]). %% For run_interval only 14 15-export([init/1, handle_call/3, handle_cast/2, handle_info/2, 16 terminate/2, code_change/3]). 17 18-define(MAX_RATIO, 0.01). 19-define(MAX_INTERVAL, 240000). 20 21-record(state, {last_interval}). 22 23%%---------------------------------------------------------------------------- 24 25-spec start_link() -> {'ok', pid()} | {'error', any()}. 26 27start_link() -> gen_server2:start_link({local, ?MODULE}, ?MODULE, [], 28 [{timeout, infinity}]). 29 30-spec run() -> 'ok'. 31 32run() -> gen_server2:cast(?MODULE, run). 33 34%%---------------------------------------------------------------------------- 35 36init([]) -> 37 {ok, IdealInterval} = application:get_env(rabbit, background_gc_target_interval), 38 {ok, interval_gc(#state{last_interval = IdealInterval})}. 39 40handle_call(Msg, _From, State) -> 41 {stop, {unexpected_call, Msg}, {unexpected_call, Msg}, State}. 42 43handle_cast(run, State) -> gc(), {noreply, State}; 44 45handle_cast(Msg, State) -> {stop, {unexpected_cast, Msg}, State}. 46 47handle_info(run, State) -> {noreply, interval_gc(State)}; 48 49handle_info(Msg, State) -> {stop, {unexpected_info, Msg}, State}. 50 51code_change(_OldVsn, State, _Extra) -> {ok, State}. 52 53terminate(_Reason, State) -> State. 54 55%%---------------------------------------------------------------------------- 56 57interval_gc(State = #state{last_interval = LastInterval}) -> 58 {ok, IdealInterval} = application:get_env(rabbit, background_gc_target_interval), 59 {ok, Interval} = rabbit_misc:interval_operation( 60 {?MODULE, gc, []}, 61 ?MAX_RATIO, ?MAX_INTERVAL, IdealInterval, LastInterval), 62 erlang:send_after(Interval, self(), run), 63 State#state{last_interval = Interval}. 64 65-spec gc() -> 'ok'. 66 67gc() -> 68 Enabled = rabbit_misc:get_env(rabbit, background_gc_enabled, false), 69 case Enabled of 70 true -> 71 [garbage_collect(P) || P <- processes(), 72 {status, waiting} == process_info(P, status)], 73 %% since we will never be waiting... 74 garbage_collect(); 75 false -> 76 ok 77 end, 78 ok. 79