<source id="4vppl"><ins id="4vppl"></ins></source>
<u id="4vppl"><sub id="4vppl"><label id="4vppl"></label></sub></u>
<object id="4vppl"></object>
  • <u id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></u>

    <object id="4vppl"></object>
    <b id="4vppl"><sub id="4vppl"><tr id="4vppl"></tr></sub></b>

      <i id="4vppl"><thead id="4vppl"></thead></i>

      <thead id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></thead>

      當(dāng)前位置:首頁(yè) > 網(wǎng)站舊欄目 > 學(xué)習(xí)園地 > 設(shè)計(jì)軟件教程 > gen_server tasting 之超簡(jiǎn)單名稱服務(wù)

      gen_server tasting 之超簡(jiǎn)單名稱服務(wù)
      2010-01-13 23:16:59  作者:  來(lái)源:
           年假不能白休,時(shí)間不能浪費(fèi),看了 erlang 程序設(shè)計(jì)的 gen_server 章節(jié),為了更好的理解、掌握于是上手寫一個(gè)名稱(鍵值)服務(wù)器。這個(gè) lzy_name_svc 服務(wù)器是基于 otp gen_server 寫成的,在底層鍵值被保存在了 erlang 的進(jìn)程字典里,并且用于存儲(chǔ)字典的進(jìn)程是可以替換的,可以通過(guò) lzy_name_svc:start/1 啟動(dòng)服務(wù)時(shí)指定,缺省情況保存在“當(dāng)前” erlang 進(jìn)程中。閑話少敘,代碼貼上。

       

      Erlang代碼 復(fù)制代碼
      1. -module(lzy_name_svc).   
      2.   
      3. -behaviour(gen_server).   
      4.   
      5. -export([init/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).   
      6. -export([start/0, start/1, stop/0, save/2, load/1, load_all/0, remove/1, remove_all/0]).   
      7.   
      8. %% Interface functions.   
      9.   
      10. start() ->   
      11.     gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).   
      12.   
      13. start(Args) ->   
      14.     gen_server:start_link({local, ?MODULE}, ?MODULE, Args, []).   
      15.   
      16. stop() ->   
      17.     gen_server:call(?MODULE, stop).   
      18.   
      19.   
      20. %% @spec save(Key, Value) -> OldValue.   
      21. save(Key, Value) ->   
      22.     gen_server:call(?MODULE, {save, Key, Value}).   
      23.   
      24. %% @spec load(Key) -> Value.   
      25. load(Key) ->   
      26.     gen_server:call(?MODULE, {load, Key}).   
      27.   
      28. %% @spec load_all() -> [{Key, Value}].   
      29. load_all() ->   
      30.     gen_server:call(?MODULE, {load_all}).   
      31.   
      32. %% @spec remove(Key) -> Value.   
      33. remove(Key) ->   
      34.     gen_server:call(?MODULE, {remove, Key}).   
      35.   
      36. %% @spec remove_all() -> [{Key, Value}].   
      37. remove_all() ->   
      38.     gen_server:call(?MODULE, {remove_all}).   
      39.   
      40.   
      41. %%  Callback functions.   
      42.   
      43. init([]) ->   
      44.     {ok, local};   
      45.   
      46. init([{isolation, NameServer}]) ->   
      47.     {ok, {isolation, NameServer}}.   
      48.   
      49. handle_call({save, Key, Value}, _From, NameServer) ->   
      50.     {reply, do_save(Key, Value, NameServer), NameServer};   
      51.   
      52. handle_call({load, Key}, _From, NameServer) ->   
      53.     {reply, do_load(Key, NameServer), NameServer};   
      54.   
      55. handle_call({load_all}, _From, NameServer) ->   
      56.     {reply, do_load_all(NameServer), NameServer};   
      57.   
      58. handle_call({remove, Key}, _From, NameServer) ->   
      59.     {reply, do_remove(Key, NameServer), NameServer};   
      60.   
      61. handle_call({remove_all}, _From, NameServer) ->   
      62.     {reply, do_remove_all(NameServer), NameServer};   
      63.   
      64. handle_call({stop}, _From, NameServer) ->   
      65.     {stop, normal, stopped, NameServer}.   
      66.   
      67. %% Default implement.   
      68.   
      69. handle_cast(_Msg, State) ->   
      70.     {noreply, State}.   
      71.        
      72. handle_info(_Info, State) ->   
      73.     {noreply, State}.   
      74.   
      75. terminate(_Reason, _State) ->   
      76.     ok.   
      77.   
      78. code_change(_OldVsn, State, _Extra) ->   
      79.     {ok, State}.   
      80.   
      81. %% Private functions.   
      82.   
      83. do_save(Key, Value, {isolation, NameServer}) ->   
      84.     NameServer ! {self(), save, Key, Value},   
      85.     receive   
      86.         Msg -> Msg   
      87.     end;   
      88.   
      89. do_save(Key, Value, _) ->   
      90.     erlang:put(Key, Value).   
      91.   
      92. do_load(Key, {isolation, NameServer}) ->   
      93.     NameServer ! {self(), load, Key},   
      94.     receive   
      95.         Msg -> Msg   
      96.     end;   
      97.   
      98. do_load(Key, _) ->   
      99.     erlang:get(Key).   
      100.   
      101. do_load_all({isolation, NameServer}) ->   
      102.     NameServer ! {self(), load_all},   
      103.     receive   
      104.         Msg -> Msg   
      105.     end;   
      106.   
      107. do_load_all(_) ->   
      108.     erlang:get().   
      109.   
      110. do_remove(Key, {isolation, NameServer}) ->   
      111.     NameServer ! {self(), remove, Key},   
      112.     receive   
      113.         Msg -> Msg   
      114.     end;   
      115.   
      116. do_remove(Key, _) ->   
      117.     erlang:erase(Key).   
      118.   
      119. do_remove_all({isolation, NameServer}) ->   
      120.     NameServer ! {self(), remove_all},   
      121.     receive   
      122.         Msg -> Msg   
      123.     end;   
      124.   
      125. do_remove_all(_) ->   
      126.     erlang:erase().  

       

      上面這段代碼就是 lzy_name_svc 名稱服務(wù)了,有些地方寫得有點(diǎn)冗余,呵呵。

       

                為了能夠替換字典進(jìn)程來(lái)測(cè)試驗(yàn)證名稱服務(wù)功能,還寫了一個(gè)超簡(jiǎn)單的 foo_svc 服務(wù),用來(lái)和 lzy_name_svc 通信完成進(jìn)程字典存取。

       

      Erlang代碼 復(fù)制代碼
      1. -module(foo_svc).   
      2.   
      3. -export([start/0, load_all/0, server_pid/0]).   
      4.   
      5. start() ->   
      6.     register(fs, spawn(fun() -> loop() end)).   
      7.   
      8. load_all() ->   
      9.     fs !  {self(), load_all},   
      10.     receive   
      11.         Msg -> Msg   
      12.     end.   
      13.        
      14. server_pid() ->   
      15.     fs ! { self(), server_pid},   
      16.     receive   
      17.         Msg -> Msg   
      18.     end.   
      19.        
      20. loop() ->   
      21.     receive   
      22.         {From, save, Key, Value} ->   
      23.             From ! erlang:put(Key, Value),   
      24.             loop();   
      25.         {From, load, Key} ->   
      26.             From ! erlang:get(Key),   
      27.             loop();   
      28.         {From, load_all} ->   
      29.             From ! erlang:get(),   
      30.             loop();   
      31.         {From, remove, Key} ->   
      32.             From ! erlang:erase(Key),   
      33.             loop();   
      34.         {From, remove_all} ->   
      35.             From ! erlang:erase(),   
      36.             loop();   
      37.         {From, server_pid} ->   
      38.             From ! self(),   
      39.             loop()   
      40.     end.  

       

                下面的代碼就是創(chuàng)建和調(diào)用服務(wù)的相關(guān)代碼了,一起貼上來(lái)。第一段是以缺省方式啟動(dòng)了 lzy_name_svc 服務(wù),并向存取 abc -> 123 名稱。

       

      Erlang代碼 復(fù)制代碼
      1. C:\Program Files\erl5.6.4\usr>..\bin\erl -sname server   
      2. Eshell V5.6.4  (abort with ^G)   
      3. (server@lzy)1> c(lzy_name_svc).   
      4. {ok,lzy_name_svc}   
      5. (server@lzy)2> c(foo_svc.erl).   
      6. {ok,foo_svc}   
      7. (server@lzy)3> lzy_name_svc:start().   
      8. {ok,<0.47.0>}   
      9. (server@lzy)4> lzy_name_svc:save(abc, 123).   
      10. undefined   
      11. (server@lzy)5> lzy_name_svc:load(abc).   
      12. 123  
      13. (server@lzy)6> lzy_name_svc:load(efg).   
      14. undefined   
      15. (server@lzy)7> lzy_name_svc:load_all().   
      16. [{abc,123},   
      17.  {'$ancestors',[<0.35.0>]},   
      18.  {'$initial_call',{gen,init_it,   
      19.                        [gen_server,<0.35.0>,<0.35.0>,   
      20.                         {local,lzy_name_svc},   
      21.                         lzy_name_svc,[],[]]}}]   
      22. (server@lzy)8> lzy_name_svc:remove(abc).   
      23. 123  
      24. (server@lzy)9> lzy_name_svc:load(abc).   
      25. undefined  

       

      下面這段是啟動(dòng) foo_svc 服務(wù),用它創(chuàng)建的進(jìn)程來(lái)專門存儲(chǔ)名稱數(shù)據(jù),是通過(guò) lzy_name_svc:start/1 傳入的 PID。

       

      Erlang代碼 復(fù)制代碼
      1. C:\Program Files\erl5.6.4\usr>..\bin\erl -sname server   
      2. Eshell V5.6.4  (abort with ^G)   
      3. (server@lzy)1> foo_svc:start().   
      4. true   
      5. (server@lzy)2> NameSvcPid = foo_svc:server_pid().   
      6. <0.37.0>   
      7. (server@lzy)3> lzy_name_svc:start([{isolation, NameSvcPid}]).   
      8. {ok,<0.40.0>}   
      9. (server@lzy)4> lzy_name_svc:save(abc, 123).   
      10. undefined   
      11. (server@lzy)5> lzy_name_svc:load(abc).   
      12. 123  
      13. (server@lzy)6> foo_svc:load_all().   
      14. [{abc,123}]   
      15. (server@lzy)7> lzy_name_svc:remove_all().   
      16. [{abc,123}]   
      17. (server@lzy)8> foo_svc:load_all().   
      18. []  

       

                上邊的兩段都是在同一機(jī)器上的同一 erlang 節(jié)點(diǎn)上完成服務(wù)調(diào)用的,下面這段代碼是 lzy_name_svc 服務(wù)基于上邊狀態(tài)時(shí),在同一機(jī)器的另外了個(gè) erlang 節(jié)點(diǎn)上通過(guò) rpc 庫(kù)完成服務(wù)調(diào)用的。

       

      Erlang代碼 復(fù)制代碼
      1. C:\Program Files\erl5.6.4\usr>..\bin\erl -sname client1   
      2. Eshell V5.6.4  (abort with ^G)   
      3. (client1@lzy)1> rpc:call(server@lzy, lzy_name_svc, save, [abc, 123]).   
      4. undefined   
      5. (client1@lzy)2> rpc:call(server@lzy, foo_svc, load_all, []).   
      6. [{abc,123}]  
       

      呵呵,挺入門的,就當(dāng)做為學(xué)習(xí)過(guò)程的記錄吧。看好 erlang。

       

                在學(xué)習(xí)的過(guò)程中,有一個(gè)事情比較不解,就是對(duì)于 字典進(jìn)程的 “熱替換” 我想本應(yīng)該是可以通過(guò) gen_server behaviour 用于“熱代碼替換”的 code_change 方法完成的,但試了幾次都達(dá)不到目的,服務(wù)倒是跑的正常,可是字典進(jìn)程就是不能熱替換,code_change 正常返回,可是名稱數(shù)據(jù)卻還是原有字典進(jìn)程的。測(cè)試驗(yàn)證代碼如下:

       

      Erlang代碼 復(fù)制代碼
      1. C:\Program Files\erl5.6.4\usr>..\bin\erl -sname server   
      2. Eshell V5.6.4  (abort with ^G)   
      3. (server@lzy)1> lzy_name_svc:start().   
      4. {ok,<0.37.0>}   
      5. (server@lzy)2> lzy_name_svc:save(abc, 123).   
      6. undefined   
      7. (server@lzy)3> lzy_name_svc:load_all().   
      8. [{abc,123},   
      9.  {'$ancestors',[<0.35.0>]},   
      10.  {'$initial_call',{gen,init_it,   
      11.                        [gen_server,<0.35.0>,<0.35.0>,   
      12.                         {local,lzy_name_svc},   
      13.                         lzy_name_svc,[],[]]}}]   
      14. (server@lzy)4> foo_svc:start().   
      15. true   
      16. (server@lzy)5> NameSvcPid = foo_svc:server_pid().   
      17. <0.41.0>   
      18. (server@lzy)6> foo_svc:load_all().   
      19. []   
      20. (server@lzy)7> lzy_name_svc:code_change(foo, NameSvcPid, foo).   
      21. {ok,<0.41.0>}   
      22. (server@lzy)8> lzy_name_svc:load_all().   
      23. [{abc,123},   
      24.  {'$ancestors',[<0.35.0>]},   
      25.  {'$initial_call',{gen,init_it,   
      26.                        [gen_server,<0.35.0>,<0.35.0>,   
      27.                         {local,lzy_name_svc},   
      28.                         lzy_name_svc,[],[]]}}]  

       

      還請(qǐng)哪位 erlang guru 指點(diǎn)~

       

      // 2009.02.07 22:52 添加 ////

       

      這里提供了該名稱服務(wù)的新迭代版本。

      gen_server tasting 之超簡(jiǎn)單名稱服務(wù)(續(xù))

       

      添加了如下功能:

       

      1. 使用 otp 監(jiān)控樹保證服務(wù)可靠性。
      2. 添加日志功能,記錄警告事件。
      3. 將名稱服務(wù)打包為 application。
      4. 開放 socket 服務(wù),使用 vsns://verb /param 自定義協(xié)議對(duì)外提供訪問(wèn)支持。

       


      安徽新華電腦學(xué)校專業(yè)職業(yè)規(guī)劃師為你提供更多幫助【在線咨詢
      国产午夜福三级在线播放_亚洲精品成a人片在线观看_亚洲自慰一区二区三区_久久棈精品久久久久久噜噜
      <source id="4vppl"><ins id="4vppl"></ins></source>
      <u id="4vppl"><sub id="4vppl"><label id="4vppl"></label></sub></u>
      <object id="4vppl"></object>
    1. <u id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></u>

      <object id="4vppl"></object>
      <b id="4vppl"><sub id="4vppl"><tr id="4vppl"></tr></sub></b>

        <i id="4vppl"><thead id="4vppl"></thead></i>

        <thead id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></thead>
        在线播放亚洲最大日韩 | 一级理伦性理伦a在线 | 在线中文字幕亚洲欧美一区 | 婷婷在线免费视频 | 天天综合一区二区三区 | 中文有码日本高清在线视频 |