簡體   English   中英

Erlang: ets 表在 gen_server 崩潰並重啟后不保存數據

[英]Erlang: ets table does not persist data after gen_server crashes and restarts

我有一個 gen_server,它將對象的位置存儲在這樣的 ets 表中

-module(my_gen_server).
-record(slot, {position, object}).
-behavior(gen_server).

%% API
-export([start_link/1, init/1, move/2, handle_call/3, handle_cast/2, get/1, delete/1]).

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

init([]) ->
  WidthX, HeightY = get_dims(),
  ets:new(my_gen_server,[named_table, {keypos, #slot.position}]),
  {ok, {WidthX, HeightY}}.

move(Object, {X,Y}) ->
  gen_server:call(?MODULE, {move, Object, {X,Y}}).

handle_call({move, Object, {X,Y}}, _From, {WidthX, HeightY}) ->
  case add_or_move(Object, X, Y) of
    {error, Reason} ->
      {reply, {error, Reason}, {WidthX, HeightY}};
    _ ->
      {reply, ok, {WidthX, HeightY}}
  end.

search_object(Object) ->
  Pos = ets:match(my_gen_server, #slot{position ='$1', object = Object, _='_'}),
  case Pos of
    [] -> {error, "Not found"};
    _ -> lists:flatten(Pos)
  end.

add_or_move(Object, X, Y) ->
   Pos = search_object(Object),
   case Pos of
      {error, _Reason} ->
          supervisor:start_child(my_object_sup, [Object, {X, Y}]),
          ets:insert(my_gen_server, #slot{position = {X,Y}, object = Object});
      _ ->
          ets:insert(my_gen_server, #slot{position = {X,Y}, object = Object})
   end.

問題是當主管啟動my_gen_server並且進程崩潰並重新啟動時,ets 表消失了,我丟失了所有 object 數據。 我搜索了這個問題,到處都說在 ets 表中存儲數據有助於使 state 持續存在,但我無法在任何地方找到實現它的代碼。 我還嘗試在調用gen_server:start_link而不是 init 之前創建 ets 表,但這會阻止 gen_server 在崩潰后完全重新啟動。 我知道從概念上講 ets 表應該能夠保留 state 但真的希望得到一些幫助來理解它在代碼中的工作方式。

ets表鏈接到創建它們的進程,這就是為什么如果您在gen_server進程中創建表,當進程終止時,該表將被銷毀。 如果您希望表持久存在,您基本上有 2 個選擇:

  • 使用ets inheritance 機制:查看ets:give_away/3和表初始化的heir選項。
  • 保留一個擁有不是您的服務器之一的表的進程。 在這種情況下,應將表創建為public表和命名表,並且不應對表持有進程執行任何操作。 該過程只應存在以保持表格。 然后,您的服務器就可以按名稱訪問該表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM