Allow the select wait for ConnectionManager to be injected eg

bind(Integer.class).annotatedWith(IncomingEventWait.class).toInstance(1);
will make the select wait 1 millisecond.

Don't wait for the select for datagrams or sockets in BindingConnectionManager as there's already a
wait on the ConnectionManager's select.



git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6163 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Charlie Groves
2010-09-16 18:23:10 +00:00
parent fc13de8b9a
commit 68a5c21cda
8 changed files with 50 additions and 19 deletions
@@ -34,12 +34,13 @@ public class DatagramAcceptor extends SelectAcceptor
* @param failureHandler - called when the selector is irredemably broken. * @param failureHandler - called when the selector is irredemably broken.
* @param hostname - the hostname to bind to or null for all interfaces * @param hostname - the hostname to bind to or null for all interfaces
* @param ports - the ports to bind to, or an empty array to skip binding * @param ports - the ports to bind to, or an empty array to skip binding
* @param selectLoopTime - the amount of time to wait in select, or 0 to skip the wait at all.
*/ */
public DatagramAcceptor (DatagramHandler dgramHandler, SelectFailureHandler failureHandler, public DatagramAcceptor (DatagramHandler dgramHandler, SelectFailureHandler failureHandler,
String hostname, int[] ports) String hostname, int[] ports, int selectLoopTime)
throws IOException throws IOException
{ {
super(failureHandler, hostname, ports); super(failureHandler, hostname, ports, selectLoopTime);
_dgramHandler = dgramHandler; _dgramHandler = dgramHandler;
} }
@@ -20,7 +20,8 @@ import com.threerings.nio.SelectorIterable.SelectFailureHandler;
*/ */
public abstract class SelectAcceptor public abstract class SelectAcceptor
{ {
public SelectAcceptor (SelectFailureHandler failureHandler, String bindHostname, int[] ports) public SelectAcceptor (SelectFailureHandler failureHandler, String bindHostname, int[] ports,
int selectLoopTime)
throws IOException throws IOException
{ {
Preconditions.checkNotNull(ports, "Ports must be non-null."); Preconditions.checkNotNull(ports, "Ports must be non-null.");
@@ -28,7 +29,7 @@ public abstract class SelectAcceptor
_bindHostname = bindHostname; _bindHostname = bindHostname;
_ports = ports; _ports = ports;
_selectorSelector = new SelectorIterable(_selector, 100, failureHandler); _selectorSelector = new SelectorIterable(_selector, selectLoopTime, failureHandler);
} }
/** /**
@@ -28,7 +28,7 @@ public class SelectorIterable
/** /**
* Creates an iterable for the given selector's selectedKeys. * Creates an iterable for the given selector's selectedKeys.
* @param selectLoopTime - the amount of time to wait in select. * @param selectLoopTime - the amount of time to wait in select, or 0 to skip the wait at all.
* @param handler - a callback for the Selector going awol. * @param handler - a callback for the Selector going awol.
*/ */
public SelectorIterable (Selector selector, int selectLoopTime, SelectFailureHandler handler) public SelectorIterable (Selector selector, int selectLoopTime, SelectFailureHandler handler)
@@ -49,7 +49,8 @@ public class SelectorIterable
// log.debug("Selecting from " + _selector.keys() + " (" + _selectLoopTime + ")."); // log.debug("Selecting from " + _selector.keys() + " (" + _selectLoopTime + ").");
// check for incoming network events // check for incoming network events
int eventCount = _selector.select(_selectLoopTime); int eventCount =
_selectLoopTime == 0 ? _selector.select(_selectLoopTime) : _selector.selectNow();
Set<SelectionKey> ready = _selector.selectedKeys(); Set<SelectionKey> ready = _selector.selectedKeys();
if (eventCount == 0 && ready.size() != 0) { if (eventCount == 0 && ready.size() != 0) {
log.warning("select() returned no selected sockets, but there are " log.warning("select() returned no selected sockets, but there are "
@@ -33,12 +33,13 @@ public class SocketChannelAcceptor extends SelectAcceptor
* @param failureHandler - called when the selector is irredemably broken. * @param failureHandler - called when the selector is irredemably broken.
* @param bindHostname - the hostname to bind to or null for all interfaces * @param bindHostname - the hostname to bind to or null for all interfaces
* @param ports - the ports to bind to, or an empty array to skip binding * @param ports - the ports to bind to, or an empty array to skip binding
* @param selectLoopTime - the amount of time to wait in select, or 0 to skip the wait at all.
*/ */
public SocketChannelAcceptor (SocketChannelHandler connectionHandler, public SocketChannelAcceptor (SocketChannelHandler connectionHandler,
SelectFailureHandler failureHandler, String bindHostname, int[] ports) SelectFailureHandler failureHandler, String bindHostname, int[] ports, int selectLoopTime)
throws IOException throws IOException
{ {
super(failureHandler, bindHostname, ports); super(failureHandler, bindHostname, ports, selectLoopTime);
_connHandler = connectionHandler; _connHandler = connectionHandler;
} }
@@ -43,6 +43,7 @@ import com.threerings.presents.dobj.RootDObjectManager;
import com.threerings.presents.server.PresentsDObjectMgr.LongRunnable; import com.threerings.presents.server.PresentsDObjectMgr.LongRunnable;
import com.threerings.presents.server.net.BindingConnectionManager; import com.threerings.presents.server.net.BindingConnectionManager;
import com.threerings.presents.server.net.ConnectionManager; import com.threerings.presents.server.net.ConnectionManager;
import com.threerings.presents.server.net.IncomingEventWait;
import com.threerings.crowd.server.PlaceManager; import com.threerings.crowd.server.PlaceManager;
@@ -5,13 +5,11 @@ import java.io.IOException;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.samskivert.util.Lifecycle; import com.samskivert.util.Lifecycle;
import com.threerings.presents.server.ReportManager; import com.threerings.presents.server.ReportManager;
import com.threerings.nio.SocketChannelAcceptor;
import com.threerings.nio.DatagramAcceptor; import com.threerings.nio.DatagramAcceptor;
import com.threerings.nio.SocketChannelAcceptor;
import static com.threerings.presents.Log.log; import static com.threerings.presents.Log.log;
@@ -21,11 +19,11 @@ import static com.threerings.presents.Log.log;
@Singleton @Singleton
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)
throws IOException throws IOException
{ {
super(cycle, repmgr); super(cycle, repmgr, incomingEventWait);
} }
@Override @Override
@@ -67,10 +65,13 @@ public class BindingConnectionManager extends ConnectionManager
Preconditions.checkNotNull(datagramPorts, "Datagram ports must be non-null. " + Preconditions.checkNotNull(datagramPorts, "Datagram ports must be non-null. " +
"Pass a zero-length array to bind no datagram ports."); "Pass a zero-length array to bind no datagram ports.");
// Listen for socket connections and datagram connections, but don't wait for anything to
// show up since that check is occurring as part of ConnectionManager's incoming event loop
// that already has a wait.
_socketAcceptor = new SocketChannelAcceptor(this, _failureHandler, socketHostname, _socketAcceptor = new SocketChannelAcceptor(this, _failureHandler, socketHostname,
socketPorts); socketPorts, 0);
_dgramAcceptor = new DatagramAcceptor(this, _failureHandler, datagramHostname, _dgramAcceptor = new DatagramAcceptor(this, _failureHandler, datagramHostname,
datagramPorts); datagramPorts, 0);
} }
@Override @Override
@@ -39,7 +39,6 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
import com.samskivert.util.IntMap; import com.samskivert.util.IntMap;
import com.samskivert.util.IntMaps; import com.samskivert.util.IntMaps;
import com.samskivert.util.Invoker; import com.samskivert.util.Invoker;
@@ -100,13 +99,15 @@ public class ConnectionManager extends LoopingThread
/** /**
* Creates a connection manager instance. * Creates a connection manager instance.
*/ */
@Inject public ConnectionManager (Lifecycle cycle, ReportManager repmgr) @Inject public ConnectionManager (Lifecycle cycle, ReportManager repmgr,
IncomingEventWaitHolder incomingEventWait)
throws IOException throws IOException
{ {
super("ConnectionManager"); super("ConnectionManager");
cycle.addComponent(this); cycle.addComponent(this);
repmgr.registerReporter(this); repmgr.registerReporter(this);
_selectorSelector = new SelectorIterable(_selector, SELECT_LOOP_TIME, _failureHandler); _selectorSelector = new SelectorIterable(_selector, incomingEventWait.value,
_failureHandler);
} }
/** /**
@@ -997,6 +998,12 @@ public class ConnectionManager extends LoopingThread
} }
}; };
/** Helper for Guice to allow the incoming event wait to be injected optionally. */
protected static class IncomingEventWaitHolder
{
@Inject(optional=true) @IncomingEventWait int value = SELECT_LOOP_TIME;
}
/** Handles client authentication. The base authenticator is injected but optional services /** Handles client authentication. The base authenticator is injected but optional services
* like the PeerManager may replace this authenticator with one that intercepts certain types * like the PeerManager may replace this authenticator with one that intercepts certain types
* of authentication and then passes normal authentications through. */ * of authentication and then passes normal authentications through. */
@@ -0,0 +1,18 @@
package com.threerings.presents.server.net;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
/**
* Identifies the amount of time to wait for incoming events in ConnectionManager's select.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@BindingAnnotation
public @interface IncomingEventWait
{
}