[연습] 간단한 이름 서비스

9057 단어 서비스
gen 사용서버의 간단한 이름 서비스
 
보주는 간단해. 시동gen서버 local 서비스 이름을 등록하면 인용하기 편합니다
 
그리고 사전을 State에 넣고 조회 등 서비스를 제공합니다.
 
코드는 다음과 같습니다.
%% @author cc fairjm
%% @doc @todo Add description to naming.


-module(naming).
-behaviour(gen_server).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

%% ====================================================================
%% API functions
%% ====================================================================
-export([start/0,stop/0,insert/2,remove/1,lookup/1]).
-define(SERVER,?MODULE).


%% ====================================================================
%% Behavioural functions 
%% ====================================================================
-record(state, {dic}).



start() ->
	gen_server:start_link({local,?SERVER}, ?MODULE, [], []).


insert(Key,Value) ->
	gen_server:cast(?SERVER,{insert,{Key,Value}})
.

remove(Key) ->
	gen_server:cast(?SERVER, {remove,Key}).

lookup(Key)->
	gen_server:call(?SERVER, {lookup,Key}).

stop() ->
	gen_server:cast(?SERVER, stop).

%% init/1
%% ====================================================================
%% @doc <a href="http://www.erlang.org/doc/man/gen_server.html#Module:init-1">gen_server:init/1</a>
-spec init(Args :: term()) -> Result when
	Result :: {ok, State}
			| {ok, State, Timeout}
			| {ok, State, hibernate}
			| {stop, Reason :: term()}
			| ignore,
	State :: term(),
	Timeout :: non_neg_integer() | infinity.
%% ====================================================================
init([]) ->
    {ok, #state{dic=dict:new()}}.


%% handle_call/3
%% ====================================================================
%% @doc <a href="http://www.erlang.org/doc/man/gen_server.html#Module:handle_call-3">gen_server:handle_call/3</a>
-spec handle_call(Request :: term(), From :: {pid(), Tag :: term()}, State :: term()) -> Result when
	Result :: {reply, Reply, NewState}
			| {reply, Reply, NewState, Timeout}
			| {reply, Reply, NewState, hibernate}
			| {noreply, NewState}
			| {noreply, NewState, Timeout}
			| {noreply, NewState, hibernate}
			| {stop, Reason, Reply, NewState}
			| {stop, Reason, NewState},
	Reply :: term(),
	NewState :: term(),
	Timeout :: non_neg_integer() | infinity,
	Reason :: term().
%% ====================================================================
handle_call({lookup,Key}, _From, State) ->
	#state{dic=Dic}=State,
	case dict:find(Key, Dic) of
     {ok,Value}->{reply, {ok,Value}, State};
	          _->{reply,{not_found},State}
	end.


%% handle_cast/2
%% ====================================================================
%% @doc <a href="http://www.erlang.org/doc/man/gen_server.html#Module:handle_cast-2">gen_server:handle_cast/2</a>
-spec handle_cast(Request :: term(), State :: term()) -> Result when
	Result :: {noreply, NewState}
			| {noreply, NewState, Timeout}
			| {noreply, NewState, hibernate}
			| {stop, Reason :: term(), NewState},
	NewState :: term(),
	Timeout :: non_neg_integer() | infinity.
%% ====================================================================
handle_cast({insert,{Key,Value}}, State) ->
	#state{dic=Dic}=State,
    {noreply, State#state{dic=dict:append(Key, Value,Dic )}};


handle_cast({remove,Key}, State) ->
	#state{dic=Dic}=State,
    {noreply, State#state{dic=dict:erase(Key, Dic)}};

handle_cast(stop, State) ->
	{stop,{normal},State}.

%% handle_info/2
%% ====================================================================
%% @doc <a href="http://www.erlang.org/doc/man/gen_server.html#Module:handle_info-2">gen_server:handle_info/2</a>
-spec handle_info(Info :: timeout | term(), State :: term()) -> Result when
	Result :: {noreply, NewState}
			| {noreply, NewState, Timeout}
			| {noreply, NewState, hibernate}
			| {stop, Reason :: term(), NewState},
	NewState :: term(),
	Timeout :: non_neg_integer() | infinity.
%% ====================================================================
handle_info(_Info, State) ->
    {noreply, State}.


%% terminate/2
%% ====================================================================
%% @doc <a href="http://www.erlang.org/doc/man/gen_server.html#Module:terminate-2">gen_server:terminate/2</a>
-spec terminate(Reason, State :: term()) -> Any :: term() when
	Reason :: normal
			| shutdown
			| {shutdown, term()}
			| term().
%% ====================================================================
terminate(_Reason, _State) ->
    ok.


%% code_change/3
%% ====================================================================
%% @doc <a href="http://www.erlang.org/doc/man/gen_server.html#Module:code_change-3">gen_server:code_change/3</a>
-spec code_change(OldVsn, State :: term(), Extra :: term()) -> Result when
	Result :: {ok, NewState :: term()} | {error, Reason :: term()},
	OldVsn :: Vsn | {down, Vsn},
	Vsn :: term().
%% ====================================================================
code_change(_OldVsn, State, _Extra) ->
    {ok, State}.


%% ====================================================================
%% Internal functions
%% ====================================================================


사실 코드를 조금만 쓰면 돼요. 어랑의 코드가 간단명료해요.
 
호출은 다음과 같습니다.
(cc@dell-PC)8> c("naming").
{ok,naming}
(cc@dell-PC)9> naming:stop().
ok
(cc@dell-PC)10> naming:lookup(cc).
** exception exit: {noproc,{gen_server,call,[naming,{lookup,cc}]}}
     in function  gen_server:call/2 (gen_server.erl, line 180)
(cc@dell-PC)11> c("naming").
{ok,naming}
(cc@dell-PC)12> naming:start().
{ok,<0.68.0>}
(cc@dell-PC)13> naming:insert(cc,"hello").
ok
(cc@dell-PC)14> naming:lookup(cc).
{ok,["hello"]}
(cc@dell-PC)15> naming:remove(cc).
ok
(cc@dell-PC)16> naming:lookup(cc).
{not_found}
(cc@dell-PC)17> naming:stop().
** exception exit: {normal}
(cc@dell-PC)18>
=ERROR REPORT==== 12-Aug-2013::02:27:17 ===
** Generic server naming terminating
** Last message in was {'$gen_cast',stop}
** When Server state == {state,{dict,0,16,16,8,80,48,
                                     {[],[],[],[],[],[],[],[],[],[],[],[],[],
                                      [],[],[]},
                                     {{[],[],[],[],[],[],[],[],[],[],[],[],[],
                                       [],[],[]}}}}
** Reason for termination ==
** {normal}
(cc@dell-PC)18> naming:lookup(cc).
** exception exit: {noproc,{gen_server,call,[naming,{lookup,cc}]}}
     in function  gen_server:call/2 (gen_server.erl, line 180)

원격에서도 rpc를 호출할 수 있습니다.
(cc02@dell-PC)1> net_adm:ping('cc@dell-PC').
pong
(cc02@dell-PC)2> rpc:call('cc@dell-PC',naming,lookup,cc).
{badrpc,{'EXIT',{badarg,[{erlang,apply,
                                 [naming,lookup,cc],
                                 []},
                         {rpc,'-handle_call_call/6-fun-0-',5,
                              [{file,"rpc.erl"},{line,205}]}]}}}
(cc02@dell-PC)3> rpc:call('cc@dell-PC',naming,lookup,[cc]).
{badrpc,{'EXIT',{noproc,{gen_server,call,
                                    [naming,{lookup,cc}]}}}}
(cc02@dell-PC)4> rpc:call('cc@dell-PC',naming,lookup,[cc]).
{ok,["hello","hello2"]}
(cc02@dell-PC)5> rpc:call('cc@dell-PC',naming,lookup,[cc]).
{ok,["hello","hello2"]}
(cc02@dell-PC)6> rpc:call('cc@dell-PC',naming,lookup,[cc]).
{ok,["hello","hello2"]}
(cc02@dell-PC)7> rpc:call('cc@dell-PC',naming,lookup,[cc]).
{not_found}
(cc02@dell-PC)8> rpc:call('cc@dell-PC',naming,lookup,[cc]).
{badrpc,{'EXIT',{noproc,{gen_server,call,
                                    [naming,{lookup,cc}]}}}}
(cc02@dell-PC)9>

좋은 웹페이지 즐겨찾기