From 67405dde9ba213331dab1fc46cb18c485070fd5b Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 05 Jun 2009 09:04:50 +0000
Subject: [PATCH] svn merge -r5333:5417 https://opends.dev.java.net/svn/opends/branches/b2.0
---
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java | 134 ++++++++++++++++++++++++++++++++++----------
1 files changed, 104 insertions(+), 30 deletions(-)
diff --git a/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java b/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
index 8d68346..47fbb80 100644
--- a/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
+++ b/opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -57,6 +57,9 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
@@ -66,6 +69,7 @@
import org.opends.server.api.AlertGenerator;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
+import org.opends.server.api.DirectoryThread;
import org.opends.server.api.KeyManagerProvider;
import org.opends.server.api.ServerShutdownListener;
import org.opends.server.api.TrustManagerProvider;
@@ -112,6 +116,34 @@
ServerShutdownListener, AlertGenerator {
/**
+ * Task run periodically by the connection finalizer.
+ */
+ private final class ConnectionFinalizerRunnable implements Runnable
+ {
+ public void run()
+ {
+ if (!connectionFinalizerActiveJobQueue.isEmpty())
+ {
+ for (Runnable r : connectionFinalizerActiveJobQueue)
+ {
+ r.run();
+ }
+ connectionFinalizerActiveJobQueue.clear();
+ }
+
+ // Switch the lists.
+ synchronized (connectionFinalizerLock)
+ {
+ List<Runnable> tmp = connectionFinalizerActiveJobQueue;
+ connectionFinalizerActiveJobQueue =
+ connectionFinalizerPendingJobQueue;
+ connectionFinalizerPendingJobQueue = tmp;
+ }
+
+ }
+ }
+
+ /**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
@@ -209,7 +241,7 @@
// The condition variable that will be used by the start method
// to wait for the socket port to be opened and ready to process
// requests before returning.
- private Object waitListen = new Object();
+ private final Object waitListen = new Object();
// The friendly name of this connection handler.
private String friendlyName;
@@ -222,6 +254,19 @@
private boolean sslConfig = false;
/**
+ * Connection finalizer thread.
+ * <p>
+ * This thread is defers closing clients for approximately 100ms. This
+ * gives the client a chance to close the connection themselves before
+ * the server thus avoiding leaving the server side in the TIME WAIT
+ * state.
+ */
+ private final Object connectionFinalizerLock = new Object();
+ private ScheduledExecutorService connectionFinalizer;
+ private List<Runnable> connectionFinalizerActiveJobQueue;
+ private List<Runnable> connectionFinalizerPendingJobQueue;
+
+ /**
* Creates a new instance of this LDAP connection handler. It must
* be initialized before it may be used.
*/
@@ -343,25 +388,10 @@
/**
- * Closes this connection handler so that it will no longer accept
- * new client connections. It may or may not disconnect existing
- * client connections based on the provided flag. Note, however,
- * that some connection handler implementations may not have any way
- * to continue processing requests from existing connections, in
- * which case they should always be closed regardless of the value
- * of the <CODE>closeConnections</CODE> flag.
- *
- * @param finalizeReason
- * The reason that this connection handler should be
- * finalized.
- * @param closeConnections
- * Indicates whether any established client connections
- * associated with the connection handler should also be
- * closed.
+ * {@inheritDoc}
*/
@Override
- public void finalizeConnectionHandler(Message finalizeReason,
- boolean closeConnections) {
+ public void finalizeConnectionHandler(Message finalizeReason) {
shutdownRequested = true;
currentConfig.removeLDAPChangeListener(this);
@@ -390,14 +420,21 @@
}
}
- if (closeConnections) {
- for (LDAPRequestHandler requestHandler : requestHandlers) {
- requestHandler.processServerShutdown(finalizeReason);
- }
- } else {
- for (LDAPRequestHandler requestHandler : requestHandlers) {
- requestHandler.registerShutdownListener();
- }
+ for (LDAPRequestHandler requestHandler : requestHandlers)
+ {
+ requestHandler.processServerShutdown(finalizeReason);
+ }
+
+ // Shutdown the connection finalizer and ensure that any pending
+ // unclosed connections are closed.
+ synchronized (connectionFinalizerLock)
+ {
+ connectionFinalizer.shutdown();
+ connectionFinalizer = null;
+
+ Runnable r = new ConnectionFinalizerRunnable();
+ r.run(); // Flush active queue.
+ r.run(); // Flush pending queue.
}
}
@@ -694,6 +731,21 @@
// listening to. This information can be displayed with jinfo.
System.setProperty(protocol + "_port", String.valueOf(listenPort));
+ // Create and start a connection finalizer thread for this
+ // connection handler.
+ connectionFinalizer =
+ Executors
+ .newSingleThreadScheduledExecutor(new DirectoryThread.Factory(
+ "LDAP Connection Finalizer for connection handler "
+ + toString()));
+
+ connectionFinalizerActiveJobQueue = new ArrayList<Runnable>();
+ connectionFinalizerPendingJobQueue = new ArrayList<Runnable>();
+
+ connectionFinalizer.scheduleWithFixedDelay(
+ new ConnectionFinalizerRunnable(), 100, 100,
+ TimeUnit.MILLISECONDS);
+
// Create and start the request handlers.
requestHandlers = new LDAPRequestHandler[numRequestHandlers];
for (int i = 0; i < numRequestHandlers; i++) {
@@ -1257,10 +1309,9 @@
ResultCode resCode = DirectoryServer.getServerErrorResultCode();
try {
String alias = config.getSSLCertNickname();
- if(config.isUseSSL())
- protocol += "+SSL";
- else if(config.isAllowStartTLS())
- protocol += "+TLS";
+ if (config.isUseSSL()) {
+ protocol = "LDAPS";
+ }
DN keyMgrDN = config.getKeyManagerProviderDN();
DN trustMgrDN = config.getTrustManagerProviderDN();
KeyManagerProvider<?> keyManagerProvider =
@@ -1301,4 +1352,27 @@
}
}
+
+
+ /**
+ * Enqueue a connection finalizer which will be invoked after a short delay.
+ *
+ * @param r The connection finalizer runnable.
+ */
+ void registerConnectionFinalizer(Runnable r)
+ {
+ synchronized (connectionFinalizerLock)
+ {
+ if (connectionFinalizer != null)
+ {
+ connectionFinalizerPendingJobQueue.add(r);
+ }
+ else
+ {
+ // Already finalized - invoked immediately.
+ r.run();
+ }
+ }
+ }
+
}
--
Gitblit v1.10.0