remote ets select

Ulf Wiger (AL/EAB) <>
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