⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 overload.erl

📁 OTP是开放电信平台的简称
💻 ERL
字号:
%% ``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%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %%     $Id$%%-module(overload). -export([start_link/0, request/0, set_config_data/2,	 get_overload_info/0]).-export([init/1, handle_call/3, handle_info/2, terminate/2,	 format_status/2]).%%%-----------------------------------------------------------------%%% This is a rewrite of overload from BS.3, by Peter H鰃feldt.%%%%%% DESCRIPTION%%%%%% This module implements a server process that keeps record of the%%% intensity of calls of the request/0 function, and answers accept or%%% reject depending on if the current average intensity is not greater %%% than a specified maximum intensity.%%%%%% The intensity i is calculated according to the formula:%%%    i(n) = exp(-K*(T(n) - T(n-1)))*i(n-1) + Kappa%%% where i(n) is the intensity at event n, Kappa is a constant, and%%% T(n) is the time at event n.%%%%%% The constant Kappa can be thought of as 1 / T, where T is the time %%% constant. Kappa is externally referred to as Weight.%%%  %%% We keep track of two intensities: the total call intensity and the %%% intensity of accepted calls.%%%-----------------------------------------------------------------%%% TODO%%%%%% 3. Hysteresis.%%%%%%------------------------------------------------------------------record(state, {total = 0, accept = 0, max, prev_t = get_now(),		kappa, call_counts = {0, 0}, alarm = clear}).-define(clear_timeout, 30000).  start_link() ->    gen_server:start_link({local, overload}, overload, [], []).init([]) ->    process_flag(priority, high),    MaxIntensity = fetch_config_data(overload_max_intensity),    Kappa = fetch_config_data(overload_weight),    {ok, #state{max = MaxIntensity, kappa = Kappa}}.  %%-----------------------------------------------------------------%% Func: request/0%% Purpose: This is a request to proceed, e.g. a request to%%          establish a call.%% Returns: accept | reject%%-----------------------------------------------------------------request() -> gen_server:call(overload, request).  %%-----------------------------------------------------------------%% Func: set_config_data/2%% Purpose: Set configuration data, and reset intensities.%% Arguments: MaxIntensity (real > 0), Weight (real > 0).%% Returns: ok | {error, What}%% This function is for debugging purposes and is therefore not%% documented at all.%%-----------------------------------------------------------------set_config_data(MaxIntensity, Weight) ->    gen_server:call(overload, {set_config_data, MaxIntensity, Weight}).%%-----------------------------------------------------------------%% Func: get_overload_info/0%% Returns: A list of tagged items: TotalIntensity, AcceptIntensity,%%          MaxIntensity, Weight, TotalRequests, AcceptedRequests.%%-----------------------------------------------------------------get_overload_info() -> gen_server:call(overload, get_overload_info).%%%-----------------------------------------------------------------%%% Callback functions from gen_server%%%-----------------------------------------------------------------handle_call(request, _From, State) ->    #state{total = TI, accept = AI, kappa = Kappa, prev_t = PrevT,	  alarm = Alarm} = State,    {TR, AR} = State#state.call_counts,    T = get_now(),    CurI = new_intensity(AI, T, PrevT, Kappa),    NewTI  = new_intensity(TI, T, PrevT, Kappa) + Kappa,    if 	CurI =< State#state.max ->	    %% Hysteresis: If alarm is set, and current intensity has	    %% fallen below 75% of max intensity, clear alarm.	    NewAlarm = if			   CurI =< 0.75*State#state.max ->			       clear_alarm(Alarm);			   true ->			       Alarm		       end,	    {reply, accept, State#state{call_counts = {TR+1, AR+1}, 					prev_t = T, total = NewTI, 					accept = CurI + Kappa, 				        alarm = NewAlarm},	     ?clear_timeout};        true ->	    %% Set alarm if not already set.	    NewAlarm = set_alarm(Alarm),	    {reply, reject,	     State#state{call_counts = {TR+1, AR}, prev_t = T,			 total = NewTI, accept = CurI,				       alarm = NewAlarm},	    ?clear_timeout}    end;handle_call({set_config_data, MaxIntensity, Weight}, _From, _State) ->    {reply, ok, #state{max = MaxIntensity, kappa = Weight},     ?clear_timeout};handle_call(get_overload_info, _From, State) ->    #state{max = MI, total = TI, accept = AI, kappa = Kappa,	   prev_t = PrevT, call_counts = {TR, AR}} = State,    T = get_now(),    CurI = new_intensity(AI, T, PrevT, Kappa),    NewTI  = new_intensity(TI, T, PrevT, Kappa),    Reply = [{total_intensity, NewTI}, {accept_intensity, CurI}, 	     {max_intensity, MI}, {weight, Kappa},	     {total_requests, TR}, {accepted_requests, AR}],    {reply, Reply, State#state{total = NewTI, accept = CurI},     ?clear_timeout}.handle_info(timeout, State) ->    #state{total = TI, accept = AI, kappa = Kappa, prev_t = PrevT,	  alarm = Alarm} = State,    T = get_now(),    CurI = new_intensity(AI, T, PrevT, Kappa),    NewTI  = new_intensity(TI, T, PrevT, Kappa),    if 	CurI < 0.75* State#state.max ->	    NewAlarm = clear_alarm(Alarm),	    {noreply, State#state{total = NewTI, accept = CurI, 				  alarm = NewAlarm}};	    	true ->	    {noreply, State#state{total = NewTI, accept = CurI},	     ?clear_timeout}    end;handle_info(_, State) ->    {noreply, State, ?clear_timeout}.terminate(_Reason, _State) ->    ok.%%-----------------------------------------------------------------%% Internal functions%%-----------------------------------------------------------------fetch_config_data(Tag) ->    case application:get_env(sasl, Tag) of	{ok, Value} -> Value;	_ -> fetch_default_data(Tag)    end.  fetch_default_data(overload_max_intensity) -> 0.8;fetch_default_data(overload_weight) -> 0.1.set_alarm(clear) ->    alarm_handler:set_alarm({overload, []}),    set;set_alarm(Alarm) ->    Alarm.clear_alarm(set) ->    alarm_handler:clear_alarm(overload),    clear;clear_alarm(Alarm) ->    Alarm.%%-----------------------------------------------------------------%% The catch protects against floating-point exception.%%new_intensity(I, T, PrevT, K) ->    Diff = sub(T, PrevT)/1000,    case catch (I*math:exp(-K*Diff)) of	{'EXIT', _} ->				% Assume zero.	    0.0;	Res ->	    Res    end.%% Mask equal to 2^27 - 1, used below.-define(mask27, 16#7ffffff).%% Returns number of milliseconds in the range [0, 2^27 - 1]. Must have%% this since statistics(wall_clock) wraps. Having 2^27 -1 as the max%% assures that we always get non-negative integers. 2^27 milliseconds %% are approx. 37.28 hours.get_now() ->     element(1, statistics(wall_clock)) band ?mask27.%% Returns (X - Y) mod 2^27 (which is in the range [0, 2^27 - 1]).sub(X, Y) ->    (X + (bnot Y) + 1) band ?mask27.format_status(Opt, [PDict, #state{max = MI, total = TI, accept = AI,				  kappa = K,				  call_counts = {TR, AR}}]) ->    [{data, [{"Total Intensity", TI},	     {"Accept Intensity", AI}, 	     {"Max Intensity", MI},	     {"Weight", K},	     {"Total requests", TR},	     {"Accepted requests", AR}]} |     misc_supp:format_pdict(Opt, PDict, [])].     

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -