You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by rn...@apache.org on 2020/12/16 18:05:20 UTC
[couchdb-ioq] 01/01: Use link/unlink for hidden nodes
This is an automated email from the ASF dual-hosted git repository.
rnewson pushed a commit to branch hidden-node-links
in repository https://gitbox.apache.org/repos/asf/couchdb-ioq.git
commit 6f970cabffda16ddb17440fe0cd13422bcc31e3e
Author: Robert Newson <rn...@apache.org>
AuthorDate: Wed Dec 16 17:53:23 2020 +0000
Use link/unlink for hidden nodes
link/unlink is supported by JInterface which presents as a hidden
node, this enhancement to ioq allows us to ditch scalang among other
effects.
---
src/ioq_server.erl | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 53 insertions(+), 2 deletions(-)
diff --git a/src/ioq_server.erl b/src/ioq_server.erl
index c9fd79b..9b12986 100644
--- a/src/ioq_server.erl
+++ b/src/ioq_server.erl
@@ -94,6 +94,7 @@ init([]) ->
histos = ets:new(ioq_histos, [named_table, ordered_set])
},
erlang:send_after(get_interval(), self(), dump_table),
+ process_flag(trap_exit, true),
{ok, update_config(State)}.
handle_call({set_priority, Pri}, _From, State) ->
@@ -146,7 +147,7 @@ handle_info({Ref, Reply}, #state{reqs = Reqs} = State) ->
case lists:keytake(Ref, #request.ref, Reqs) of
{value, #request{from=From} = Req, Reqs2} ->
TResponse = erlang:monotonic_time(),
- erlang:demonitor(Ref, [flush]),
+ demonitor_(Ref, Req#request.fd),
reply_to_all(From, Reply),
update_histograms(ioq_histos, Req, TResponse),
{noreply, State#state{reqs = Reqs2}, 0};
@@ -163,6 +164,12 @@ handle_info({'DOWN', Ref, _, _, Reason}, #state{reqs = Reqs} = State) ->
{noreply, State, 0}
end;
+handle_info({'EXIT', Pid, Reason}, #state{reqs = Reqs} = State) ->
+ {L1, L2} = lists:splitwith(fun(R) -> Pid == R#request.fd end, Reqs),
+ lists:foreach(
+ fun(R) -> reply_to_all(R#request.from, {'EXIT', Reason}) end, L1),
+ {noreply, State#state{reqs = L2}, 0};
+
handle_info(dump_table, State) ->
erlang:send_after(get_interval(), self(), dump_table),
{noreply, dump_table(State), 0};
@@ -414,7 +421,7 @@ submit_request(Request, State) ->
#state{reqs = Reqs, counters = Counters} = State,
% make the request
- Ref = erlang:monitor(process, Fd),
+ Ref = monitor_(Fd),
Fd ! {'$gen_call', {self(), Ref}, Call},
% record some stats
@@ -598,6 +605,50 @@ rw({append_bin, _}) ->
rw(_) ->
unknown.
+
+monitor_(Pid) when is_pid(Pid) ->
+ case is_hidden(Pid) of
+ true ->
+ link(Pid),
+ make_ref();
+ false ->
+ erlang:monitor(process, Pid)
+ end;
+
+monitor_({Name, Node}) when is_atom(Name), is_atom(Node) ->
+ case is_hidden(Node) of
+ true ->
+ make_ref();
+ false ->
+ erlang:monitor(process, {Name, Node})
+ end.
+
+
+demonitor_(Ref, Pid) when is_reference(Ref), is_pid(Pid) ->
+ case is_hidden(Pid) of
+ true ->
+ unlink(Pid);
+ false ->
+ erlang:demonitor(Ref, [flush])
+ end;
+
+demonitor_(Ref, {Name, Node})
+ when is_reference(Ref), is_atom(Name), is_atom(Node) ->
+ case is_hidden(Node) of
+ true ->
+ ok;
+ false ->
+ erlang:demonitor(Ref, [flush])
+ end.
+
+
+is_hidden(Pid) when is_pid(Pid) ->
+ is_hidden(node(Pid));
+
+is_hidden(Node) when is_atom(Node) ->
+ lists:member(Node, nodes(hidden)).
+
+
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").