forked from mirrors/gecko-dev
		
	 3f2298c2f6
			
		
	
	
		3f2298c2f6
		
	
	
	
	
		
			
			MozReview-Commit-ID: 666LNaHyiuQ --HG-- extra : rebase_source : f3a24e0342d8dcdf9020dd473bc6b1045cbc533b
		
			
				
	
	
		
			439 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			439 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef CacheStorageService__h__
 | |
| #define CacheStorageService__h__
 | |
| 
 | |
| #include "nsICacheStorageService.h"
 | |
| #include "nsIMemoryReporter.h"
 | |
| #include "nsINamed.h"
 | |
| #include "nsITimer.h"
 | |
| #include "nsICacheTesting.h"
 | |
| 
 | |
| #include "nsClassHashtable.h"
 | |
| #include "nsDataHashtable.h"
 | |
| #include "nsString.h"
 | |
| #include "nsThreadUtils.h"
 | |
| #include "nsProxyRelease.h"
 | |
| #include "mozilla/Monitor.h"
 | |
| #include "mozilla/Mutex.h"
 | |
| #include "mozilla/Atomics.h"
 | |
| #include "mozilla/TimeStamp.h"
 | |
| #include "nsTArray.h"
 | |
| 
 | |
| class nsIURI;
 | |
| class nsICacheEntryDoomCallback;
 | |
| class nsICacheStorageVisitor;
 | |
| class nsIRunnable;
 | |
| class nsIThread;
 | |
| class nsIEventTarget;
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace net {
 | |
| 
 | |
| class CacheStorageService;
 | |
| class CacheStorage;
 | |
| class CacheEntry;
 | |
| class CacheEntryHandle;
 | |
| 
 | |
| class CacheMemoryConsumer
 | |
| {
 | |
| private:
 | |
|   friend class CacheStorageService;
 | |
|   uint32_t mReportedMemoryConsumption : 30;
 | |
|   uint32_t mFlags : 2;
 | |
| 
 | |
| private:
 | |
|   CacheMemoryConsumer() = delete;
 | |
| 
 | |
| protected:
 | |
|   enum {
 | |
|     // No special treatment, reports always to the disk-entries pool.
 | |
|     NORMAL = 0,
 | |
|     // This consumer is belonging to a memory-only cache entry, used to decide
 | |
|     // which of the two disk and memory pools count this consumption at.
 | |
|     MEMORY_ONLY = 1 << 0,
 | |
|     // Prevent reports of this consumer at all, used for disk data chunks since
 | |
|     // we throw them away as soon as the entry is not used by any consumer and
 | |
|     // don't want to make them wipe the whole pool out during their short life.
 | |
|     DONT_REPORT = 1 << 1
 | |
|   };
 | |
| 
 | |
|   explicit CacheMemoryConsumer(uint32_t aFlags);
 | |
|   ~CacheMemoryConsumer() { DoMemoryReport(0); }
 | |
|   void DoMemoryReport(uint32_t aCurrentSize);
 | |
| };
 | |
| 
 | |
| class CacheStorageService final : public nsICacheStorageService
 | |
|                                 , public nsIMemoryReporter
 | |
|                                 , public nsITimerCallback
 | |
|                                 , public nsICacheTesting
 | |
|                                 , public nsINamed
 | |
| {
 | |
| public:
 | |
|   NS_DECL_THREADSAFE_ISUPPORTS
 | |
|   NS_DECL_NSICACHESTORAGESERVICE
 | |
|   NS_DECL_NSIMEMORYREPORTER
 | |
|   NS_DECL_NSITIMERCALLBACK
 | |
|   NS_DECL_NSICACHETESTING
 | |
|   NS_DECL_NSINAMED
 | |
| 
 | |
|   CacheStorageService();
 | |
| 
 | |
|   void Shutdown();
 | |
|   void DropPrivateBrowsingEntries();
 | |
| 
 | |
|   // Takes care of deleting any pending trashes for both cache1 and cache2
 | |
|   // as well as old cache directory.
 | |
|   static void CleaupCacheDirectories();
 | |
| 
 | |
|   static CacheStorageService* Self() { return sSelf; }
 | |
|   static nsISupports* SelfISupports() { return static_cast<nsICacheStorageService*>(Self()); }
 | |
|   nsresult Dispatch(nsIRunnable* aEvent);
 | |
|   static bool IsRunning() { return sSelf && !sSelf->mShutdown; }
 | |
|   static bool IsOnManagementThread();
 | |
|   already_AddRefed<nsIEventTarget> Thread() const;
 | |
|   mozilla::Mutex& Lock() { return mLock; }
 | |
| 
 | |
|   // Tracks entries that may be forced valid in a pruned hashtable.
 | |
|   nsDataHashtable<nsCStringHashKey, TimeStamp> mForcedValidEntries;
 | |
|   void ForcedValidEntriesPrune(TimeStamp &now);
 | |
| 
 | |
|   // Helper thread-safe interface to pass entry info, only difference from
 | |
|   // nsICacheStorageVisitor is that instead of nsIURI only the uri spec is
 | |
|   // passed.
 | |
|   class EntryInfoCallback {
 | |
|   public:
 | |
|     virtual void OnEntryInfo(const nsACString & aURISpec, const nsACString & aIdEnhance,
 | |
|                              int64_t aDataSize, int32_t aFetchCount,
 | |
|                              uint32_t aLastModifiedTime, uint32_t aExpirationTime,
 | |
|                              bool aPinned, nsILoadContextInfo* aInfo) = 0;
 | |
|   };
 | |
| 
 | |
|   // Invokes OnEntryInfo for the given aEntry, synchronously.
 | |
|   static void GetCacheEntryInfo(CacheEntry* aEntry, EntryInfoCallback *aVisitor);
 | |
| 
 | |
|   nsresult GetCacheIndexEntryAttrs(CacheStorage const* aStorage,
 | |
|                                    const nsACString &aURI,
 | |
|                                    const nsACString &aIdExtension,
 | |
|                                    bool *aHasAltData,
 | |
|                                    uint32_t *aFileSizeKb);
 | |
| 
 | |
|   static uint32_t CacheQueueSize(bool highPriority);
 | |
| 
 | |
|   // Memory reporting
 | |
|   size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 | |
|   size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 | |
|   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
 | |
| 
 | |
| private:
 | |
|   virtual ~CacheStorageService();
 | |
|   void ShutdownBackground();
 | |
| 
 | |
| private:
 | |
|   // The following methods may only be called on the management
 | |
|   // thread.
 | |
|   friend class CacheEntry;
 | |
| 
 | |
|   /**
 | |
|    * Registers the entry in management ordered arrays, a mechanism
 | |
|    * helping with weighted purge of entries.
 | |
|    * Management arrays keep hard reference to the entry.  Entry is
 | |
|    * responsible to remove it self or the service is responsible to
 | |
|    * remove the entry when it's no longer needed.
 | |
|    */
 | |
|   void RegisterEntry(CacheEntry* aEntry);
 | |
| 
 | |
|   /**
 | |
|    * Deregisters the entry from management arrays.  References are
 | |
|    * then released.
 | |
|    */
 | |
|   void UnregisterEntry(CacheEntry* aEntry);
 | |
| 
 | |
|   /**
 | |
|    * Removes the entry from the related entry hash table, if still present.
 | |
|    */
 | |
|   bool RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced = false);
 | |
| 
 | |
|   /**
 | |
|    * Tells the storage service whether this entry is only to be stored in
 | |
|    * memory.
 | |
|    */
 | |
|   void RecordMemoryOnlyEntry(CacheEntry* aEntry,
 | |
|                              bool aOnlyInMemory,
 | |
|                              bool aOverwrite);
 | |
| 
 | |
|   /**
 | |
|    * Sets a cache entry valid (overrides the default loading behavior by loading
 | |
|    * directly from cache) for the given number of seconds
 | |
|    * See nsICacheEntry.idl for more details
 | |
|    */
 | |
|   void ForceEntryValidFor(nsACString const &aContextKey,
 | |
|                           nsACString const &aEntryKey,
 | |
|                           uint32_t aSecondsToTheFuture);
 | |
| 
 | |
|   /**
 | |
|    * Remove the validity info
 | |
|    */
 | |
|   void RemoveEntryForceValid(nsACString const &aContextKey,
 | |
|                              nsACString const &aEntryKey);
 | |
| 
 | |
|   /**
 | |
|    * Retrieves the status of the cache entry to see if it has been forced valid
 | |
|    * (so it will loaded directly from cache without further validation)
 | |
|    */
 | |
|   bool IsForcedValidEntry(nsACString const &aContextKey,
 | |
|                           nsACString const &aEntryKey);
 | |
| 
 | |
| private:
 | |
|   friend class CacheIndex;
 | |
| 
 | |
|   /**
 | |
|    * CacheIndex uses this to prevent a cache entry from being prememptively
 | |
|    * thrown away when forced valid
 | |
|    * See nsICacheEntry.idl for more details
 | |
|    */
 | |
|   bool IsForcedValidEntry(nsACString const &aEntryKeyWithContext);
 | |
| 
 | |
| private:
 | |
|   // These are helpers for telemetry monitoring of the memory pools.
 | |
|   void TelemetryPrune(TimeStamp &now);
 | |
|   void TelemetryRecordEntryCreation(CacheEntry const* entry);
 | |
|   void TelemetryRecordEntryRemoval(CacheEntry const* entry);
 | |
| 
 | |
| private:
 | |
|   // Following methods are thread safe to call.
 | |
|   friend class CacheStorage;
 | |
| 
 | |
|   /**
 | |
|    * Get, or create when not existing and demanded, an entry for the storage
 | |
|    * and uri+id extension.
 | |
|    */
 | |
|   nsresult AddStorageEntry(CacheStorage const* aStorage,
 | |
|                            const nsACString & aURI,
 | |
|                            const nsACString & aIdExtension,
 | |
|                            bool aReplace,
 | |
|                            CacheEntryHandle** aResult);
 | |
| 
 | |
|   /**
 | |
|    * Check existance of an entry.  This may throw NS_ERROR_NOT_AVAILABLE
 | |
|    * when the information cannot be obtained synchronously w/o blocking.
 | |
|    */
 | |
|   nsresult CheckStorageEntry(CacheStorage const* aStorage,
 | |
|                              const nsACString & aURI,
 | |
|                              const nsACString & aIdExtension,
 | |
|                              bool* aResult);
 | |
| 
 | |
|   /**
 | |
|    * Removes the entry from the related entry hash table, if still present
 | |
|    * and returns it.
 | |
|    */
 | |
|   nsresult DoomStorageEntry(CacheStorage const* aStorage,
 | |
|                             const nsACString & aURI,
 | |
|                             const nsACString & aIdExtension,
 | |
|                             nsICacheEntryDoomCallback* aCallback);
 | |
| 
 | |
|   /**
 | |
|    * Removes and returns entry table for the storage.
 | |
|    */
 | |
|   nsresult DoomStorageEntries(CacheStorage const* aStorage,
 | |
|                               nsICacheEntryDoomCallback* aCallback);
 | |
| 
 | |
|   /**
 | |
|    * Walk all entiries beloging to the storage.
 | |
|    */
 | |
|   nsresult WalkStorageEntries(CacheStorage const* aStorage,
 | |
|                               bool aVisitEntries,
 | |
|                               nsICacheStorageVisitor* aVisitor);
 | |
| 
 | |
| private:
 | |
|   friend class CacheFileIOManager;
 | |
| 
 | |
|   /**
 | |
|    * CacheFileIOManager uses this method to notify CacheStorageService that
 | |
|    * an active entry was removed. This method is called even if the entry
 | |
|    * removal was originated by CacheStorageService.
 | |
|    */
 | |
|   void CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
 | |
|                        const nsACString & aIdExtension,
 | |
|                        const nsACString & aURISpec);
 | |
| 
 | |
|   /**
 | |
|    * Tries to find an existing entry in the hashtables and synchronously call
 | |
|    * OnCacheEntryInfo of the aVisitor callback when found.
 | |
|    * @retuns
 | |
|    *   true, when the entry has been found that also implies the callbacks has
 | |
|    *        beem invoked
 | |
|    *   false, when an entry has not been found
 | |
|    */
 | |
|   bool GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo,
 | |
|                          const nsACString & aIdExtension,
 | |
|                          const nsACString & aURISpec,
 | |
|                          EntryInfoCallback *aCallback);
 | |
| 
 | |
| private:
 | |
|   friend class CacheMemoryConsumer;
 | |
| 
 | |
|   /**
 | |
|    * When memory consumption of this entry radically changes, this method
 | |
|    * is called to reflect the size of allocated memory.  This call may purge
 | |
|    * unspecified number of entries from memory (but not from disk).
 | |
|    */
 | |
|   void OnMemoryConsumptionChange(CacheMemoryConsumer* aConsumer,
 | |
|                                  uint32_t aCurrentMemoryConsumption);
 | |
| 
 | |
|   /**
 | |
|    * If not already pending, it schedules mPurgeTimer that fires after 1 second
 | |
|    * and dispatches PurgeOverMemoryLimit().
 | |
|    */
 | |
|   void SchedulePurgeOverMemoryLimit();
 | |
| 
 | |
|   /**
 | |
|    * Called on the management thread, removes all expired and then least used
 | |
|    * entries from the memory, first from the disk pool and then from the memory
 | |
|    * pool.
 | |
|    */
 | |
|   void PurgeOverMemoryLimit();
 | |
| 
 | |
| private:
 | |
|   nsresult DoomStorageEntries(const nsACString& aContextKey,
 | |
|                               nsILoadContextInfo* aContext,
 | |
|                               bool aDiskStorage,
 | |
|                               bool aPin,
 | |
|                               nsICacheEntryDoomCallback* aCallback);
 | |
|   nsresult AddStorageEntry(const nsACString& aContextKey,
 | |
|                            const nsACString & aURI,
 | |
|                            const nsACString & aIdExtension,
 | |
|                            bool aWriteToDisk,
 | |
|                            bool aSkipSizeCheck,
 | |
|                            bool aPin,
 | |
|                            bool aReplace,
 | |
|                            CacheEntryHandle** aResult);
 | |
| 
 | |
|   static CacheStorageService* sSelf;
 | |
| 
 | |
|   mozilla::Mutex mLock;
 | |
|   mozilla::Mutex mForcedValidEntriesLock;
 | |
| 
 | |
|   bool mShutdown;
 | |
| 
 | |
|   // Accessible only on the service thread
 | |
|   class MemoryPool
 | |
|   {
 | |
|   public:
 | |
|     enum EType
 | |
|     {
 | |
|       DISK,
 | |
|       MEMORY,
 | |
|     } mType;
 | |
| 
 | |
|     explicit MemoryPool(EType aType);
 | |
|     ~MemoryPool();
 | |
| 
 | |
|     nsTArray<RefPtr<CacheEntry> > mFrecencyArray;
 | |
|     nsTArray<RefPtr<CacheEntry> > mExpirationArray;
 | |
|     Atomic<uint32_t, Relaxed> mMemorySize;
 | |
| 
 | |
|     bool OnMemoryConsumptionChange(uint32_t aSavedMemorySize,
 | |
|                                    uint32_t aCurrentMemoryConsumption);
 | |
|     /**
 | |
|      * Purges entries from memory based on the frecency ordered array.
 | |
|      */
 | |
|     void PurgeOverMemoryLimit();
 | |
|     void PurgeExpired();
 | |
|     void PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat);
 | |
|     void PurgeAll(uint32_t aWhat);
 | |
| 
 | |
|   private:
 | |
|     uint32_t Limit() const;
 | |
|     MemoryPool() = delete;
 | |
|   };
 | |
| 
 | |
|   MemoryPool mDiskPool;
 | |
|   MemoryPool mMemoryPool;
 | |
|   TimeStamp mLastPurgeTime;
 | |
|   MemoryPool& Pool(bool aUsingDisk)
 | |
|   {
 | |
|     return aUsingDisk ? mDiskPool : mMemoryPool;
 | |
|   }
 | |
|   MemoryPool const& Pool(bool aUsingDisk) const
 | |
|   {
 | |
|     return aUsingDisk ? mDiskPool : mMemoryPool;
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsITimer> mPurgeTimer;
 | |
| 
 | |
|   class PurgeFromMemoryRunnable : public Runnable
 | |
|   {
 | |
|   public:
 | |
|     PurgeFromMemoryRunnable(CacheStorageService* aService, uint32_t aWhat)
 | |
|       : Runnable("net::CacheStorageService::PurgeFromMemoryRunnable")
 | |
|       , mService(aService)
 | |
|       , mWhat(aWhat)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|   private:
 | |
|     virtual ~PurgeFromMemoryRunnable() = default;
 | |
| 
 | |
|     NS_IMETHOD Run() override;
 | |
| 
 | |
|     RefPtr<CacheStorageService> mService;
 | |
|     uint32_t mWhat;
 | |
|   };
 | |
| 
 | |
|   // Used just for telemetry purposes, accessed only on the management thread.
 | |
|   // Note: not included in the memory reporter, this is not expected to be huge
 | |
|   // and also would be complicated to report since reporting happens on the main
 | |
|   // thread but this table is manipulated on the management thread.
 | |
|   nsDataHashtable<nsCStringHashKey, mozilla::TimeStamp> mPurgeTimeStamps;
 | |
| 
 | |
|   // nsICacheTesting
 | |
|   class IOThreadSuspender : public Runnable
 | |
|   {
 | |
|   public:
 | |
|     IOThreadSuspender()
 | |
|       : Runnable("net::CacheStorageService::IOThreadSuspender")
 | |
|       , mMon("IOThreadSuspender")
 | |
|       , mSignaled(false)
 | |
|     {
 | |
|     }
 | |
|     void Notify();
 | |
|   private:
 | |
|     virtual ~IOThreadSuspender() = default;
 | |
|     NS_IMETHOD Run() override;
 | |
| 
 | |
|     Monitor mMon;
 | |
|     bool mSignaled;
 | |
|   };
 | |
| 
 | |
|   RefPtr<IOThreadSuspender> mActiveIOSuspender;
 | |
| };
 | |
| 
 | |
| template<class T>
 | |
| void ProxyRelease(const char* aName, nsCOMPtr<T> &object, nsIEventTarget* target)
 | |
| {
 | |
|   NS_ProxyRelease(aName, target, object.forget());
 | |
| }
 | |
| 
 | |
| template<class T>
 | |
| void ProxyReleaseMainThread(const char* aName, nsCOMPtr<T> &object)
 | |
| {
 | |
|   ProxyRelease(aName, object, GetMainThreadEventTarget());
 | |
| }
 | |
| 
 | |
| } // namespace net
 | |
| } // namespace mozilla
 | |
| 
 | |
| #define NS_CACHE_STORAGE_SERVICE_CID \
 | |
|   { 0xea70b098, 0x5014, 0x4e21, \
 | |
|   { 0xae, 0xe1, 0x75, 0xe6, 0xb2, 0xc4, 0xb8, 0xe0 } } \
 | |
| 
 | |
| #define NS_CACHE_STORAGE_SERVICE_CONTRACTID \
 | |
|   "@mozilla.org/netwerk/cache-storage-service;1"
 | |
| 
 | |
| #define NS_CACHE_STORAGE_SERVICE_CONTRACTID2 \
 | |
|   "@mozilla.org/network/cache-storage-service;1"
 | |
| 
 | |
| #endif
 |