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