You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ro...@apache.org on 2007/02/18 18:04:32 UTC

svn commit: r508919 - in /jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http: conn/ impl/client/ impl/conn/

Author: rolandw
Date: Sun Feb 18 09:04:31 2007
New Revision: 508919

URL: http://svn.apache.org/viewvc?view=rev&rev=508919
Log:
connection can release itself, stream can be aborted

Added:
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java   (with props)
Modified:
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/BasicEofSensorWatcher.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorInputStream.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorWatcher.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/AbstractClientConnectionAdapter.java
    jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/BasicEofSensorWatcher.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/BasicEofSensorWatcher.java?view=diff&rev=508919&r1=508918&r2=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/BasicEofSensorWatcher.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/BasicEofSensorWatcher.java Sun Feb 18 09:04:31 2007
@@ -52,9 +52,6 @@
     /** The connection to auto-release. */
     protected ManagedClientConnection managedConn;
 
-    /** The connection manager to release to. */
-    protected ClientConnectionManager connManager;
-
     /** Whether to keep the connection alive. */
     protected boolean attemptReuse;
 
@@ -64,22 +61,15 @@
      * Creates a new watcher for auto-releasing a connection.
      *
      * @param conn      the connection to auto-release
-     * @param mgr       the connection manager to release to
      * @param reuse     whether the connection should be re-used
      */
     public BasicEofSensorWatcher(ManagedClientConnection conn,
-                                 ClientConnectionManager mgr,
                                  boolean reuse) {
         if (conn == null)
             throw new IllegalArgumentException
                 ("Connection may not be null.");
-        if (mgr == null)
-            throw new IllegalArgumentException
-                ("Connection manager may not be null.");
 
         managedConn = conn;
-        //@@@ put a release method in the connection interface?
-        connManager = mgr;
         attemptReuse = reuse;
     }
 
@@ -96,7 +86,7 @@
                 managedConn.markReusable();
             }
         } finally {
-            connManager.releaseConnection(managedConn);
+            managedConn.releaseConnection();
         }
         return false;
     }
@@ -114,8 +104,17 @@
                 managedConn.markReusable();
             }
         } finally {
-            connManager.releaseConnection(managedConn);
+            managedConn.releaseConnection();
         }
+        return false;
+    }
+
+
+    // non-javadoc, see interface EofSensorWatcher
+    public boolean streamAbort(InputStream wrapped)
+        throws IOException {
+
+        managedConn.abortConnection();
         return false;
     }
 

Added: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java?view=auto&rev=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java (added)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java Sun Feb 18 09:04:31 2007
@@ -0,0 +1,82 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ *
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ *
+ */
+
+package org.apache.http.conn;
+
+import java.io.IOException;
+
+
+/**
+ * Interface for releasing a connection.
+ * This can be implemented by various "trigger" objects which are
+ * associated with a connection, for example a stream or an entity
+ * or the {@link ManagedClientConnection connection} itself.
+ * <br/>
+ * The methods in this interface can safely be called multiple times.
+ * The first invocation releases the connection, subsequent calls
+ * are ignored.
+ *
+ * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
+ *
+ *
+ * <!-- empty lines to avoid svn diff problems -->
+ * @version $Revision$
+ *
+ * @since 4.0
+ */
+public interface ConnectionReleaseTrigger {
+
+    /**
+     * Releases the connection with the option of keep-alive.
+     * This is a "graceful" release and may cause IO operations
+     * for consuming the remainder of a response entity.
+     * Use {@link #abortConnection abortConnection} for a hard release.
+     *
+     * @throws IOException      in case of an IO problem.
+     *         The connection will be released anyway.
+     */
+    void releaseConnection()
+        throws IOException
+        ;
+
+    /**
+     * Releases the connection without the option of keep-alive.
+     * This is a "hard" release that implies a shutdown of the connection.
+     * Use {@link #releaseConnection releaseConnection} for a graceful release.
+     *
+     * @throws IOException      in case of an IO problem.
+     *         The connection will be released anyway.
+     */
+    void abortConnection()
+        throws IOException
+        ;
+
+
+} // interface ConnectionReleaseTrigger

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ConnectionReleaseTrigger.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorInputStream.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorInputStream.java?view=diff&rev=508919&r1=508918&r2=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorInputStream.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorInputStream.java Sun Feb 18 09:04:31 2007
@@ -60,9 +60,10 @@
  *
  * @since 4.0
  */
-public class EofSensorInputStream extends InputStream {
-    // don't use FilterInputStream as the base class, we'd have to
-    // override markSupported(), mark(), and reset() to disable them
+// don't use FilterInputStream as the base class, we'd have to
+// override markSupported(), mark(), and reset() to disable them
+public class EofSensorInputStream extends InputStream
+    implements ConnectionReleaseTrigger {
 
     /**
      * The wrapped input stream, while accessible.
@@ -244,6 +245,56 @@
                 wrappedStream = null;
             }
         }
+    }
+
+
+    /**
+     * Detects stream abort and notifies the watcher.
+     * There's not much to detect since this is called by
+     * {@link #abortConnection abortConnection}.
+     * The watcher will only be notified if this stream is aborted
+     * for the first time and before EOF has been detected or the
+     * stream has been {@link #close closed} gracefully.
+     * This stream will be detached from the underlying stream to prevent
+     * multiple notifications to the watcher.
+     *
+     * @throws IOException
+     *          in case of an IO problem on closing the underlying stream
+     */
+    protected void checkAbort() throws IOException {
+
+        if (wrappedStream != null) {
+            try {
+                boolean scws = true; // should close wrapped stream?
+                if (eofWatcher != null)
+                    scws = eofWatcher.streamAbort(wrappedStream);
+                if (scws)
+                    wrappedStream.close();
+            } finally {
+                wrappedStream = null;
+            }
+        }
+    }
+
+
+    /**
+     * Same as {@link #close close()}.
+     */
+    public void releaseConnection() throws IOException {
+        this.close();
+    }
+
+    /**
+     * Aborts this stream.
+     * This is a special version of {@link #close close()} which prevents
+     * re-use of the underlying connection, if any. Calling this method
+     * indicates that there should be no attempt to read until the end of
+     * the stream.
+     */
+    public void abortConnection() throws IOException {
+        // tolerate multiple calls
+        selfClosed = true;
+        checkAbort();
     }
 
 } // class EOFSensorInputStream

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorWatcher.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorWatcher.java?view=diff&rev=508919&r1=508918&r2=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorWatcher.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/EofSensorWatcher.java Sun Feb 18 09:04:31 2007
@@ -85,4 +85,25 @@
         throws IOException
         ;
 
+
+    /**
+     * Indicates that the {@link EofSensorInputStream stream} is aborted.
+     * This method will be called only if EOF was <i>not</i> detected
+     * before aborting. Otherwise, {@link #eofDetected eofDetected} is called.
+     *
+     * @param wrapped   the underlying stream which has not reached EOF
+     *
+     * @return  <code>true</code> if <code>wrapped</code> should be closed,
+     *          <code>false</code> if it should be left alone
+     *
+     * @throws IOException
+     *         in case of an IO problem, for example if the watcher itself
+     *         closes the underlying stream. The caller will leave the
+     *         wrapped stream alone, as if <code>false</code> was returned.
+     */
+    boolean streamAbort(InputStream wrapped)
+        throws IOException
+        ;
+
+
 } // interface EofSensorWatcher

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java?view=diff&rev=508919&r1=508918&r2=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/conn/ManagedClientConnection.java Sun Feb 18 09:04:31 2007
@@ -51,8 +51,8 @@
  *
  * @since 4.0
  */
-public interface ManagedClientConnection
-    extends HttpClientConnection, HttpInetConnection {
+public interface ManagedClientConnection extends
+    HttpClientConnection, HttpInetConnection, ConnectionReleaseTrigger {
 
 
     /**
@@ -130,18 +130,6 @@
     void layerProtocol(HttpContext context, HttpParams params)
         throws IOException
         ;
-
-
-    /* *
-     * Releases this connection back to it's connection manager.
-     *
-     * @throws IllegalStateException
-     *          if this connection is already released
-     * /
-    boolean release()
-        throws IllegalStateException
-        ;
-    */
 
 
     /**

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java?view=diff&rev=508919&r1=508918&r2=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/client/DefaultClientRequestDirector.java Sun Feb 18 09:04:31 2007
@@ -426,10 +426,10 @@
                 BasicHttpEntity bhe = (BasicHttpEntity) entity;
                 //@@@ evaluate connection re-use strategy
                 boolean reuse = false;
-                BasicEofSensorWatcher esw = new BasicEofSensorWatcher
-                    (mcc, connManager, reuse);
-                EofSensorInputStream esis = new EofSensorInputStream
-                    (bhe.getContent(), esw);
+                BasicEofSensorWatcher esw =
+                    new BasicEofSensorWatcher(mcc, reuse);
+                EofSensorInputStream esis =
+                    new EofSensorInputStream(bhe.getContent(), esw);
                 bhe.setContent(esis);
             }
         } else {

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/AbstractClientConnectionAdapter.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/AbstractClientConnectionAdapter.java?view=diff&rev=508919&r1=508918&r2=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/AbstractClientConnectionAdapter.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/AbstractClientConnectionAdapter.java Sun Feb 18 09:04:31 2007
@@ -41,6 +41,7 @@
 import org.apache.http.params.HttpParams;
 import org.apache.http.conn.OperatedClientConnection;
 import org.apache.http.conn.ManagedClientConnection;
+import org.apache.http.conn.ClientConnectionManager;
 
 
 
@@ -57,6 +58,11 @@
  * as indicated by {@link #markReusable markReusable} and queried by
  * {@link #isMarkedReusable isMarkedReusable}.
  * All send and receive operations will automatically clear the mark.
+ * <br/>
+ * Connection release calls are delegated to the connection manager,
+ * if there is one. {@link #abortConnection abortConnection} will
+ * clear the reusability mark first. The connection manager is
+ * expected to tolerate multiple calls to the release method.
  *
  * @author <a href="mailto:rolandw at apache.org">Roland Weber</a>
  *
@@ -69,6 +75,9 @@
 public abstract class AbstractClientConnectionAdapter
     implements ManagedClientConnection {
 
+    /** The connection manager, if any. */
+    protected final ClientConnectionManager connManager;
+
     /** The wrapped connection. */
     protected OperatedClientConnection wrappedConnection;
 
@@ -81,10 +90,13 @@
      * The adapter is initially <i>not</i>
      * {@link #isMarkedReusable marked} as reusable.
      *
+     * @param mgr       the connection manager, or <code>null</code>
      * @param conn      the connection to wrap, or <code>null</code>
      */
-    protected AbstractClientConnectionAdapter(OperatedClientConnection conn) {
+    protected AbstractClientConnectionAdapter(ClientConnectionManager mgr,
+                                              OperatedClientConnection conn) {
 
+        connManager = mgr;
         wrappedConnection = conn;
         markedReusable = false;
 
@@ -223,6 +235,27 @@
     // non-javadoc, see interface ManagedClientConnection
     public boolean isMarkedReusable() {
         return markedReusable;
+    }
+
+    // non-javadoc, see interface ConnectionReleaseTrigger
+    public void releaseConnection() {
+        if (connManager == null)
+            throw new IllegalStateException
+                ("No connection manager to release to.");
+
+        connManager.releaseConnection(this);
+    }
+
+    // non-javadoc, see interface ConnectionReleaseTrigger
+    public void abortConnection() {
+
+        unmarkReusable();
+
+        if (connManager == null)
+            throw new IllegalStateException
+                ("No connection manager to release to.");
+
+        connManager.releaseConnection(this);
     }
 
 } // class AbstractClientConnectionAdapter

Modified: jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java
URL: http://svn.apache.org/viewvc/jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java?view=diff&rev=508919&r1=508918&r2=508919
==============================================================================
--- jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java (original)
+++ jakarta/httpcomponents/httpclient/trunk/src/java/org/apache/http/impl/conn/ThreadSafeClientConnManager.java Sun Feb 18 09:04:31 2007
@@ -1316,7 +1316,7 @@
          * @param entry   the pool entry for the connection being wrapped
          */
         protected HttpConnectionAdapter(TrackingPoolEntry entry) {
-            super(entry.connection);
+            super(ThreadSafeClientConnManager.this, entry.connection);
             poolEntry = entry;
             super.markedReusable = true;
         }