我是Erlang新手.我有一个关于ets表的问题.
我有两个ets表,我需要插入或删除两者的值.
insert(V) ->
ets:insert(table_test,V),
ets:insert(table_cp,V).
delete(V)->
ets:delete(table_test,V),
ets:delete(table_cp,V).
Run Code Online (Sandbox Code Playgroud)
我怎样才能保证两者的操作成功或失败?
例如,插入操作,如果在ets上有错误:insert(table_cp,V),我应该从talbe_test中删除该值吗?
删除相同,如果ets:delete(table_cp,V)失败,我应该重新插入值吗?
请帮忙.
我是 Erlang 的新手,但我想知道是否有可能以某种方式附加到一个工作应用程序并检查它正在使用的 ETS 或 DETS。如果是,你愿意举一个小例子吗?
谢谢!
我是动态创建ets表,所以最好避免使用 atom 作为名称。
简单使用字符串作为名称,例如:
:ets.new("aaa", [:named_table])
但是不能编译:
** (ArgumentError) argument error
(stdlib) :ets.new("aaa", [])
Run Code Online (Sandbox Code Playgroud) Erlang ETS表可以在不同的进程之间共享吗?因此,如果我有两个进程在不同的Erlang运行系统上运行,我可以以某种方式链接它们,以便我在一个ETS表中做的所有更改将反映在另一个ETS表中吗?
我正在尝试实现一个可以查询/更新某些状态信息的流程(我正在开发短信服务,并希望根据响应存储一些本地数据 - 稍后我将使用数据库,但现在我想使用 ETS,这是我的第一个 Erlang 项目,所以我认为学习它很有用)。不幸的是,我的插入似乎没有通过,我不明白为什么。这是模块:
-module(st).
-compile(export_all).
maintain_state() ->
Tab = ets:new(state, [set]),
receive
{Pid, lookup, Key} ->
Pid ! ets:lookup(Tab, Key),
maintain_state();
{Pid, update, Key, Handler} ->
NewState = Handler(ets:lookup(Tab, Key)),
Status = ets:insert(Tab, NewState),
Pid ! {Status, NewState},
maintain_state();
{Pid, statelist} ->
Pid ! ets:tab2list(Tab),
maintain_state();
kill ->
void
end,
ets:delete(Tab).
start_state_maintainer() ->
Pid = spawn(st, maintain_state, []),
register(state, Pid).
update_state(StateHandler) ->
state ! {self(), update, testing, StateHandler},
receive
After ->
After
after 1000 ->
throw("Timeout in …Run Code Online (Sandbox Code Playgroud) 所以这是我的代码:
defmodule Parent do
def arun(pid) do
:ets.new(:my_table,[:named_table, :set, :public, read_concurrency: true])
:ets.give_away(:my_table, pid, [])
end
def receiver do
pid = spawn(fn -> arun(self()) end)
receive do
{'ETS-TRANSFER',_,_,_} ->
IO.puts "ets got transferred"
_ ->
IO.puts "I dont know what happened"
end
end
end
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试编译此运行时错误即将到来.
iex(31)> Parent.receiver
17:37:19.183 [error] Process #PID<0.204.0> raised an exception
** (ArgumentError) argument error
(stdlib) :ets.give_away(:my_table, #PID<0.204.0>, [])
parent.ex:4: Parent.arun/1
Run Code Online (Sandbox Code Playgroud)
还有人可以告诉我正确的方法来制作一个ets表并将其所有权交给其他进程吗?我正在尝试这样做:父进程将创建一个异步任务,它将创建一个ets表,然后此任务/进程将所有权返还给父进程.
在ets中查找不存在的表(t3)之后,将删除所有用户创建的表(t1和t2).它是一个bug还是只是ets的一个奇怪的功能?
这是Eshell中的代码.
Eshell V5.9.1 (abort with ^G)
1> ets:new(t1, [named_table]).
t1
2> ets:new(t2, [named_table]).
t2
3> ets:all().
[t2,t1,8207,4110,13,file_io_servers,inet_hosts_file_byaddr,
inet_hosts_file_byname,inet_hosts_byaddr,inet_hosts_byname,
inet_cache,inet_db,global_pid_ids,global_pid_names,
global_names_ext,global_names,global_locks,ac_tab]
4> ets:insert(t1, {1,2}).
true
5> ets:lookup(t1, 1).
[{1,2}]
6> ets:lookup(t2, 1).
[]
7> ets:all().
[t2,t1,8207,4110,13,file_io_servers,inet_hosts_file_byaddr,
inet_hosts_file_byname,inet_hosts_byaddr,inet_hosts_byname,
inet_cache,inet_db,global_pid_ids,global_pid_names,
global_names_ext,global_names,global_locks,ac_tab]
8> ets:lookup(t3, 1).
** exception error: bad argument
in function ets:lookup/2
called as ets:lookup(t3,1)
9> ets:all().
[8207,4110,13,file_io_servers,inet_hosts_file_byaddr,
inet_hosts_file_byname,inet_hosts_byaddr,inet_hosts_byname,
inet_cache,inet_db,global_pid_ids,global_pid_names,
global_names_ext,global_names,global_locks,ac_tab]
10>
Run Code Online (Sandbox Code Playgroud)
谁能告诉我这里的问题是什么?
我正在创建一个在进程中具有唯一原子名称的ETS表.该过程执行并终止.流程终止是否会清除ETS消耗的资源(内存)?
使用后是否需要清理/删除ETS表?
这就是我在做的事情:
parentProcess() ->
UniqueAtomTerm = 'myAtomIdentifier',
ets:new( UniqueAtomTerm, [] ),
myProc (UniqueAtomTerm).
Run Code Online (Sandbox Code Playgroud)
.
myProc( UniqueAtomTerm ) ->
.... do some inserts, etc
ets:delete_all_objects( UniqueAtomTerm ).
Run Code Online (Sandbox Code Playgroud)
似乎如果我尝试创建具有相同原子标识符的另一个ETS表,它将会出错,因此上述似乎不起作用.根据以上所述,我不能将ETS表选项设置为私有,因为我需要从不同的进程插入(以防私有将清除ETS资源).
所以底线问题:如何从特定的ETS表中删除所有资源?
我有一个使用erlang术语存储的小型Elixir应用程序,我想浏览它并查看存储的内容.有没有办法用Elixir或Erlang做到这一点?
我想知道它有多大,里面有什么.
编辑:我知道我可以查看进程:observer.start,但没有列出的进程或应用程序ets.有Elixir.Hex.Registry.ETS,但状态或其他过程信息看起来不正确.
我也可以打印出来,iex但这不是一次很棒的体验.
我ets在一个长生不老药应用程序中有一个设置表。我需要清理其 updated_at 字段超过 10 秒的记录。有没有一种方法可以设置到期时间或手动完成而不遍历所有记录?我根据大于给定时间的时间戳匹配记录。
示例记录:
key: key_1
record: %{id: key_1, updated_at: ~N[2018-12-19 10:08:47.803075]}
Run Code Online (Sandbox Code Playgroud)
到目前为止我有这个代码
def clean_stale(previous_key) do
if previous_key == :"$end_of_table" do
:ok
else
device = get(previous_key)
next_key = :ets.next(__MODULE__, previous_key)
if NaiveDateTime.diff(NaiveDateTime.utc_now, device.last_recorded_at) > 10 do
remove(device.id)
end
clean_stale(next_key)
end
end
Run Code Online (Sandbox Code Playgroud)