memsup.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,003 行 · 第 1/3 页

ERL
1,003
字号
%% ``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(memsup).-behaviour(gen_server).%% API-export([start_link/0]). % for supervisor-export([get_memory_data/0, get_system_memory_data/0,	 get_check_interval/0, set_check_interval/1,	 get_procmem_high_watermark/0, set_procmem_high_watermark/1,	 get_sysmem_high_watermark/0, set_sysmem_high_watermark/1,	 get_helper_timeout/0, set_helper_timeout/1]).-export([dummy_reply/1, param_type/2, param_default/1]).%% gen_server callbacks-export([init/1, handle_call/3, handle_cast/2, handle_info/2,	 terminate/2, code_change/3]).%% Other exports-export([format_status/2]).-include("memsup.hrl").-record(state,	{os,                  % {OSfamily,OSname} | OSfamily	 port_mode,           % bool()	 mem_usage,           % undefined | {Alloc, Total}	 worst_mem_user,      % undefined | {Pid, Alloc}	 sys_only,            % bool()  memsup_system_only	 timeout,             % int()   memory_check_interval, ms	 helper_timeout,      % int()   memsup_helper_timeout, ms	 sys_mem_watermark,   % float() system_memory_high_watermark, %	 proc_mem_watermark,  % float() process_memory_high_watermark, %	 pid,                 % undefined | pid()	 wd_timer,            % undefined | TimerRef	 ext_wd_timer,        % undefined | TimerRef	 pending = [],        % [reg | {reg,From} | {ext,From}]	 ext_pending = []     % [{ext,From}]	}).%%----------------------------------------------------------------------%% API%%----------------------------------------------------------------------start_link() ->    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).get_memory_data() ->    os_mon:call(memsup, get_memory_data, infinity).get_system_memory_data() ->    os_mon:call(memsup, get_system_memory_data, infinity).get_check_interval() ->    os_mon:call(memsup, get_check_interval, infinity).set_check_interval(Minutes) ->    case param_type(memory_check_interval, Minutes) of	true ->	    MS = minutes_to_ms(Minutes), % for backwards compatibility	    os_mon:call(memsup, {set_check_interval, MS}, infinity);	false ->	    erlang:error(badarg)    end.get_procmem_high_watermark() ->    os_mon:call(memsup, get_procmem_high_watermark, infinity).set_procmem_high_watermark(Float) ->    case param_type(process_memory_high_watermark, Float) of	true ->	    os_mon:call(memsup, {set_procmem_high_watermark, Float},			infinity);	false ->	    erlang:error(badarg)    end.get_sysmem_high_watermark() ->    os_mon:call(memsup, get_sysmem_high_watermark, infinity).set_sysmem_high_watermark(Float) ->    case param_type(system_memory_high_watermark, Float) of	true ->	    os_mon:call(memsup, {set_sysmem_high_watermark, Float},			infinity);	false ->	    erlang:error(badarg)    end.get_helper_timeout() ->    os_mon:call(memsup, get_helper_timeout, infinity).set_helper_timeout(Seconds) ->    case param_type(memsup_helper_timeout, Seconds) of	true ->	    os_mon:call(memsup, {set_helper_timeout, Seconds});	false ->	    erlang:error(badarg)    end.dummy_reply(get_memory_data) ->    dummy_reply(get_memory_data,		os_mon:get_env(memsup, memsup_system_only));dummy_reply(get_system_memory_data) ->    [];dummy_reply(get_check_interval) ->    minutes_to_ms(os_mon:get_env(memsup, memory_check_interval));dummy_reply({set_check_interval, _}) ->    ok;dummy_reply(get_procmem_high_watermark) ->    trunc(100 * os_mon:get_env(memsup, process_memory_high_watermark));dummy_reply({set_procmem_high_watermark, _}) ->    ok;dummy_reply(get_sysmem_high_watermark) ->    trunc(100 * os_mon:get_env(memsup, system_memory_high_watermark));dummy_reply({set_sysmem_high_watermark, _}) ->    ok;dummy_reply(get_helper_timeout) ->    os_mon:get_env(memsup, memsup_helper_timeout);dummy_reply({set_helper_timeout, _}) ->    ok.dummy_reply(get_memory_data, true) ->    {0,0,undefined};dummy_reply(get_memory_data, false) ->    {0,0,{self(),0}}.param_type(memsup_system_only, Val) when Val==true; Val==false -> true;param_type(memory_check_interval, Val) when is_integer(Val),                                            Val>0 -> true;param_type(memsup_helper_timeout, Val) when is_integer(Val),                                            Val>0 -> true;param_type(system_memory_high_watermark, Val) when is_number(Val),						   0=<Val,						   Val=<1 -> true;param_type(process_memory_high_watermark, Val) when is_number(Val),						    0=<Val,						    Val=<1 -> true;param_type(_Param, _Val) -> false.param_default(memsup_system_only) -> false;param_default(memory_check_interval) -> 1;param_default(memsup_helper_timeout) -> 30;param_default(system_memory_high_watermark) -> 0.80;param_default(process_memory_high_watermark) -> 0.05.%%----------------------------------------------------------------------%% gen_server callbacks%%----------------------------------------------------------------------init([]) ->    process_flag(trap_exit, true),    process_flag(priority, low),    OS = os:type(),    PortMode = case OS of		   {unix, darwin} -> false;		   {unix, freebsd} -> false;		   {unix, linux} -> false;		   {unix, openbsd} -> true;		   {unix, irix64} -> true;		   {unix, irix} -> true;		   {unix, sunos} -> true;		   {win32, _OSname} -> false;		   vxworks -> true;		   _ ->		       exit({unsupported_os, OS})	       end,    Pid = if	      PortMode ->		  spawn_link(fun() -> port_init() end);	      not PortMode ->		  undefined	  end,    %% Read the values of some configuration parameters    SysOnly = os_mon:get_env(memsup, memsup_system_only),    Timeout = os_mon:get_env(memsup, memory_check_interval),    HelperTimeout = os_mon:get_env(memsup, memsup_helper_timeout),    SysMem = os_mon:get_env(memsup, system_memory_high_watermark),    ProcMem = os_mon:get_env(memsup, process_memory_high_watermark),    %% Initiate first data collection    self() ! time_to_collect,    {ok, #state{os=OS, port_mode=PortMode,		sys_only           = SysOnly,		timeout            = minutes_to_ms(Timeout),		helper_timeout     = sec_to_ms(HelperTimeout),		sys_mem_watermark  = SysMem,		proc_mem_watermark = ProcMem,		pid=Pid}}.handle_call(get_memory_data, From, State) ->    %% Return result of latest memory check    case State#state.mem_usage of	{Alloc, Total} ->	    Worst = State#state.worst_mem_user,	    {reply, {Total, Alloc, Worst}, State};		%% Special case: get_memory_data called before any memory data	%% has been collected	undefined ->	    case State#state.wd_timer of		undefined ->		    WDTimer = erlang:send_after(State#state.timeout,						self(),						reg_collection_timeout),		    Pending = [{reg,From}],		    if			State#state.port_mode ->			    State#state.pid ! {self(), collect_sys},			    {noreply, State#state{wd_timer=WDTimer,						  pending=Pending}};			true ->			    OS = State#state.os,			    Self = self(),			    Pid = spawn_link(fun() ->						     MU = get_memory_usage(OS),						     Self ! {collected_sys,MU}					     end),			    {noreply, State#state{pid=Pid,						  wd_timer=WDTimer,						  pending=Pending}}		    end;		_TimerRef ->		    Pending = [{reg,From} | State#state.pending],		    {noreply, State#state{pending=Pending}}	    end    end;handle_call(get_system_memory_data,From,#state{port_mode=true}=State) ->    %% When using a port, the extensive memory collection is slightly    %% different than a regular one    case State#state.ext_wd_timer of	undefined ->	    WDTimer = erlang:send_after(State#state.helper_timeout,					self(),					ext_collection_timeout),	    State#state.pid ! {self(), collect_ext_sys},	    {noreply, State#state{ext_wd_timer=WDTimer,				  ext_pending=[{ext,From}]}};	_TimerRef ->	    Pending = [{ext,From} | State#state.ext_pending],	    {noreply, State#state{ext_pending=Pending}}    end;handle_call(get_system_memory_data, From, State) ->    %% When not using a port, the regular memory collection is used    %% for extensive memory data as well    case State#state.wd_timer of	undefined ->	    WDTimer = erlang:send_after(State#state.helper_timeout,					self(),					reg_collection_timeout),	    OS = State#state.os,	    Self = self(),	    Pid = spawn_link(fun() ->				     MemUsage = get_memory_usage(OS),				     Self ! {collected_sys, MemUsage}			     end),	    {noreply, State#state{pid=Pid, wd_timer=WDTimer,				  pending=[{ext,From}]}};	_TimerRef ->	    Pending = [{ext,From} | State#state.pending],	    {noreply, State#state{pending=Pending}}    end;handle_call(get_check_interval, _From, State) ->    {reply, State#state.timeout, State};handle_call({set_check_interval, MS}, _From, State) ->    {reply, ok, State#state{timeout=MS}};handle_call(get_procmem_high_watermark, _From, State) ->    {reply, trunc(100 * State#state.proc_mem_watermark), State};handle_call({set_procmem_high_watermark, Float}, _From, State) ->    {reply, ok, State#state{proc_mem_watermark=Float}};handle_call(get_sysmem_high_watermark, _From, State) ->    {reply, trunc(100 * State#state.sys_mem_watermark), State};handle_call({set_sysmem_high_watermark, Float}, _From, State) ->    {reply, ok, State#state{sys_mem_watermark=Float}};handle_call(get_helper_timeout, _From, State) ->    {reply, ms_to_sec(State#state.helper_timeout), State};handle_call({set_helper_timeout, Seconds}, _From, State) ->    {reply, ok, State#state{helper_timeout=sec_to_ms(Seconds)}};%% The following are only for test purposes (whitebox testing).handle_call({set_sys_hw, HW}, _From, State) ->    {reply, ok, State#state{sys_mem_watermark=HW}};handle_call({set_pid_hw, HW}, _From, State) ->    {reply, ok, State#state{proc_mem_watermark=HW}};handle_call(get_state, _From, State) ->    {reply, State, State}.handle_cast(_Msg, State) ->    {noreply, State}.%% It's time to check memoryhandle_info(time_to_collect, State) ->    case State#state.wd_timer of	undefined ->	    WDTimer = erlang:send_after(State#state.helper_timeout,					self(),					reg_collection_timeout),	    if		State#state.port_mode ->		    State#state.pid ! {self(), collect_sys},		    {noreply, State#state{wd_timer=WDTimer,					  pending=[reg]}};		true ->		    OS = State#state.os,		    Self = self(),		    Pid = spawn_link(fun() ->					     MU = get_memory_usage(OS),					     Self ! {collected_sys,MU}				     end),		    {noreply, State#state{pid=Pid, wd_timer=WDTimer,					  pending=[reg]}}	    end;

⌨️ 快捷键说明

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