From 9993923c40b96ab07752ec36692dc09c4c7648e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= <essen@ninenines.eu>
Date: Mon, 24 Dec 2012 16:09:40 +0100
Subject: Add ranch:set_max_connections/2 and get_max_connections/1

---
 src/ranch.erl          | 15 +++++++++++++++
 src/ranch_acceptor.erl | 25 +++++++++++++++++--------
 src/ranch_listener.erl | 11 ++++++++++-
 3 files changed, 42 insertions(+), 9 deletions(-)

(limited to 'src')

diff --git a/src/ranch.erl b/src/ranch.erl
index 59e1fa7..c582efa 100644
--- a/src/ranch.erl
+++ b/src/ranch.erl
@@ -20,6 +20,8 @@
 -export([child_spec/6]).
 -export([accept_ack/1]).
 -export([get_port/1]).
+-export([get_max_connections/1]).
+-export([set_max_connections/2]).
 -export([get_protocol_options/1]).
 -export([set_protocol_options/2]).
 -export([filter_options/3]).
@@ -121,6 +123,19 @@ get_port(Ref) ->
 	{ok, Port} = ranch_listener:get_port(ListenerPid),
 	Port.
 
+%% @doc Return the max number of connections allowed concurrently.
+-spec get_max_connections(any()) -> non_neg_integer().
+get_max_connections(Ref) ->
+	ListenerPid = ranch_server:lookup_listener(Ref),
+	{ok, MaxConnections} = ranch_listener:get_max_connections(ListenerPid),
+	MaxConnections.
+
+%% @doc Set the max number of connections allowed concurrently.
+-spec set_max_connections(any(), non_neg_integer()) -> ok.
+set_max_connections(Ref, MaxConnections) ->
+	ListenerPid = ranch_server:lookup_listener(Ref),
+	ok = ranch_listener:set_max_connections(ListenerPid, MaxConnections).
+
 %% @doc Return the current protocol options for the given listener.
 -spec get_protocol_options(any()) -> any().
 get_protocol_options(Ref) ->
diff --git a/src/ranch_acceptor.erl b/src/ranch_acceptor.erl
index d208a7f..1985826 100644
--- a/src/ranch_acceptor.erl
+++ b/src/ranch_acceptor.erl
@@ -57,22 +57,31 @@ loop(LSocket, Transport, Protocol, MaxConns, Opts, ListenerPid, ConnsSup) ->
 			Transport:controlling_process(CSocket, ConnPid),
 			ConnPid ! {shoot, ListenerPid},
 			NbConns = ranch_listener:add_connection(ListenerPid, ConnPid),
-			maybe_wait(ListenerPid, MaxConns, NbConns),
+			{ok, MaxConns2} = maybe_wait(ListenerPid, MaxConns, NbConns),
 			?MODULE:init(LSocket, Transport, Protocol,
-				MaxConns, Opts, ListenerPid, ConnsSup);
+				MaxConns2, Opts, ListenerPid, ConnsSup);
+		%% Upgrade the max number of connections allowed concurrently.
+		{set_max_conns, MaxConns2} ->
+			?MODULE:loop(LSocket, Transport, Protocol,
+				MaxConns2, Opts, ListenerPid, ConnsSup);
 		%% Upgrade the protocol options.
 		{set_opts, Opts2} ->
 			?MODULE:loop(LSocket, Transport, Protocol,
 				MaxConns, Opts2, ListenerPid, ConnsSup)
 	end.
 
--spec maybe_wait(pid(), non_neg_integer(), non_neg_integer()) -> ok.
+-spec maybe_wait(pid(), non_neg_integer(), non_neg_integer())
+	-> {ok, non_neg_integer()}.
 maybe_wait(_, MaxConns, NbConns) when MaxConns > NbConns ->
-	ok;
-maybe_wait(ListenerPid, MaxConns, _) ->
-	erlang:yield(),
-	NbConns2 = ranch_server:count_connections(ListenerPid),
-	maybe_wait(ListenerPid, MaxConns, NbConns2).
+	{ok, MaxConns};
+maybe_wait(ListenerPid, MaxConns, NbConns) ->
+	receive
+		{set_max_conns, MaxConns2} ->
+			maybe_wait(ListenerPid, MaxConns2, NbConns)
+	after 0 ->
+		NbConns2 = ranch_server:count_connections(ListenerPid),
+		maybe_wait(ListenerPid, MaxConns, NbConns2)
+	end.
 
 -spec async_accept(inet:socket(), module()) -> ok.
 async_accept(LSocket, Transport) ->
diff --git a/src/ranch_listener.erl b/src/ranch_listener.erl
index 52e4c32..873d860 100644
--- a/src/ranch_listener.erl
+++ b/src/ranch_listener.erl
@@ -24,6 +24,7 @@
 -export([get_port/1]).
 -export([set_port/2]).
 -export([get_max_connections/1]).
+-export([set_max_connections/2]).
 -export([get_protocol_options/1]).
 -export([set_protocol_options/2]).
 
@@ -82,11 +83,15 @@ set_port(ServerPid, Port) ->
 	gen_server:cast(ServerPid, {set_port, Port}).
 
 %% @doc Return the max number of connections allowed concurrently.
-%% @todo Add set_max_connections.
 -spec get_max_connections(pid()) -> {ok, non_neg_integer()}.
 get_max_connections(ServerPid) ->
 	gen_server:call(ServerPid, get_max_connections).
 
+%% @doc Set the max number of connections allowed concurrently.
+-spec set_max_connections(pid(), non_neg_integer()) -> ok.
+set_max_connections(ServerPid, MaxConnections) ->
+	gen_server:call(ServerPid, {set_max_connections, MaxConnections}).
+
 %% @doc Return the current protocol options.
 -spec get_protocol_options(pid()) -> {ok, any()}.
 get_protocol_options(ServerPid) ->
@@ -109,6 +114,10 @@ handle_call(get_port, _From, State=#state{port=Port}) ->
 	{reply, {ok, Port}, State};
 handle_call(get_max_connections, _From, State=#state{max_conns=MaxConns}) ->
 	{reply, {ok, MaxConns}, State};
+handle_call({set_max_connections, MaxConnections}, _From,
+		State=#state{ref=Ref}) ->
+	ranch_server:send_to_acceptors(Ref, {set_max_conns, MaxConnections}),
+	{reply, ok, State#state{max_conns=MaxConnections}};
 handle_call(get_protocol_options, _From, State=#state{proto_opts=ProtoOpts}) ->
 	{reply, {ok, ProtoOpts}, State};
 handle_call({set_protocol_options, ProtoOpts}, _From, State=#state{ref=Ref}) ->
-- 
cgit v1.2.3