| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed 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. |
| */ |
| |
| /** |
| * Hangs onto idle live connections for a little while |
| */ |
| |
| package android.net.http; |
| |
| import org.apache.http.HttpHost; |
| |
| import android.os.SystemClock; |
| |
| /** |
| * {@hide} |
| */ |
| class IdleCache { |
| |
| class Entry { |
| HttpHost mHost; |
| Connection mConnection; |
| long mTimeout; |
| }; |
| |
| private final static int IDLE_CACHE_MAX = 8; |
| |
| /* Allow five consecutive empty queue checks before shutdown */ |
| private final static int EMPTY_CHECK_MAX = 5; |
| |
| /* six second timeout for connections */ |
| private final static int TIMEOUT = 6 * 1000; |
| private final static int CHECK_INTERVAL = 2 * 1000; |
| private Entry[] mEntries = new Entry[IDLE_CACHE_MAX]; |
| |
| private int mCount = 0; |
| |
| private IdleReaper mThread = null; |
| |
| /* stats */ |
| private int mCached = 0; |
| private int mReused = 0; |
| |
| IdleCache() { |
| for (int i = 0; i < IDLE_CACHE_MAX; i++) { |
| mEntries[i] = new Entry(); |
| } |
| } |
| |
| /** |
| * Caches connection, if there is room. |
| * @return true if connection cached |
| */ |
| synchronized boolean cacheConnection( |
| HttpHost host, Connection connection) { |
| |
| boolean ret = false; |
| |
| if (HttpLog.LOGV) { |
| HttpLog.v("IdleCache size " + mCount + " host " + host); |
| } |
| |
| if (mCount < IDLE_CACHE_MAX) { |
| long time = SystemClock.uptimeMillis(); |
| for (int i = 0; i < IDLE_CACHE_MAX; i++) { |
| Entry entry = mEntries[i]; |
| if (entry.mHost == null) { |
| entry.mHost = host; |
| entry.mConnection = connection; |
| entry.mTimeout = time + TIMEOUT; |
| mCount++; |
| if (HttpLog.LOGV) mCached++; |
| ret = true; |
| if (mThread == null) { |
| mThread = new IdleReaper(); |
| mThread.start(); |
| } |
| break; |
| } |
| } |
| } |
| return ret; |
| } |
| |
| synchronized Connection getConnection(HttpHost host) { |
| Connection ret = null; |
| |
| if (mCount > 0) { |
| for (int i = 0; i < IDLE_CACHE_MAX; i++) { |
| Entry entry = mEntries[i]; |
| HttpHost eHost = entry.mHost; |
| if (eHost != null && eHost.equals(host)) { |
| ret = entry.mConnection; |
| entry.mHost = null; |
| entry.mConnection = null; |
| mCount--; |
| if (HttpLog.LOGV) mReused++; |
| break; |
| } |
| } |
| } |
| return ret; |
| } |
| |
| synchronized void clear() { |
| for (int i = 0; mCount > 0 && i < IDLE_CACHE_MAX; i++) { |
| Entry entry = mEntries[i]; |
| if (entry.mHost != null) { |
| entry.mHost = null; |
| entry.mConnection.closeConnection(); |
| entry.mConnection = null; |
| mCount--; |
| } |
| } |
| } |
| |
| private synchronized void clearIdle() { |
| if (mCount > 0) { |
| long time = SystemClock.uptimeMillis(); |
| for (int i = 0; i < IDLE_CACHE_MAX; i++) { |
| Entry entry = mEntries[i]; |
| if (entry.mHost != null && time > entry.mTimeout) { |
| entry.mHost = null; |
| entry.mConnection.closeConnection(); |
| entry.mConnection = null; |
| mCount--; |
| } |
| } |
| } |
| } |
| |
| private class IdleReaper extends Thread { |
| |
| public void run() { |
| int check = 0; |
| |
| setName("IdleReaper"); |
| android.os.Process.setThreadPriority( |
| android.os.Process.THREAD_PRIORITY_BACKGROUND); |
| synchronized (IdleCache.this) { |
| while (check < EMPTY_CHECK_MAX) { |
| try { |
| IdleCache.this.wait(CHECK_INTERVAL); |
| } catch (InterruptedException ex) { |
| } |
| if (mCount == 0) { |
| check++; |
| } else { |
| check = 0; |
| clearIdle(); |
| } |
| } |
| mThread = null; |
| } |
| if (HttpLog.LOGV) { |
| HttpLog.v("IdleCache IdleReaper shutdown: cached " + mCached + |
| " reused " + mReused); |
| mCached = 0; |
| mReused = 0; |
| } |
| } |
| } |
| } |