%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% 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 online 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. %% %% %CopyrightEnd% %% -module(os_mon_sysinfo). -behaviour(gen_server). %% API -export([start_link/0]). -export([get_disk_info/0, get_disk_info/1, get_mem_info/0]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -define(DISK_INFO, $d). -define(MEM_INFO, $m). -define(OK, $o). -record(state, {port}). %%---------------------------------------------------------------------- %% API %%---------------------------------------------------------------------- start_link() -> gen_server:start_link({local,os_mon_sysinfo}, os_mon_sysinfo, [],[]). get_disk_info() -> gen_server:call(os_mon_sysinfo, get_disk_info). get_disk_info(DriveRoot) -> gen_server:call(os_mon_sysinfo, {get_disk_info,DriveRoot}). get_mem_info() -> gen_server:call(os_mon_sysinfo, get_mem_info). %%---------------------------------------------------------------------- %% gen_server callbacks %%---------------------------------------------------------------------- init([]) -> process_flag(trap_exit, true), process_flag(priority, low), Port = case os:type() of {win32, _OSname} -> start_portprogram(); OS -> exit({unsupported_os, OS}) end, {ok, #state{port=Port}}. handle_call(get_disk_info, _From, State) -> {reply, get_disk_info1(State#state.port), State}; handle_call({get_disk_info,RootList}, _From, State) -> {reply, get_disk_info1(State#state.port,RootList), State}; handle_call(get_mem_info, _From, State) -> {reply, get_mem_info1(State#state.port), State}. handle_cast(_Msg, State) -> {noreply, State}. handle_info({'EXIT', _Port, Reason}, State) -> {stop, {port_died, Reason}, State#state{port=not_used}}; handle_info(_Info, State) -> {noreply, State}. terminate(_Reason, State) -> case State#state.port of not_used -> ok; Port -> port_close(Port) end, ok. %% os_mon-2.0 %% For live downgrade to/upgrade from os_mon-1.8[.1] code_change(Vsn, PrevState, "1.8") -> case Vsn of %% Downgrade from this version {down, _Vsn} -> process_flag(trap_exit, false); %% Upgrade to this version _Vsn -> process_flag(trap_exit, true) end, {ok, PrevState}; code_change(_OldVsn, State, _Extra) -> {ok, State}. %%---------------------------------------------------------------------- %% Internal functions %%---------------------------------------------------------------------- start_portprogram() -> Port = os_mon:open_port("win32sysinfo.exe", [{packet,1}]), receive {Port, {data, [?OK]}} -> Port; {Port, {data, Data}} -> exit({port_error, Data}); {'EXIT', Port, Reason} -> exit({port_died, Reason}) after 5000 -> exit({port_error, timeout}) end. get_disk_info1(Port) -> Port ! {self(),{command,[?DISK_INFO]}}, get_data(Port,[]). get_disk_info1(Port,PathList) -> Port ! {self(),{command,[?DISK_INFO|[P++[0]||P <- PathList]]}}, get_data(Port,[]). get_mem_info1(Port) -> Port ! {self(),{command,[?MEM_INFO]}}, get_data(Port,[]). get_data(Port, Sofar) -> receive {Port, {data, [?OK]}} -> lists:reverse(Sofar); {Port, {data, Bytes}} -> get_data(Port, [Bytes|Sofar]); {'EXIT', Port, Reason} -> exit({port_died, Reason}) after 5000 -> lists:reverse(Sofar) end.