From 68a5c21cda82e7542f5941a9fc7a57852fc32162 Mon Sep 17 00:00:00 2001 From: Charlie Groves Date: Thu, 16 Sep 2010 18:23:10 +0000 Subject: [PATCH] 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 --- .../com/threerings/nio/DatagramAcceptor.java | 5 +++-- .../com/threerings/nio/SelectAcceptor.java | 5 +++-- .../com/threerings/nio/SelectorIterable.java | 5 +++-- .../threerings/nio/SocketChannelAcceptor.java | 5 +++-- .../presents/server/PresentsServer.java | 1 + .../server/net/BindingConnectionManager.java | 17 +++++++++-------- .../presents/server/net/ConnectionManager.java | 13 ++++++++++--- .../presents/server/net/IncomingEventWait.java | 18 ++++++++++++++++++ 8 files changed, 50 insertions(+), 19 deletions(-) create mode 100644 src/java/com/threerings/presents/server/net/IncomingEventWait.java diff --git a/src/java/com/threerings/nio/DatagramAcceptor.java b/src/java/com/threerings/nio/DatagramAcceptor.java index f1217cfac..1f5ac0494 100644 --- a/src/java/com/threerings/nio/DatagramAcceptor.java +++ b/src/java/com/threerings/nio/DatagramAcceptor.java @@ -34,12 +34,13 @@ public class DatagramAcceptor extends SelectAcceptor * @param failureHandler - called when the selector is irredemably broken. * @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 selectLoopTime - the amount of time to wait in select, or 0 to skip the wait at all. */ public DatagramAcceptor (DatagramHandler dgramHandler, SelectFailureHandler failureHandler, - String hostname, int[] ports) + String hostname, int[] ports, int selectLoopTime) throws IOException { - super(failureHandler, hostname, ports); + super(failureHandler, hostname, ports, selectLoopTime); _dgramHandler = dgramHandler; } diff --git a/src/java/com/threerings/nio/SelectAcceptor.java b/src/java/com/threerings/nio/SelectAcceptor.java index ac72d26e8..1f381d8ae 100644 --- a/src/java/com/threerings/nio/SelectAcceptor.java +++ b/src/java/com/threerings/nio/SelectAcceptor.java @@ -20,7 +20,8 @@ import com.threerings.nio.SelectorIterable.SelectFailureHandler; */ public abstract class SelectAcceptor { - public SelectAcceptor (SelectFailureHandler failureHandler, String bindHostname, int[] ports) + public SelectAcceptor (SelectFailureHandler failureHandler, String bindHostname, int[] ports, + int selectLoopTime) throws IOException { Preconditions.checkNotNull(ports, "Ports must be non-null."); @@ -28,7 +29,7 @@ public abstract class SelectAcceptor _bindHostname = bindHostname; _ports = ports; - _selectorSelector = new SelectorIterable(_selector, 100, failureHandler); + _selectorSelector = new SelectorIterable(_selector, selectLoopTime, failureHandler); } /** diff --git a/src/java/com/threerings/nio/SelectorIterable.java b/src/java/com/threerings/nio/SelectorIterable.java index 5d076ec38..143a2cb21 100644 --- a/src/java/com/threerings/nio/SelectorIterable.java +++ b/src/java/com/threerings/nio/SelectorIterable.java @@ -28,7 +28,7 @@ public class SelectorIterable /** * 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. */ public SelectorIterable (Selector selector, int selectLoopTime, SelectFailureHandler handler) @@ -49,7 +49,8 @@ public class SelectorIterable // log.debug("Selecting from " + _selector.keys() + " (" + _selectLoopTime + ")."); // check for incoming network events - int eventCount = _selector.select(_selectLoopTime); + int eventCount = + _selectLoopTime == 0 ? _selector.select(_selectLoopTime) : _selector.selectNow(); Set ready = _selector.selectedKeys(); if (eventCount == 0 && ready.size() != 0) { log.warning("select() returned no selected sockets, but there are " diff --git a/src/java/com/threerings/nio/SocketChannelAcceptor.java b/src/java/com/threerings/nio/SocketChannelAcceptor.java index 07fc040e0..10fe62acf 100644 --- a/src/java/com/threerings/nio/SocketChannelAcceptor.java +++ b/src/java/com/threerings/nio/SocketChannelAcceptor.java @@ -33,12 +33,13 @@ public class SocketChannelAcceptor extends SelectAcceptor * @param failureHandler - called when the selector is irredemably broken. * @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 selectLoopTime - the amount of time to wait in select, or 0 to skip the wait at all. */ public SocketChannelAcceptor (SocketChannelHandler connectionHandler, - SelectFailureHandler failureHandler, String bindHostname, int[] ports) + SelectFailureHandler failureHandler, String bindHostname, int[] ports, int selectLoopTime) throws IOException { - super(failureHandler, bindHostname, ports); + super(failureHandler, bindHostname, ports, selectLoopTime); _connHandler = connectionHandler; } diff --git a/src/java/com/threerings/presents/server/PresentsServer.java b/src/java/com/threerings/presents/server/PresentsServer.java index f84dde9e5..a22199049 100644 --- a/src/java/com/threerings/presents/server/PresentsServer.java +++ b/src/java/com/threerings/presents/server/PresentsServer.java @@ -43,6 +43,7 @@ import com.threerings.presents.dobj.RootDObjectManager; import com.threerings.presents.server.PresentsDObjectMgr.LongRunnable; import com.threerings.presents.server.net.BindingConnectionManager; import com.threerings.presents.server.net.ConnectionManager; +import com.threerings.presents.server.net.IncomingEventWait; import com.threerings.crowd.server.PlaceManager; diff --git a/src/java/com/threerings/presents/server/net/BindingConnectionManager.java b/src/java/com/threerings/presents/server/net/BindingConnectionManager.java index 5f8b719f1..8575800eb 100644 --- a/src/java/com/threerings/presents/server/net/BindingConnectionManager.java +++ b/src/java/com/threerings/presents/server/net/BindingConnectionManager.java @@ -5,13 +5,11 @@ import java.io.IOException; import com.google.common.base.Preconditions; import com.google.inject.Inject; import com.google.inject.Singleton; - import com.samskivert.util.Lifecycle; import com.threerings.presents.server.ReportManager; - -import com.threerings.nio.SocketChannelAcceptor; import com.threerings.nio.DatagramAcceptor; +import com.threerings.nio.SocketChannelAcceptor; import static com.threerings.presents.Log.log; @@ -21,11 +19,11 @@ import static com.threerings.presents.Log.log; @Singleton public class BindingConnectionManager extends ConnectionManager { - - @Inject public BindingConnectionManager (Lifecycle cycle, ReportManager repmgr) + @Inject public BindingConnectionManager (Lifecycle cycle, ReportManager repmgr, + IncomingEventWaitHolder incomingEventWait) throws IOException { - super(cycle, repmgr); + super(cycle, repmgr, incomingEventWait); } @Override @@ -67,10 +65,13 @@ public class BindingConnectionManager extends ConnectionManager Preconditions.checkNotNull(datagramPorts, "Datagram ports must be non-null. " + "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, - socketPorts); + socketPorts, 0); _dgramAcceptor = new DatagramAcceptor(this, _failureHandler, datagramHostname, - datagramPorts); + datagramPorts, 0); } @Override diff --git a/src/java/com/threerings/presents/server/net/ConnectionManager.java b/src/java/com/threerings/presents/server/net/ConnectionManager.java index 4728a513b..9b0317a4b 100644 --- a/src/java/com/threerings/presents/server/net/ConnectionManager.java +++ b/src/java/com/threerings/presents/server/net/ConnectionManager.java @@ -39,7 +39,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.inject.Inject; import com.google.inject.Singleton; - import com.samskivert.util.IntMap; import com.samskivert.util.IntMaps; import com.samskivert.util.Invoker; @@ -100,13 +99,15 @@ public class ConnectionManager extends LoopingThread /** * Creates a connection manager instance. */ - @Inject public ConnectionManager (Lifecycle cycle, ReportManager repmgr) + @Inject public ConnectionManager (Lifecycle cycle, ReportManager repmgr, + IncomingEventWaitHolder incomingEventWait) throws IOException { super("ConnectionManager"); cycle.addComponent(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 * like the PeerManager may replace this authenticator with one that intercepts certain types * of authentication and then passes normal authentications through. */ diff --git a/src/java/com/threerings/presents/server/net/IncomingEventWait.java b/src/java/com/threerings/presents/server/net/IncomingEventWait.java new file mode 100644 index 000000000..5a6da9b46 --- /dev/null +++ b/src/java/com/threerings/presents/server/net/IncomingEventWait.java @@ -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 +{ +}