DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (27a812186ff4)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
/* 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 "nsClassHashtable.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "mozilla/Mutex.h"
#include "mozilla/Atomics.h"
#include "nsTArray.h"

class nsIURI;
class nsICacheEntryOpenCallback;
class nsICacheEntryDoomCallback;
class nsICacheStorageVisitor;
class nsIRunnable;
class nsIThread;
class nsIEventTarget;

namespace mozilla {
namespace net {

class CacheStorageService;
class CacheStorage;
class CacheEntry;
class CacheEntryHandle;
class CacheEntryTable;

class CacheMemoryConsumer
{
private:
  friend class CacheStorageService;
  uint32_t mReportedMemoryConsumption;
protected:
  CacheMemoryConsumer();
  void DoMemoryReport(uint32_t aCurrentSize);
};

class CacheStorageService : public nsICacheStorageService
                          , public nsIMemoryReporter
{
public:
  NS_DECL_THREADSAFE_ISUPPORTS
  NS_DECL_NSICACHESTORAGESERVICE
  NS_DECL_NSIMEMORYREPORTER

  CacheStorageService();

  void Shutdown();
  void DropPrivateBrowsingEntries();

  // Wipes out the new or the old cache directory completely.
  static void WipeCacheDirectory(uint32_t aVersion);

  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; }

  // 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);

private:
  // Following methods are thread safe to call.
  friend class CacheStorage;
  friend class CacheFileIOManager;

  /**
   * Get, or create when not existing and demanded, an entry for the storage
   * and uri+id extension.
   */
  nsresult AddStorageEntry(CacheStorage const* aStorage,
                           nsIURI* aURI,
                           const nsACString & aIdExtension,
                           bool aCreateIfNotExist,
                           bool aReplace,
                           CacheEntryHandle** aResult);

  /**
   * Removes the entry from the related entry hash table, if still present
   * and returns it.
   */
  nsresult DoomStorageEntry(CacheStorage const* aStorage,
                            nsIURI* 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);

  /**
   * 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.
   */
  nsresult CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
                           const nsACString & aURL);

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);
  void PurgeOverMemoryLimit();

private:
  class PurgeFromMemoryRunnable : public nsRunnable
  {
  public:
    PurgeFromMemoryRunnable(CacheStorageService* aService, uint32_t aWhat)
      : mService(aService), mWhat(aWhat) { }

  private:
    virtual ~PurgeFromMemoryRunnable() { }

    NS_IMETHOD Run() {
      mService->PurgeAll(mWhat);
      return NS_OK;
    }

    nsRefPtr<CacheStorageService> mService;
    uint32_t mWhat;
  };

  /**
   * Purges entries from memory based on the frecency ordered array.
   */
  void PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat);
  void PurgeExpired();
  void PurgeAll(uint32_t aWhat);

  nsresult DoomStorageEntries(nsCSubstring const& aContextKey,
                              bool aDiskStorage,
                              nsICacheEntryDoomCallback* aCallback);
  nsresult AddStorageEntry(nsCSubstring const& aContextKey,
                           nsIURI* aURI,
                           const nsACString & aIdExtension,
                           bool aWriteToDisk,
                           bool aCreateIfNotExist,
                           bool aReplace,
                           CacheEntryHandle** aResult);

  static CacheStorageService* sSelf;

  mozilla::Mutex mLock;

  bool mShutdown;

  // Accessible only on the service thread
  nsTArray<nsRefPtr<CacheEntry> > mFrecencyArray;
  nsTArray<nsRefPtr<CacheEntry> > mExpirationArray;
  mozilla::Atomic<uint32_t> mMemorySize;
  bool mPurging;
};

template<class T>
void ProxyRelease(nsCOMPtr<T> &object, nsIThread* thread)
{
  T* release;
  object.forget(&release);

  NS_ProxyRelease(thread, release);
}

template<class T>
void ProxyReleaseMainThread(nsCOMPtr<T> &object)
{
  nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
  ProxyRelease(object, mainThread);
}

} // net
} // 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"

#endif