remote ets select
Ulf Wiger (AL/EAB)
ulf.wiger@REDACTED
Fri Jun 16 10:48:05 CEST 2006
We had reason to deal with the need for doing chunked ets:select() via
rpc. The complication, which is well documented in ets, is that the
continuation returned by ets:select/3 cannot be serialized, and
therefore breaks if it is passed between nodes.
I wrote the following example program to illustrate how one could go
about using ets:select/3 remotely. One *could* imagine putting something
similar in ets.erl as a library function, but I don't know if there is
enough demand to warrant that. Let this be a lightweight howto for now.
(:
The solution is somewhat inspired by rpc:async_rpc/4.
Not one line of comments - the code is obviously
self-documenting. ;)
BR,
Ulf W
-module(remote_select).
-export([select/4, select/1]).
select(Node, Tab, Ms, Limit) ->
ReplyTo = self(),
Pid =
spawn(
Node,
fun() ->
MRefB = erlang:monitor(process, ReplyTo),
handle_select(MRefB, ReplyTo, ets:select(Tab, Ms,
Limit))
end),
MRefA = erlang:monitor(process, Pid),
await_reply(Pid, MRefA).
select('$end_of_table' = Last) -> Last;
select({MRef, {Pid, Cont}}) ->
Pid ! {self(), Cont},
await_reply(Pid, MRef).
await_reply(Pid, MRef) ->
receive
{'DOWN', MRef, _, _, Reason} ->
erlang:error({proxy_error, Pid, Reason});
{Pid, {_Objs, '$end_of_table'} = Last} ->
erlang:demonitor(MRef),
Last;
{Pid, {Objs, Cont}} ->
{Objs, {MRef, Cont}}
end.
handle_select(MRef, ReplyTo, Result) ->
case Result of
{_, '$end_of_table'} ->
ReplyTo ! {self(), Result},
done;
{Objs, Cont1} ->
ReplyTo ! {self(), {Objs, {self(), cont}}},
select_loop(MRef, ReplyTo, Cont1)
end.
select_loop(MRef, ReplyTo, Cont) ->
receive
{'DOWN', MRef, _, _, _} ->
done;
{ReplyTo, cont} ->
handle_select(MRef, ReplyTo, ets:select(Cont))
end.
More information about the erlang-questions
mailing list