Some tidying up and comment improvements.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6169 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -40,11 +40,19 @@ import static com.threerings.presents.Log.log;
|
|||||||
public class SelectorIterable
|
public class SelectorIterable
|
||||||
implements Iterable<SelectionKey>
|
implements Iterable<SelectionKey>
|
||||||
{
|
{
|
||||||
|
/** The maximum allowed consecutive select() failures, after which we will declare ourselves
|
||||||
|
* irreparably hosed. */
|
||||||
|
public static final int MAX_SELECT_FAILURES = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for the Selector failing.
|
* An interface for hearing about catastrophic selection failure. If select fails (in a
|
||||||
|
* non-expected way) more than {@link #MAX_SELECT_FAILURES} times in a row, this interface will
|
||||||
|
* be notified. This allows a server to reboot itself in an orderly manner, rather than
|
||||||
|
* continue in an inoperable state.
|
||||||
*/
|
*/
|
||||||
public interface SelectFailureHandler {
|
public interface SelectFailureHandler {
|
||||||
void handleSelectFailure(Exception e);
|
/** Called to report a select() failure. */
|
||||||
|
void handleSelectFailure (Exception e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,6 +67,7 @@ public class SelectorIterable
|
|||||||
_failureHandler = handler;
|
_failureHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// from interface Iterable<SelectionKey>
|
||||||
public Iterator<SelectionKey> iterator ()
|
public Iterator<SelectionKey> iterator ()
|
||||||
{
|
{
|
||||||
return Iterators.consumingIterator(select().iterator());
|
return Iterators.consumingIterator(select().iterator());
|
||||||
@@ -89,7 +98,7 @@ public class SelectorIterable
|
|||||||
// instead of looping indefinitely after things go pear-shaped, shut us down in an
|
// instead of looping indefinitely after things go pear-shaped, shut us down in an
|
||||||
// orderly fashion
|
// orderly fashion
|
||||||
log.warning("Failure select()ing.", re);
|
log.warning("Failure select()ing.", re);
|
||||||
if (_runtimeExceptionCount++ >= 20) {
|
if (_runtimeExceptionCount++ >= MAX_SELECT_FAILURES) {
|
||||||
_failureHandler.handleSelectFailure(re);
|
_failureHandler.handleSelectFailure(re);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,10 +106,7 @@ public class SelectorIterable
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected int _runtimeExceptionCount;
|
protected int _runtimeExceptionCount;
|
||||||
|
|
||||||
protected final int _selectLoopTime;
|
protected final int _selectLoopTime;
|
||||||
|
|
||||||
protected final Selector _selector;
|
protected final Selector _selector;
|
||||||
|
|
||||||
protected final SelectFailureHandler _failureHandler;
|
protected final SelectFailureHandler _failureHandler;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ import com.threerings.nio.SelectorIterable.SelectFailureHandler;
|
|||||||
|
|
||||||
import static com.threerings.presents.Log.log;
|
import static com.threerings.presents.Log.log;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listens for socket connections on a set of ports for a hostname and passes those connected
|
* Listens for socket connections on a set of ports for a hostname and passes those connected
|
||||||
* sockets on to a listener when they're ready. {@link #listen()} must be called after
|
* sockets on to a listener when they're ready. {@link #listen()} must be called after
|
||||||
@@ -51,6 +50,13 @@ import static com.threerings.presents.Log.log;
|
|||||||
*/
|
*/
|
||||||
public class SocketChannelAcceptor
|
public class SocketChannelAcceptor
|
||||||
{
|
{
|
||||||
|
/** Used to pass freshly accepted sockets to entities that want them. */
|
||||||
|
public interface SocketChannelHandler
|
||||||
|
{
|
||||||
|
/** Called when a new connection has been accepted and is ready for use. */
|
||||||
|
void handleSocketChannel (SocketChannel channel, long when);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a address to the given host, or the wildcard host if the hostname is
|
* Creates a address to the given host, or the wildcard host if the hostname is
|
||||||
* {@link StringUtil#blank}.
|
* {@link StringUtil#blank}.
|
||||||
@@ -61,11 +67,6 @@ public class SocketChannelAcceptor
|
|||||||
new InetSocketAddress(port) : new InetSocketAddress(hostname, port);
|
new InetSocketAddress(port) : new InetSocketAddress(hostname, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface SocketChannelHandler
|
|
||||||
{
|
|
||||||
void handleSocketChannel (SocketChannel channel, long when);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an acceptor that passes socket connections on to the given handler.
|
* Creates an acceptor that passes socket connections on to the given handler.
|
||||||
*
|
*
|
||||||
@@ -79,12 +80,9 @@ public class SocketChannelAcceptor
|
|||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
Preconditions.checkNotNull(ports, "Ports must be non-null.");
|
Preconditions.checkNotNull(ports, "Ports must be non-null.");
|
||||||
|
|
||||||
_bindHostname = bindHostname;
|
_bindHostname = bindHostname;
|
||||||
_ports = ports;
|
_ports = ports;
|
||||||
|
|
||||||
_selectorSelector = new SelectorIterable(_selector, selectLoopTime, failureHandler);
|
_selectorSelector = new SelectorIterable(_selector, selectLoopTime, failureHandler);
|
||||||
|
|
||||||
_connHandler = connectionHandler;
|
_connHandler = connectionHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,13 +105,14 @@ public class SocketChannelAcceptor
|
|||||||
log.info("Psych! Got ACCEPT_READY, but no connection.");
|
log.info("Psych! Got ACCEPT_READY, but no connection.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// log.debug("Accepted connection " + channel + ".");
|
// log.debug("Accepted connection " + channel + ".");
|
||||||
|
|
||||||
_connHandler.handleSocketChannel(channel, when);
|
_connHandler.handleSocketChannel(channel, when);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ports on which we are listening for connections.
|
||||||
|
*/
|
||||||
public Iterable<Integer> getPorts ()
|
public Iterable<Integer> getPorts ()
|
||||||
{
|
{
|
||||||
return Ints.asList(_ports);
|
return Ints.asList(_ports);
|
||||||
@@ -173,11 +172,13 @@ public class SocketChannelAcceptor
|
|||||||
return !_channels.isEmpty();
|
return !_channels.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes all listening sockets and shuts down.
|
||||||
|
*/
|
||||||
public void shutdown()
|
public void shutdown()
|
||||||
{
|
{
|
||||||
// unbind our listening socket
|
// unbind our listening sockets; note: because we wait for the objmgr to exit before we do,
|
||||||
// Note: because we wait for the object manager to exit before we do, we will still be
|
// we will still be accepting connections as long as there are events pending
|
||||||
// accepting connections as long as there are events pending.
|
|
||||||
for (ServerSocketChannel ssocket : _ssockets) {
|
for (ServerSocketChannel ssocket : _ssockets) {
|
||||||
try {
|
try {
|
||||||
ssocket.socket().close();
|
ssocket.socket().close();
|
||||||
@@ -187,7 +188,6 @@ public class SocketChannelAcceptor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected final int[] _ports;
|
protected final int[] _ports;
|
||||||
protected final String _bindHostname;
|
protected final String _bindHostname;
|
||||||
protected final Map<SelectionKey, ServerSocketChannel> _channels = Maps.newHashMap();
|
protected final Map<SelectionKey, ServerSocketChannel> _channels = Maps.newHashMap();
|
||||||
|
|||||||
@@ -157,10 +157,11 @@ public class PresentsServer
|
|||||||
// provide our client manager with the injector it needs
|
// provide our client manager with the injector it needs
|
||||||
_clmgr.setInjector(injector);
|
_clmgr.setInjector(injector);
|
||||||
|
|
||||||
// configure our connection manager
|
// if we have a connection manager that handles its own socket accepting, initialize it
|
||||||
|
// with the hostname and ports on which to listen
|
||||||
if (_conmgr instanceof BindingConnectionManager) {
|
if (_conmgr instanceof BindingConnectionManager) {
|
||||||
((BindingConnectionManager)_conmgr).init(getBindHostname(), getDatagramHostname(),
|
((BindingConnectionManager)_conmgr).init(
|
||||||
getListenPorts(), getDatagramPorts());
|
getBindHostname(), getDatagramHostname(), getListenPorts(), getDatagramPorts());
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize the time base services
|
// initialize the time base services
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import static com.threerings.presents.Log.log;
|
|||||||
public class BindingConnectionManager extends ConnectionManager
|
public class BindingConnectionManager extends ConnectionManager
|
||||||
{
|
{
|
||||||
@Inject public BindingConnectionManager (Lifecycle cycle, ReportManager repmgr,
|
@Inject public BindingConnectionManager (Lifecycle cycle, ReportManager repmgr,
|
||||||
IncomingEventWaitHolder incomingEventWait)
|
IncomingEventWaitHolder incomingEventWait)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
super(cycle, repmgr, incomingEventWait);
|
super(cycle, repmgr, incomingEventWait);
|
||||||
@@ -89,6 +89,7 @@ public class BindingConnectionManager extends ConnectionManager
|
|||||||
if (!_socketAcceptor.listen()) {
|
if (!_socketAcceptor.listen()) {
|
||||||
log.warning("ConnectionManager failed to bind to any ports. Shutting down.");
|
log.warning("ConnectionManager failed to bind to any ports. Shutting down.");
|
||||||
_server.queueShutdown();
|
_server.queueShutdown();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// open up the datagram ports as well
|
// open up the datagram ports as well
|
||||||
for (int port : _datagramPorts) {
|
for (int port : _datagramPorts) {
|
||||||
@@ -105,7 +106,10 @@ public class BindingConnectionManager extends ConnectionManager
|
|||||||
@Override
|
@Override
|
||||||
protected void processIncomingEvents (long iterStamp)
|
protected void processIncomingEvents (long iterStamp)
|
||||||
{
|
{
|
||||||
|
// first check for any new sockets, ready to be accepted
|
||||||
_socketAcceptor.tick(iterStamp);
|
_socketAcceptor.tick(iterStamp);
|
||||||
|
|
||||||
|
// then do our standard processing for existing connected sockets
|
||||||
super.processIncomingEvents(iterStamp);
|
super.processIncomingEvents(iterStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,6 @@ import com.threerings.presents.server.ReportManager;
|
|||||||
import com.threerings.presents.util.DatagramSequencer;
|
import com.threerings.presents.util.DatagramSequencer;
|
||||||
|
|
||||||
import com.threerings.nio.SocketChannelAcceptor;
|
import com.threerings.nio.SocketChannelAcceptor;
|
||||||
import com.threerings.nio.SocketChannelAcceptor.SocketChannelHandler;
|
|
||||||
import com.threerings.nio.SelectorIterable;
|
import com.threerings.nio.SelectorIterable;
|
||||||
import com.threerings.nio.SelectorIterable.SelectFailureHandler;
|
import com.threerings.nio.SelectorIterable.SelectFailureHandler;
|
||||||
|
|
||||||
@@ -80,15 +79,16 @@ import static com.threerings.presents.Log.log;
|
|||||||
* connection objects interact closely with the connection manager because network I/O is done via
|
* connection objects interact closely with the connection manager because network I/O is done via
|
||||||
* a poll()-like mechanism rather than via threads.<p>
|
* a poll()-like mechanism rather than via threads.<p>
|
||||||
*
|
*
|
||||||
* ConnectionManager doesn't handle accepting tcp connections; it expects an external entity to do
|
* ConnectionManager doesn't directly accept TCP connections; it expects an external entity to do
|
||||||
* so and call its <code>handleSocketChannel</code> method.
|
* so and call its {@link #handleSocketChannel} method.
|
||||||
*
|
*
|
||||||
* @see BindingConnectionManager
|
* @see BindingConnectionManager
|
||||||
* @see SocketChannelAcceptor
|
* @see SocketChannelAcceptor
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ConnectionManager extends LoopingThread
|
public class ConnectionManager extends LoopingThread
|
||||||
implements Lifecycle.ShutdownComponent, ReportManager.Reporter, SocketChannelHandler
|
implements Lifecycle.ShutdownComponent, ReportManager.Reporter,
|
||||||
|
SocketChannelAcceptor.SocketChannelHandler
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a connection manager instance.
|
* Creates a connection manager instance.
|
||||||
@@ -100,8 +100,8 @@ public class ConnectionManager extends LoopingThread
|
|||||||
super("ConnectionManager");
|
super("ConnectionManager");
|
||||||
cycle.addComponent(this);
|
cycle.addComponent(this);
|
||||||
repmgr.registerReporter(this);
|
repmgr.registerReporter(this);
|
||||||
_selectorSelector = new SelectorIterable(_selector, incomingEventWait.value,
|
_selectorSelector = new SelectorIterable(
|
||||||
_failureHandler);
|
_selector, incomingEventWait.value, _failureHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,16 +224,7 @@ public class ConnectionManager extends LoopingThread
|
|||||||
report.append(bytesOut*1000/sinceLast).append(" bps\n");
|
report.append(bytesOut*1000/sinceLast).append(" bps\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override // from LoopingThread
|
// from interface SocketChannelAcceptor.SocketChannelHandler
|
||||||
public boolean isRunning ()
|
|
||||||
{
|
|
||||||
// Prevent exiting our thread until the object manager is done.
|
|
||||||
return super.isRunning() || _omgr.isRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by our SocketChannelAcceptor when a new connection has been accepted on its socket.
|
|
||||||
*/
|
|
||||||
public void handleSocketChannel (SocketChannel channel, long when)
|
public void handleSocketChannel (SocketChannel channel, long when)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -260,6 +251,13 @@ public class ConnectionManager extends LoopingThread
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override // from LoopingThread
|
||||||
|
public boolean isRunning ()
|
||||||
|
{
|
||||||
|
// Prevent exiting our thread until the object manager is done.
|
||||||
|
return super.isRunning() || _omgr.isRunning();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the authentication process on the specified connection. This is called by {@link
|
* Performs the authentication process on the specified connection. This is called by {@link
|
||||||
* AuthingConnection} itself once it receives its auth request.
|
* AuthingConnection} itself once it receives its auth request.
|
||||||
|
|||||||
Reference in New Issue
Block a user