View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.http.impl.conn;
28  
29  import java.io.IOException;
30  import java.util.HashMap;
31  import java.util.Map;
32  import java.util.Map.Entry;
33  import java.util.concurrent.TimeUnit;
34  
35  import org.apache.commons.logging.Log;
36  import org.apache.commons.logging.LogFactory;
37  import org.apache.http.HttpConnection;
38  
39  // Currently only used by AbstractConnPool
40  /**
41   * A helper class for connection managers to track idle connections.
42   *
43   * <p>This class is not synchronized.</p>
44   *
45   * @see org.apache.http.conn.ClientConnectionManager#closeIdleConnections
46   *
47   * @since 4.0
48   *
49   * @deprecated (4.1)  no longer used
50   */
51  @Deprecated
52  public class IdleConnectionHandler {
53  
54      private final Log log = LogFactory.getLog(getClass());
55  
56      /** Holds connections and the time they were added. */
57      private final Map<HttpConnection,TimeValues> connectionToTimes;
58  
59  
60      public IdleConnectionHandler() {
61          super();
62          connectionToTimes = new HashMap<HttpConnection,TimeValues>();
63      }
64  
65      /**
66       * Registers the given connection with this handler.  The connection will be held until
67       * {@link #remove} or {@link #closeIdleConnections} is called.
68       *
69       * @param connection the connection to add
70       *
71       * @see #remove
72       */
73      public void add(final HttpConnection connection, final long validDuration, final TimeUnit unit) {
74  
75          final long timeAdded = System.currentTimeMillis();
76  
77          if (log.isDebugEnabled()) {
78              log.debug("Adding connection at: " + timeAdded);
79          }
80  
81          connectionToTimes.put(connection, new TimeValues(timeAdded, validDuration, unit));
82      }
83  
84      /**
85       * Removes the given connection from the list of connections to be closed when idle.
86       * This will return true if the connection is still valid, and false
87       * if the connection should be considered expired and not used.
88       *
89       * @param connection
90       * @return True if the connection is still valid.
91       */
92      public boolean remove(final HttpConnection connection) {
93          final TimeValues times = connectionToTimes.remove(connection);
94          if(times == null) {
95              log.warn("Removing a connection that never existed!");
96              return true;
97          } else {
98              return System.currentTimeMillis() <= times.timeExpires;
99          }
100     }
101 
102     /**
103      * Removes all connections referenced by this handler.
104      */
105     public void removeAll() {
106         this.connectionToTimes.clear();
107     }
108 
109     /**
110      * Closes connections that have been idle for at least the given amount of time.
111      *
112      * @param idleTime the minimum idle time, in milliseconds, for connections to be closed
113      */
114     public void closeIdleConnections(final long idleTime) {
115 
116         // the latest time for which connections will be closed
117         final long idleTimeout = System.currentTimeMillis() - idleTime;
118 
119         if (log.isDebugEnabled()) {
120             log.debug("Checking for connections, idle timeout: "  + idleTimeout);
121         }
122 
123         for (final Entry<HttpConnection, TimeValues> entry : connectionToTimes.entrySet()) {
124             final HttpConnection conn = entry.getKey();
125             final TimeValues times = entry.getValue();
126             final long connectionTime = times.timeAdded;
127             if (connectionTime <= idleTimeout) {
128                 if (log.isDebugEnabled()) {
129                     log.debug("Closing idle connection, connection time: "  + connectionTime);
130                 }
131                 try {
132                     conn.close();
133                 } catch (final IOException ex) {
134                     log.debug("I/O error closing connection", ex);
135                 }
136             }
137         }
138     }
139 
140 
141     public void closeExpiredConnections() {
142         final long now = System.currentTimeMillis();
143         if (log.isDebugEnabled()) {
144             log.debug("Checking for expired connections, now: "  + now);
145         }
146 
147         for (final Entry<HttpConnection, TimeValues> entry : connectionToTimes.entrySet()) {
148             final HttpConnection conn = entry.getKey();
149             final TimeValues times = entry.getValue();
150             if(times.timeExpires <= now) {
151                 if (log.isDebugEnabled()) {
152                     log.debug("Closing connection, expired @: "  + times.timeExpires);
153                 }
154                 try {
155                     conn.close();
156                 } catch (final IOException ex) {
157                     log.debug("I/O error closing connection", ex);
158                 }
159             }
160         }
161     }
162 
163     private static class TimeValues {
164         private final long timeAdded;
165         private final long timeExpires;
166 
167         /**
168          * @param now The current time in milliseconds
169          * @param validDuration The duration this connection is valid for
170          * @param validUnit The unit of time the duration is specified in.
171          */
172         TimeValues(final long now, final long validDuration, final TimeUnit validUnit) {
173             this.timeAdded = now;
174             if(validDuration > 0) {
175                 this.timeExpires = now + validUnit.toMillis(validDuration);
176             } else {
177                 this.timeExpires = Long.MAX_VALUE;
178             }
179         }
180     }
181 }