Home | History | Annotate | Download | only in loader
      1 /*
      2     Copyright (C) 1998 Lars Knoll (knoll (at) mpi-hd.mpg.de)
      3     Copyright (C) 2001 Dirk Mueller <mueller (at) kde.org>
      4     Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
      5 
      6     This library is free software; you can redistribute it and/or
      7     modify it under the terms of the GNU Library General Public
      8     License as published by the Free Software Foundation; either
      9     version 2 of the License, or (at your option) any later version.
     10 
     11     This library is distributed in the hope that it will be useful,
     12     but WITHOUT ANY WARRANTY; without even the implied warranty of
     13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14     Library General Public License for more details.
     15 
     16     You should have received a copy of the GNU Library General Public License
     17     along with this library; see the file COPYING.LIB.  If not, write to
     18     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     19     Boston, MA 02110-1301, USA.
     20 
     21     This class provides all functionality needed for loading images, style sheets and html
     22     pages from the web. It has a memory cache for these objects.
     23 */
     24 
     25 #ifndef Cache_h
     26 #define Cache_h
     27 
     28 #include "CachePolicy.h"
     29 #include "CachedResource.h"
     30 #include "PlatformString.h"
     31 #include "StringHash.h"
     32 #include "loader.h"
     33 #include <wtf/HashMap.h>
     34 #include <wtf/HashSet.h>
     35 #include <wtf/Noncopyable.h>
     36 #include <wtf/Vector.h>
     37 
     38 namespace WebCore  {
     39 
     40 class CachedCSSStyleSheet;
     41 class CachedResource;
     42 class DocLoader;
     43 class KURL;
     44 
     45 // This cache holds subresources used by Web pages: images, scripts, stylesheets, etc.
     46 
     47 // The cache keeps a flexible but bounded window of dead resources that grows/shrinks
     48 // depending on the live resource load. Here's an example of cache growth over time,
     49 // with a min dead resource capacity of 25% and a max dead resource capacity of 50%:
     50 
     51 //        |-----|                              Dead: -
     52 //        |----------|                         Live: +
     53 //      --|----------|                         Cache boundary: | (objects outside this mark have been evicted)
     54 //      --|----------++++++++++|
     55 // -------|-----+++++++++++++++|
     56 // -------|-----+++++++++++++++|+++++
     57 
     58 class Cache : public Noncopyable {
     59 public:
     60     friend Cache* cache();
     61 
     62     typedef HashMap<String, CachedResource*> CachedResourceMap;
     63 
     64     struct LRUList {
     65         CachedResource* m_head;
     66         CachedResource* m_tail;
     67         LRUList() : m_head(0), m_tail(0) { }
     68     };
     69 
     70     struct TypeStatistic {
     71         int count;
     72         int size;
     73         int liveSize;
     74         int decodedSize;
     75         int purgeableSize;
     76         int purgedSize;
     77         TypeStatistic() : count(0), size(0), liveSize(0), decodedSize(0), purgeableSize(0), purgedSize(0) { }
     78         void addResource(CachedResource*);
     79     };
     80 
     81     struct Statistics {
     82         TypeStatistic images;
     83         TypeStatistic cssStyleSheets;
     84         TypeStatistic scripts;
     85 #if ENABLE(XSLT)
     86         TypeStatistic xslStyleSheets;
     87 #endif
     88 #if ENABLE(XBL)
     89         TypeStatistic xblDocs;
     90 #endif
     91         TypeStatistic fonts;
     92     };
     93 
     94     // The loader that fetches resources.
     95     Loader* loader() { return &m_loader; }
     96 
     97     // Request resources from the cache.  A load will be initiated and a cache object created if the object is not
     98     // found in the cache.
     99     CachedResource* requestResource(DocLoader*, CachedResource::Type, const KURL& url, const String& charset, bool isPreload = false);
    100 
    101     CachedCSSStyleSheet* requestUserCSSStyleSheet(DocLoader*, const String& url, const String& charset);
    102 
    103     void revalidateResource(CachedResource*, DocLoader*);
    104     void revalidationSucceeded(CachedResource* revalidatingResource, const ResourceResponse&);
    105     void revalidationFailed(CachedResource* revalidatingResource);
    106 
    107     // Sets the cache's memory capacities, in bytes. These will hold only approximately,
    108     // since the decoded cost of resources like scripts and stylesheets is not known.
    109     //  - minDeadBytes: The maximum number of bytes that dead resources should consume when the cache is under pressure.
    110     //  - maxDeadBytes: The maximum number of bytes that dead resources should consume when the cache is not under pressure.
    111     //  - totalBytes: The maximum number of bytes that the cache should consume overall.
    112     void setCapacities(unsigned minDeadBytes, unsigned maxDeadBytes, unsigned totalBytes);
    113 
    114     // Turn the cache on and off.  Disabling the cache will remove all resources from the cache.  They may
    115     // still live on if they are referenced by some Web page though.
    116     void setDisabled(bool);
    117     bool disabled() const { return m_disabled; }
    118 
    119     void setPruneEnabled(bool enabled) { m_pruneEnabled = enabled; }
    120     void prune()
    121     {
    122         if (m_liveSize + m_deadSize <= m_capacity && m_maxDeadCapacity && m_deadSize <= m_maxDeadCapacity) // Fast path.
    123             return;
    124 
    125         pruneDeadResources(); // Prune dead first, in case it was "borrowing" capacity from live.
    126         pruneLiveResources();
    127     }
    128 
    129     void setDeadDecodedDataDeletionInterval(double interval) { m_deadDecodedDataDeletionInterval = interval; }
    130     double deadDecodedDataDeletionInterval() const { return m_deadDecodedDataDeletionInterval; }
    131 
    132     // Remove an existing cache entry from both the resource map and from the LRU list.
    133     void remove(CachedResource* resource) { evict(resource); }
    134 
    135     void addDocLoader(DocLoader*);
    136     void removeDocLoader(DocLoader*);
    137 
    138     CachedResource* resourceForURL(const String&);
    139 
    140     // Calls to put the cached resource into and out of LRU lists.
    141     void insertInLRUList(CachedResource*);
    142     void removeFromLRUList(CachedResource*);
    143 
    144     // Called to adjust the cache totals when a resource changes size.
    145     void adjustSize(bool live, int delta);
    146 
    147     // Track decoded resources that are in the cache and referenced by a Web page.
    148     void insertInLiveDecodedResourcesList(CachedResource*);
    149     void removeFromLiveDecodedResourcesList(CachedResource*);
    150 
    151     void addToLiveResourcesSize(CachedResource*);
    152     void removeFromLiveResourcesSize(CachedResource*);
    153 
    154     // Function to collect cache statistics for the caches window in the Safari Debug menu.
    155     Statistics getStatistics();
    156 
    157 #ifdef ANDROID_INSTRUMENT
    158     unsigned getLiveSize() { return m_liveSize; }
    159     unsigned getDeadSize() { return m_deadSize; }
    160 #endif
    161 
    162 private:
    163     Cache();
    164     ~Cache(); // Not implemented to make sure nobody accidentally calls delete -- WebCore does not delete singletons.
    165 
    166     LRUList* lruListFor(CachedResource*);
    167     void resourceAccessed(CachedResource*);
    168 #ifndef NDEBUG
    169     void dumpStats();
    170     void dumpLRULists(bool includeLive) const;
    171 #endif
    172 
    173     unsigned liveCapacity() const;
    174     unsigned deadCapacity() const;
    175 
    176     void pruneDeadResources(); // Flush decoded and encoded data from resources not referenced by Web pages.
    177     void pruneLiveResources(); // Flush decoded data from resources still referenced by Web pages.
    178 
    179     void evict(CachedResource*);
    180 
    181     // Member variables.
    182     HashSet<DocLoader*> m_docLoaders;
    183     Loader m_loader;
    184 
    185     bool m_disabled;  // Whether or not the cache is enabled.
    186     bool m_pruneEnabled;
    187     bool m_inPruneDeadResources;
    188 
    189     unsigned m_capacity;
    190     unsigned m_minDeadCapacity;
    191     unsigned m_maxDeadCapacity;
    192     double m_deadDecodedDataDeletionInterval;
    193 
    194     unsigned m_liveSize; // The number of bytes currently consumed by "live" resources in the cache.
    195     unsigned m_deadSize; // The number of bytes currently consumed by "dead" resources in the cache.
    196 
    197     // Size-adjusted and popularity-aware LRU list collection for cache objects.  This collection can hold
    198     // more resources than the cached resource map, since it can also hold "stale" multiple versions of objects that are
    199     // waiting to die when the clients referencing them go away.
    200     Vector<LRUList, 32> m_allResources;
    201 
    202     // List just for live resources with decoded data.  Access to this list is based off of painting the resource.
    203     LRUList m_liveDecodedResources;
    204 
    205     // A URL-based map of all resources that are in the cache (including the freshest version of objects that are currently being
    206     // referenced by a Web page).
    207     HashMap<String, CachedResource*> m_resources;
    208 };
    209 
    210 // Function to obtain the global cache.
    211 Cache* cache();
    212 
    213 }
    214 
    215 #endif
    216