erlang ets 选择错误的参数

Posted

技术标签:

【中文标题】erlang ets 选择错误的参数【英文标题】:erlang ets select bad arg 【发布时间】:2016-10-23 06:12:45 【问题描述】:

erlang 版本 18.3

Erlang ets:select/1

遇到一个奇怪的错误

以下代码将从表格中选择元素并获取它们

如果我这样做

save(10), %% insert 10 data

remove(3) %% remove 3 data per time

有效

如果我这样做

save(6007), %% insert  more datas

remove(400) %% remove 400 data per time

ets:select(Cont) 中的 arg 也是错误的,它不是在第一个或第二个循环中,但始终存在。

有什么建议吗?

 -record(item, name, age).
 %% start the table
 start() ->
 ets:new(example_table, [public, keypos, 2,
 named_table,
 read_concurrency, true,
 write_concurrency, true]).

 %% insert n demo data
 save(Limit) ->
 All = lists:seq(1 ,Limit),
 All_rec = [#itemname = <<"demo">>, integer_to_binary(V) , age = V || V <- All],
 ets:insert(example_table, All_rec).

 %% remove all data, n data per select
 remove(Limit) ->
   M_head   = #itemname = '$1', _ = '_',
 M_guards = [],
 M_result = ['$1'],
 M_spec   = [M_head, M_guards, M_result],

 case ets:select(example_table, M_spec, Limit) of
      '$end_of_table' ->
      0;
      Keys, Cont ->

      remove(example_table, Keys, Cont, 0, [])
      end.

      remove(Table, [],  Cont, Count, _Acc) ->

        case ets:select(Cont) of
          '$end_of_table' ->
            Count;
          Keys, Cont_1 ->

            remove(Table, Keys,  Cont_1, Count, [])
        end;
      remove(Table,[Key | T],  Cont, Count, Acc) ->
        case ets:take(example_table, Key) of
          [] ->
       remove(Table, T,  Cont, Count, Acc);
          [Rec] ->
       io:format("Rec [~p] ~n", [Rec]),
       remove(Table, T,  Cont, Count + 1, [Rec | Acc])
        end.

堆栈跟踪

     4> example_remove:save(6007).
      true
     5> example_remove:remove(500).
    ** exception error: bad argument
   in function  ets:select/1
    called as ets:select(example_table,304,500,<<>>,
                             [<<"demo">>,<<"2826">>,
                              <<"demo">>,<<"3837">>,
                              <<"demo">>,<<"5120">>,
                              <<"demo">>,<<"878">>,
                              <<"demo">>,<<"1195">>,
                              <<"demo">>,<<"1256">>,
                              <<"demo">>,<<"1449">>,
                              <<"demo">>,<<"5621">>,
                              <<"demo">>,<<"5768">>],
                             9)
 in call from example_remove:remove/5 (d:/workspace/simple-cache/src/example_remove.erl, line 47)

【问题讨论】:

这段代码的目的是什么?另外,请向我们展示您收到的错误日志。 我无法复制。 @Lol4t0 你用的是哪个版本的erlang? @A.Sarid 日志已更新 【参考方案1】:

我相信发生这种情况是因为您同时遍历表并对其进行修改。

我建议用safe_fixtable 的守卫来包装主删除周期

remove(Limit) ->
    ets:safe_fixtable(example_table, true),
    M_head   = #itemname = '$1', _ = '_',
    M_guards = [],
    M_result = ['$1'],
    M_spec   = [M_head, M_guards, M_result],

    R = case ets:select(example_table, M_spec, Limit) of
        '$end_of_table' ->
            0;
        Keys, Cont ->
            remove(example_table, Keys, Cont, 0, [])
    end,
    ets:safe_fixtable(example_table, false),
    R. 

【讨论】:

谢谢。这是有道理的。

以上是关于erlang ets 选择错误的参数的主要内容,如果未能解决你的问题,请参考以下文章

Erlang ETS 插入/2 错误

如何从 Erlang/Elixir 中的 ets 集中选择一个随机元素?

erlang 笔记(06/03/02)

有没有办法浏览 erlang 术语存储 (ETS)

从 ets:lookup() 中提取值 - Erlang

Erlang ETS 内存碎片