IdleCache.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
14b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet/* 24b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Copyright (C) 2008 The Android Open Source Project 34b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 44b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 54b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * you may not use this file except in compliance with the License. 64b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * You may obtain a copy of the License at 74b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 84b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 94b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * 104b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software 114b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 124b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 134b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * See the License for the specific language governing permissions and 144b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * limitations under the License. 154b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 164b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 174b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet/** 184b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Hangs onto idle live connections for a little while 194b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 204b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 214b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetpackage android.net.http; 224b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 234b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport org.apache.http.HttpHost; 244b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 254b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetimport android.os.SystemClock; 264b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 274b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet/** 284b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * {@hide} 294b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 304b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohetclass IdleCache { 31f354ad108c794bd4c9d1aa9a4f2a526d9c27e224Xavier Ducrohet 324b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet class Entry { 334b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet HttpHost mHost; 344b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Connection mConnection; 354b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet long mTimeout; 36f354ad108c794bd4c9d1aa9a4f2a526d9c27e224Xavier Ducrohet }; 374b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 384b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final static int IDLE_CACHE_MAX = 8; 394b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 404b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* Allow five consecutive empty queue checks before shutdown */ 414b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final static int EMPTY_CHECK_MAX = 5; 424b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 434b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* six second timeout for connections */ 444b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final static int TIMEOUT = 6 * 1000; 454b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private final static int CHECK_INTERVAL = 2 * 1000; 464b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private Entry[] mEntries = new Entry[IDLE_CACHE_MAX]; 474b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 484b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private int mCount = 0; 494b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 504b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private IdleReaper mThread = null; 514b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 524b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /* stats */ 534b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private int mCached = 0; 544b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private int mReused = 0; 554b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 564b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet IdleCache() { 574b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet for (int i = 0; i < IDLE_CACHE_MAX; i++) { 584b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mEntries[i] = new Entry(); 594b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 604b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 614b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 624b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet /** 634b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * Caches connection, if there is room. 644b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet * @return true if connection cached 654b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet */ 664b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet synchronized boolean cacheConnection( 674b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet HttpHost host, Connection connection) { 684b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 694b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet boolean ret = false; 704b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 714b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (HttpLog.LOGV) { 724b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet HttpLog.v("IdleCache size " + mCount + " host " + host); 734b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 744b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 754b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (mCount < IDLE_CACHE_MAX) { 764b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet long time = SystemClock.uptimeMillis(); 774b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet for (int i = 0; i < IDLE_CACHE_MAX; i++) { 784b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Entry entry = mEntries[i]; 794b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (entry.mHost == null) { 804b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mHost = host; 814b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mConnection = connection; 824b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mTimeout = time + TIMEOUT; 834b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mCount++; 844b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (HttpLog.LOGV) mCached++; 854b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet ret = true; 864b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (mThread == null) { 874b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mThread = new IdleReaper(); 884b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mThread.start(); 894b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 904b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet break; 914b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 924b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 934b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 944b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet return ret; 954b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 964b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 974b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet synchronized Connection getConnection(HttpHost host) { 984b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Connection ret = null; 994b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1004b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (mCount > 0) { 1014b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet for (int i = 0; i < IDLE_CACHE_MAX; i++) { 1024b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Entry entry = mEntries[i]; 1034b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet HttpHost eHost = entry.mHost; 1044b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (eHost != null && eHost.equals(host)) { 1054b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet ret = entry.mConnection; 1064b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mHost = null; 1074b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mConnection = null; 1084b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mCount--; 1094b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (HttpLog.LOGV) mReused++; 1104b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet break; 1114b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1124b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1134b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1144b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet return ret; 1154b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1164b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1174b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet synchronized void clear() { 1184b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet for (int i = 0; mCount > 0 && i < IDLE_CACHE_MAX; i++) { 1194b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Entry entry = mEntries[i]; 1204b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (entry.mHost != null) { 1214b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mHost = null; 1224b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mConnection.closeConnection(); 1234b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mConnection = null; 1244b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mCount--; 1254b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1264b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1274b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1284b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1294b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private synchronized void clearIdle() { 1304b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (mCount > 0) { 1314b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet long time = SystemClock.uptimeMillis(); 1324b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet for (int i = 0; i < IDLE_CACHE_MAX; i++) { 1334b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet Entry entry = mEntries[i]; 1344b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (entry.mHost != null && time > entry.mTimeout) { 1354b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mHost = null; 1364b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mConnection.closeConnection(); 1374b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet entry.mConnection = null; 1384b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mCount--; 1394b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1404b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1414b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1424b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1434b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1444b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet private class IdleReaper extends Thread { 1454b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1464b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet public void run() { 1474b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet int check = 0; 1484b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet 1494b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet setName("IdleReaper"); 1504b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet android.os.Process.setThreadPriority( 1514b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet android.os.Process.THREAD_PRIORITY_BACKGROUND); 1524b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet synchronized (IdleCache.this) { 1534b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet while (check < EMPTY_CHECK_MAX) { 1544b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet try { 1554b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet IdleCache.this.wait(CHECK_INTERVAL); 1564b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } catch (InterruptedException ex) { 1574b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1584b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (mCount == 0) { 1594b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet check++; 1604b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } else { 1614b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet check = 0; 1624b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet clearIdle(); 1634b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1644b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1654b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mThread = null; 1664b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1674b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet if (HttpLog.LOGV) { 1684b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet HttpLog.v("IdleCache IdleReaper shutdown: cached " + mCached + 1694b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet " reused " + mReused); 1704b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mCached = 0; 1714b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet mReused = 0; 1724b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1734b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1744b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet } 1754b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet} 1764b52ec49fee79b0488d6a9eaaa4ea5d74ce90905Xavier Ducrohet