netwerk/cache2/CacheEntry.h

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #ifndef CacheEntry__h__
     6 #define CacheEntry__h__
     8 #include "nsICacheEntry.h"
     9 #include "CacheFile.h"
    11 #include "nsIRunnable.h"
    12 #include "nsIOutputStream.h"
    13 #include "nsICacheEntryOpenCallback.h"
    14 #include "nsICacheEntryDoomCallback.h"
    16 #include "nsCOMPtr.h"
    17 #include "nsRefPtrHashtable.h"
    18 #include "nsDataHashtable.h"
    19 #include "nsHashKeys.h"
    20 #include "nsString.h"
    21 #include "nsCOMArray.h"
    22 #include "nsThreadUtils.h"
    23 #include "mozilla/Mutex.h"
    24 #include "mozilla/TimeStamp.h"
    26 static inline uint32_t
    27 PRTimeToSeconds(PRTime t_usec)
    28 {
    29   PRTime usec_per_sec = PR_USEC_PER_SEC;
    30   return uint32_t(t_usec /= usec_per_sec);
    31 }
    33 #define NowInSeconds() PRTimeToSeconds(PR_Now())
    35 class nsIStorageStream;
    36 class nsIOutputStream;
    37 class nsIURI;
    38 class nsIThread;
    40 namespace mozilla {
    41 namespace net {
    43 class CacheStorageService;
    44 class CacheStorage;
    45 class CacheFileOutputStream;
    46 class CacheOutputCloseListener;
    47 class CacheEntryHandle;
    49 class CacheEntry : public nsICacheEntry
    50                  , public nsIRunnable
    51                  , public CacheFileListener
    52 {
    53 public:
    54   NS_DECL_THREADSAFE_ISUPPORTS
    55   NS_DECL_NSICACHEENTRY
    56   NS_DECL_NSIRUNNABLE
    58   CacheEntry(const nsACString& aStorageID, nsIURI* aURI, const nsACString& aEnhanceID,
    59              bool aUseDisk);
    61   void AsyncOpen(nsICacheEntryOpenCallback* aCallback, uint32_t aFlags);
    63   CacheEntryHandle* NewHandle();
    65 public:
    66   uint32_t GetMetadataMemoryConsumption();
    67   nsCString const &GetStorageID() const { return mStorageID; }
    68   nsCString const &GetEnhanceID() const { return mEnhanceID; }
    69   nsIURI* GetURI() const { return mURI; }
    70   // Accessible only under the CacheStorageService lock (asserts it)
    71   bool IsUsingDiskLocked() const;
    72   // Accessible at any time
    73   bool IsUsingDisk() const { return mUseDisk; }
    74   bool SetUsingDisk(bool aUsingDisk);
    75   bool IsReferenced() const;
    76   bool IsFileDoomed();
    78   // Methods for entry management (eviction from memory),
    79   // called only on the management thread.
    81   // TODO make these inline
    82   double GetFrecency() const;
    83   uint32_t GetExpirationTime() const;
    85   bool IsRegistered() const;
    86   bool CanRegister() const;
    87   void SetRegistered(bool aRegistered);
    89   enum EPurge {
    90     PURGE_DATA_ONLY_DISK_BACKED,
    91     PURGE_WHOLE_ONLY_DISK_BACKED,
    92     PURGE_WHOLE,
    93   };
    95   bool Purge(uint32_t aWhat);
    96   void PurgeAndDoom();
    97   void DoomAlreadyRemoved();
    99   nsresult HashingKeyWithStorage(nsACString &aResult);
   100   nsresult HashingKey(nsACString &aResult);
   102   static nsresult HashingKey(nsCSubstring const& aStorageID,
   103                              nsCSubstring const& aEnhanceID,
   104                              nsIURI* aURI,
   105                              nsACString &aResult);
   107   static nsresult HashingKey(nsCSubstring const& aStorageID,
   108                              nsCSubstring const& aEnhanceID,
   109                              nsCSubstring const& aURISpec,
   110                              nsACString &aResult);
   112   // Accessed only on the service management thread
   113   double mFrecency;
   114   uint32_t mSortingExpirationTime;
   116   // Memory reporting
   117   size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
   118   size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
   120 private:
   121   virtual ~CacheEntry();
   123   // CacheFileListener
   124   NS_IMETHOD OnFileReady(nsresult aResult, bool aIsNew);
   125   NS_IMETHOD OnFileDoomed(nsresult aResult);
   127   // Keep the service alive during life-time of an entry
   128   nsRefPtr<CacheStorageService> mService;
   130   // We must monitor when a cache entry whose consumer is responsible
   131   // for writing it the first time gets released.  We must then invoke
   132   // waiting callbacks to not break the chain.
   133   class Callback
   134   {
   135   public:
   136     Callback(CacheEntry* aEntry,
   137              nsICacheEntryOpenCallback *aCallback,
   138              bool aReadOnly, bool aCheckOnAnyThread);
   139     Callback(Callback const &aThat);
   140     ~Callback();
   142     // Called when this callback record changes it's owning entry,
   143     // mainly during recreation.
   144     void ExchangeEntry(CacheEntry* aEntry);
   146     // We are raising reference count here to take into account the pending
   147     // callback (that virtually holds a ref to this entry before it gets
   148     // it's pointer).
   149     nsRefPtr<CacheEntry> mEntry;
   150     nsCOMPtr<nsICacheEntryOpenCallback> mCallback;
   151     nsCOMPtr<nsIThread> mTargetThread;
   152     bool mReadOnly : 1;
   153     bool mCheckOnAnyThread : 1;
   154     bool mRecheckAfterWrite : 1;
   155     bool mNotWanted : 1;
   157     nsresult OnCheckThread(bool *aOnCheckThread) const;
   158     nsresult OnAvailThread(bool *aOnAvailThread) const;
   159   };
   161   // Since OnCacheEntryAvailable must be invoked on the main thread
   162   // we need a runnable for it...
   163   class AvailableCallbackRunnable : public nsRunnable
   164   {
   165   public:
   166     AvailableCallbackRunnable(CacheEntry* aEntry,
   167                               Callback const &aCallback)
   168       : mEntry(aEntry)
   169       , mCallback(aCallback)
   170     {}
   172   private:
   173     NS_IMETHOD Run()
   174     {
   175       mEntry->InvokeAvailableCallback(mCallback);
   176       return NS_OK;
   177     }
   179     nsRefPtr<CacheEntry> mEntry;
   180     Callback mCallback;
   181   };
   183   // Since OnCacheEntryDoomed must be invoked on the main thread
   184   // we need a runnable for it...
   185   class DoomCallbackRunnable : public nsRunnable
   186   {
   187   public:
   188     DoomCallbackRunnable(CacheEntry* aEntry, nsresult aRv)
   189       : mEntry(aEntry), mRv(aRv) {}
   191   private:
   192     NS_IMETHOD Run()
   193     {
   194       nsCOMPtr<nsICacheEntryDoomCallback> callback;
   195       {
   196         mozilla::MutexAutoLock lock(mEntry->mLock);
   197         mEntry->mDoomCallback.swap(callback);
   198       }
   200       if (callback)
   201         callback->OnCacheEntryDoomed(mRv);
   202       return NS_OK;
   203     }
   205     nsRefPtr<CacheEntry> mEntry;
   206     nsresult mRv;
   207   };
   209   // Loads from disk asynchronously
   210   bool Load(bool aTruncate, bool aPriority);
   211   void OnLoaded();
   213   void RememberCallback(Callback const & aCallback);
   214   void InvokeCallbacksLock();
   215   void InvokeCallbacks();
   216   bool InvokeCallbacks(bool aReadOnly);
   217   bool InvokeCallback(Callback & aCallback);
   218   void InvokeAvailableCallback(Callback const & aCallback);
   220   nsresult OpenOutputStreamInternal(int64_t offset, nsIOutputStream * *_retval);
   222   // When this entry is new and recreated w/o a callback, we need to wrap it
   223   // with a handle to detect writing consumer is gone.
   224   CacheEntryHandle* NewWriteHandle();
   225   void OnHandleClosed(CacheEntryHandle const* aHandle);
   227 private:
   228   friend class CacheEntryHandle;
   229   // Increment/decrements the number of handles keeping this entry.
   230   void AddHandleRef() { ++mHandlesCount; }
   231   void ReleaseHandleRef() { --mHandlesCount; }
   232   // Current number of handles keeping this entry.
   233   uint32_t HandlesCount() const { return mHandlesCount; }
   235 private:
   236   friend class CacheOutputCloseListener;
   237   void OnOutputClosed();
   239 private:
   240   // Schedules a background operation on the management thread.
   241   // When executed on the management thread directly, the operation(s)
   242   // is (are) executed immediately.
   243   void BackgroundOp(uint32_t aOperation, bool aForceAsync = false);
   244   void StoreFrecency();
   246   // Called only from DoomAlreadyRemoved()
   247   void DoomFile();
   249   already_AddRefed<CacheEntryHandle> ReopenTruncated(bool aMemoryOnly,
   250                                                      nsICacheEntryOpenCallback* aCallback);
   251   void TransferCallbacks(CacheEntry & aFromEntry);
   253   mozilla::Mutex mLock;
   255   // Reflects the number of existing handles for this entry
   256   ::mozilla::ThreadSafeAutoRefCnt mHandlesCount;
   258   nsTArray<Callback> mCallbacks;
   259   nsCOMPtr<nsICacheEntryDoomCallback> mDoomCallback;
   261   nsRefPtr<CacheFile> mFile;
   262   nsresult mFileStatus;
   263   nsCOMPtr<nsIURI> mURI;
   264   nsCString mEnhanceID;
   265   nsCString mStorageID;
   267   // Whether it's allowed to persist the data to disk
   268   // Synchronized by the service management lock.
   269   // Hence, leave it as a standalone boolean.
   270   bool mUseDisk;
   272   // Set when entry is doomed with AsyncDoom() or DoomAlreadyRemoved().
   273   // Left as a standalone flag to not bother with locking (there is no need).
   274   bool mIsDoomed;
   276   // Following flags are all synchronized with the cache entry lock.
   278   // Whether security info has already been looked up in metadata.
   279   bool mSecurityInfoLoaded : 1;
   280   // Prevents any callback invocation
   281   bool mPreventCallbacks : 1;
   282   // true: after load and an existing file, or after output stream has been opened.
   283   //       note - when opening an input stream, and this flag is false, output stream
   284   //       is open along ; this makes input streams on new entries behave correctly
   285   //       when EOF is reached (WOULD_BLOCK is returned).
   286   // false: after load and a new file, or dropped to back to false when a writer
   287   //        fails to open an output stream.
   288   bool mHasData : 1;
   290 #ifdef PR_LOG
   291   static char const * StateString(uint32_t aState);
   292 #endif
   294   enum EState {      // transiting to:
   295     NOTLOADED = 0,   // -> LOADING | EMPTY
   296     LOADING = 1,     // -> EMPTY | READY
   297     EMPTY = 2,       // -> WRITING
   298     WRITING = 3,     // -> EMPTY | READY
   299     READY = 4,       // -> REVALIDATING
   300     REVALIDATING = 5 // -> READY
   301   };
   303   // State of this entry.
   304   EState mState;
   306   enum ERegistration {
   307     NEVERREGISTERED = 0, // The entry has never been registered
   308     REGISTERED = 1,      // The entry is stored in the memory pool index
   309     DEREGISTERED = 2     // The entry has been removed from the pool
   310   };
   312   // Accessed only on the management thread.  Records the state of registration
   313   // this entry in the memory pool intermediate cache.
   314   ERegistration mRegistration;
   316   // If a new (empty) entry is requested to open an input stream before
   317   // output stream has been opened, we must open output stream internally
   318   // on CacheFile and hold until writer releases the entry or opens the output
   319   // stream for read (then we trade him mOutputStream).
   320   nsCOMPtr<nsIOutputStream> mOutputStream;
   322   // Weak reference to the current writter.  There can be more then one
   323   // writer at a time and OnHandleClosed() must be processed only for the
   324   // current one.
   325   CacheEntryHandle* mWriter;
   327   // Background thread scheduled operation.  Set (under the lock) one
   328   // of this flags to tell the background thread what to do.
   329   class Ops {
   330   public:
   331     static uint32_t const REGISTER =          1 << 0;
   332     static uint32_t const FRECENCYUPDATE =    1 << 1;
   333     static uint32_t const CALLBACKS =         1 << 2;
   334     static uint32_t const UNREGISTER =        1 << 3;
   336     Ops() : mFlags(0) { }
   337     uint32_t Grab() { uint32_t flags = mFlags; mFlags = 0; return flags; }
   338     bool Set(uint32_t aFlags) { if (mFlags & aFlags) return false; mFlags |= aFlags; return true; }
   339   private:
   340     uint32_t mFlags;
   341   } mBackgroundOperations;
   343   nsCOMPtr<nsISupports> mSecurityInfo;
   344   int64_t mPredictedDataSize;
   345   mozilla::TimeStamp mLoadStart;
   346   nsCOMPtr<nsIThread> mReleaseThread;
   347 };
   350 class CacheEntryHandle : public nsICacheEntry
   351 {
   352 public:
   353   CacheEntryHandle(CacheEntry* aEntry);
   354   virtual ~CacheEntryHandle();
   355   CacheEntry* Entry() const { return mEntry; }
   357   NS_DECL_THREADSAFE_ISUPPORTS
   358   NS_FORWARD_NSICACHEENTRY(mEntry->)
   359 private:
   360   nsRefPtr<CacheEntry> mEntry;
   361 };
   364 class CacheOutputCloseListener : public nsRunnable
   365 {
   366 public:
   367   void OnOutputClosed();
   368   virtual ~CacheOutputCloseListener();
   370 private:
   371   friend class CacheEntry;
   373   NS_DECL_NSIRUNNABLE
   374   CacheOutputCloseListener(CacheEntry* aEntry);
   376 private:
   377   nsRefPtr<CacheEntry> mEntry;
   378 };
   380 } // net
   381 } // mozilla
   383 #endif

mercurial