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 }