netwerk/cache/nsCacheService.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* vim: set ts=8 sts=4 et sw=4 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef _nsCacheService_h_
michael@0 8 #define _nsCacheService_h_
michael@0 9
michael@0 10 #include "nsICacheService.h"
michael@0 11 #include "nsCacheSession.h"
michael@0 12 #include "nsCacheDevice.h"
michael@0 13 #include "nsCacheEntry.h"
michael@0 14 #include "nsThreadUtils.h"
michael@0 15 #include "nsICacheListener.h"
michael@0 16 #include "nsIMemoryReporter.h"
michael@0 17
michael@0 18 #include "prthread.h"
michael@0 19 #include "nsIObserver.h"
michael@0 20 #include "nsString.h"
michael@0 21 #include "nsTArray.h"
michael@0 22 #include "nsRefPtrHashtable.h"
michael@0 23 #include "mozilla/CondVar.h"
michael@0 24 #include "mozilla/Mutex.h"
michael@0 25 #include "mozilla/Telemetry.h"
michael@0 26
michael@0 27 class nsCacheRequest;
michael@0 28 class nsCacheProfilePrefObserver;
michael@0 29 class nsDiskCacheDevice;
michael@0 30 class nsMemoryCacheDevice;
michael@0 31 class nsOfflineCacheDevice;
michael@0 32 class nsCacheServiceAutoLock;
michael@0 33 class nsITimer;
michael@0 34 class mozIStorageService;
michael@0 35
michael@0 36
michael@0 37 /******************************************************************************
michael@0 38 * nsNotifyDoomListener
michael@0 39 *****************************************************************************/
michael@0 40
michael@0 41 class nsNotifyDoomListener : public nsRunnable {
michael@0 42 public:
michael@0 43 nsNotifyDoomListener(nsICacheListener *listener,
michael@0 44 nsresult status)
michael@0 45 : mListener(listener) // transfers reference
michael@0 46 , mStatus(status)
michael@0 47 {}
michael@0 48
michael@0 49 NS_IMETHOD Run()
michael@0 50 {
michael@0 51 mListener->OnCacheEntryDoomed(mStatus);
michael@0 52 NS_RELEASE(mListener);
michael@0 53 return NS_OK;
michael@0 54 }
michael@0 55
michael@0 56 private:
michael@0 57 nsICacheListener *mListener;
michael@0 58 nsresult mStatus;
michael@0 59 };
michael@0 60
michael@0 61 /******************************************************************************
michael@0 62 * nsCacheService
michael@0 63 ******************************************************************************/
michael@0 64
michael@0 65 class nsCacheService : public nsICacheServiceInternal,
michael@0 66 public nsIMemoryReporter
michael@0 67 {
michael@0 68 public:
michael@0 69 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 70 NS_DECL_NSICACHESERVICE
michael@0 71 NS_DECL_NSICACHESERVICEINTERNAL
michael@0 72 NS_DECL_NSIMEMORYREPORTER
michael@0 73
michael@0 74 nsCacheService();
michael@0 75 virtual ~nsCacheService();
michael@0 76
michael@0 77 // Define a Create method to be used with a factory:
michael@0 78 static nsresult
michael@0 79 Create(nsISupports* outer, const nsIID& iid, void* *result);
michael@0 80
michael@0 81
michael@0 82 /**
michael@0 83 * Methods called by nsCacheSession
michael@0 84 */
michael@0 85 static nsresult OpenCacheEntry(nsCacheSession * session,
michael@0 86 const nsACString & key,
michael@0 87 nsCacheAccessMode accessRequested,
michael@0 88 bool blockingMode,
michael@0 89 nsICacheListener * listener,
michael@0 90 nsICacheEntryDescriptor ** result);
michael@0 91
michael@0 92 static nsresult EvictEntriesForSession(nsCacheSession * session);
michael@0 93
michael@0 94 static nsresult IsStorageEnabledForPolicy(nsCacheStoragePolicy storagePolicy,
michael@0 95 bool * result);
michael@0 96
michael@0 97 static nsresult DoomEntry(nsCacheSession *session,
michael@0 98 const nsACString &key,
michael@0 99 nsICacheListener *listener);
michael@0 100
michael@0 101 /**
michael@0 102 * Methods called by nsCacheEntryDescriptor
michael@0 103 */
michael@0 104
michael@0 105 static void CloseDescriptor(nsCacheEntryDescriptor * descriptor);
michael@0 106
michael@0 107 static nsresult GetFileForEntry(nsCacheEntry * entry,
michael@0 108 nsIFile ** result);
michael@0 109
michael@0 110 static nsresult OpenInputStreamForEntry(nsCacheEntry * entry,
michael@0 111 nsCacheAccessMode mode,
michael@0 112 uint32_t offset,
michael@0 113 nsIInputStream ** result);
michael@0 114
michael@0 115 static nsresult OpenOutputStreamForEntry(nsCacheEntry * entry,
michael@0 116 nsCacheAccessMode mode,
michael@0 117 uint32_t offset,
michael@0 118 nsIOutputStream ** result);
michael@0 119
michael@0 120 static nsresult OnDataSizeChange(nsCacheEntry * entry, int32_t deltaSize);
michael@0 121
michael@0 122 static nsresult SetCacheElement(nsCacheEntry * entry, nsISupports * element);
michael@0 123
michael@0 124 static nsresult ValidateEntry(nsCacheEntry * entry);
michael@0 125
michael@0 126 static int32_t CacheCompressionLevel();
michael@0 127
michael@0 128 static bool GetClearingEntries();
michael@0 129
michael@0 130 static void GetCacheBaseDirectoty(nsIFile ** result);
michael@0 131 static void GetDiskCacheDirectory(nsIFile ** result);
michael@0 132 static void GetAppCacheDirectory(nsIFile ** result);
michael@0 133
michael@0 134 /**
michael@0 135 * Methods called by any cache classes
michael@0 136 */
michael@0 137
michael@0 138 static
michael@0 139 nsCacheService * GlobalInstance() { return gService; }
michael@0 140
michael@0 141 static nsresult DoomEntry(nsCacheEntry * entry);
michael@0 142
michael@0 143 static bool IsStorageEnabledForPolicy_Locked(nsCacheStoragePolicy policy);
michael@0 144
michael@0 145 /**
michael@0 146 * Called by disk cache to notify us to use the new max smart size
michael@0 147 */
michael@0 148 static void MarkStartingFresh();
michael@0 149
michael@0 150 /**
michael@0 151 * Methods called by nsApplicationCacheService
michael@0 152 */
michael@0 153
michael@0 154 nsresult GetOfflineDevice(nsOfflineCacheDevice ** aDevice);
michael@0 155
michael@0 156 /**
michael@0 157 * Creates an offline cache device that works over a specific profile directory.
michael@0 158 * A tool to preload offline cache for profiles different from the current
michael@0 159 * application's profile directory.
michael@0 160 */
michael@0 161 nsresult GetCustomOfflineDevice(nsIFile *aProfileDir,
michael@0 162 int32_t aQuota,
michael@0 163 nsOfflineCacheDevice **aDevice);
michael@0 164
michael@0 165 // This method may be called to release an object while the cache service
michael@0 166 // lock is being held. If a non-null target is specified and the target
michael@0 167 // does not correspond to the current thread, then the release will be
michael@0 168 // proxied to the specified target. Otherwise, the object will be added to
michael@0 169 // the list of objects to be released when the cache service is unlocked.
michael@0 170 static void ReleaseObject_Locked(nsISupports * object,
michael@0 171 nsIEventTarget * target = nullptr);
michael@0 172
michael@0 173 static nsresult DispatchToCacheIOThread(nsIRunnable* event);
michael@0 174
michael@0 175 // Calling this method will block the calling thread until all pending
michael@0 176 // events on the cache-io thread has finished. The calling thread must
michael@0 177 // hold the cache-lock
michael@0 178 static nsresult SyncWithCacheIOThread();
michael@0 179
michael@0 180
michael@0 181 /**
michael@0 182 * Methods called by nsCacheProfilePrefObserver
michael@0 183 */
michael@0 184 static void OnProfileShutdown(bool cleanse);
michael@0 185 static void OnProfileChanged();
michael@0 186
michael@0 187 static void SetDiskCacheEnabled(bool enabled);
michael@0 188 // Sets the disk cache capacity (in kilobytes)
michael@0 189 static void SetDiskCacheCapacity(int32_t capacity);
michael@0 190 // Set max size for a disk-cache entry (in KB). -1 disables limit up to
michael@0 191 // 1/8th of disk cache size
michael@0 192 static void SetDiskCacheMaxEntrySize(int32_t maxSize);
michael@0 193 // Set max size for a memory-cache entry (in kilobytes). -1 disables
michael@0 194 // limit up to 90% of memory cache size
michael@0 195 static void SetMemoryCacheMaxEntrySize(int32_t maxSize);
michael@0 196
michael@0 197 static void SetOfflineCacheEnabled(bool enabled);
michael@0 198 // Sets the offline cache capacity (in kilobytes)
michael@0 199 static void SetOfflineCacheCapacity(int32_t capacity);
michael@0 200
michael@0 201 static void SetMemoryCache();
michael@0 202
michael@0 203 static void SetCacheCompressionLevel(int32_t level);
michael@0 204
michael@0 205 // Starts smart cache size computation if disk device is available
michael@0 206 static nsresult SetDiskSmartSize();
michael@0 207
michael@0 208 static void MoveOrRemoveDiskCache(nsIFile *aOldCacheDir,
michael@0 209 nsIFile *aNewCacheDir,
michael@0 210 const char *aCacheSubdir);
michael@0 211
michael@0 212 nsresult Init();
michael@0 213 void Shutdown();
michael@0 214
michael@0 215 static bool IsInitialized()
michael@0 216 {
michael@0 217 if (!gService) {
michael@0 218 return false;
michael@0 219 }
michael@0 220 return gService->mInitialized;
michael@0 221 }
michael@0 222
michael@0 223 static void AssertOwnsLock()
michael@0 224 { gService->mLock.AssertCurrentThreadOwns(); }
michael@0 225
michael@0 226 static void LeavePrivateBrowsing();
michael@0 227 bool IsDoomListEmpty();
michael@0 228
michael@0 229 typedef bool (*DoomCheckFn)(nsCacheEntry* entry);
michael@0 230
michael@0 231 private:
michael@0 232 friend class nsCacheServiceAutoLock;
michael@0 233 friend class nsOfflineCacheDevice;
michael@0 234 friend class nsProcessRequestEvent;
michael@0 235 friend class nsSetSmartSizeEvent;
michael@0 236 friend class nsBlockOnCacheThreadEvent;
michael@0 237 friend class nsSetDiskSmartSizeCallback;
michael@0 238 friend class nsDoomEvent;
michael@0 239 friend class nsDisableOldMaxSmartSizePrefEvent;
michael@0 240 friend class nsDiskCacheMap;
michael@0 241 friend class nsAsyncDoomEvent;
michael@0 242 friend class nsCacheEntryDescriptor;
michael@0 243
michael@0 244 /**
michael@0 245 * Internal Methods
michael@0 246 */
michael@0 247
michael@0 248 static void Lock(::mozilla::Telemetry::ID mainThreadLockerID);
michael@0 249 static void Unlock();
michael@0 250 void LockAcquired();
michael@0 251 void LockReleased();
michael@0 252
michael@0 253 nsresult CreateDiskDevice();
michael@0 254 nsresult CreateOfflineDevice();
michael@0 255 nsresult CreateCustomOfflineDevice(nsIFile *aProfileDir,
michael@0 256 int32_t aQuota,
michael@0 257 nsOfflineCacheDevice **aDevice);
michael@0 258 nsresult CreateMemoryDevice();
michael@0 259
michael@0 260 nsresult RemoveCustomOfflineDevice(nsOfflineCacheDevice *aDevice);
michael@0 261
michael@0 262 nsresult CreateRequest(nsCacheSession * session,
michael@0 263 const nsACString & clientKey,
michael@0 264 nsCacheAccessMode accessRequested,
michael@0 265 bool blockingMode,
michael@0 266 nsICacheListener * listener,
michael@0 267 nsCacheRequest ** request);
michael@0 268
michael@0 269 nsresult DoomEntry_Internal(nsCacheEntry * entry,
michael@0 270 bool doProcessPendingRequests);
michael@0 271
michael@0 272 nsresult EvictEntriesForClient(const char * clientID,
michael@0 273 nsCacheStoragePolicy storagePolicy);
michael@0 274
michael@0 275 // Notifies request listener asynchronously on the request's thread, and
michael@0 276 // releases the descriptor on the request's thread. If this method fails,
michael@0 277 // the descriptor is not released.
michael@0 278 nsresult NotifyListener(nsCacheRequest * request,
michael@0 279 nsICacheEntryDescriptor * descriptor,
michael@0 280 nsCacheAccessMode accessGranted,
michael@0 281 nsresult error);
michael@0 282
michael@0 283 nsresult ActivateEntry(nsCacheRequest * request,
michael@0 284 nsCacheEntry ** entry,
michael@0 285 nsCacheEntry ** doomedEntry);
michael@0 286
michael@0 287 nsCacheDevice * EnsureEntryHasDevice(nsCacheEntry * entry);
michael@0 288
michael@0 289 nsCacheEntry * SearchCacheDevices(nsCString * key, nsCacheStoragePolicy policy, bool *collision);
michael@0 290
michael@0 291 void DeactivateEntry(nsCacheEntry * entry);
michael@0 292
michael@0 293 nsresult ProcessRequest(nsCacheRequest * request,
michael@0 294 bool calledFromOpenCacheEntry,
michael@0 295 nsICacheEntryDescriptor ** result);
michael@0 296
michael@0 297 nsresult ProcessPendingRequests(nsCacheEntry * entry);
michael@0 298
michael@0 299 void ClearDoomList(void);
michael@0 300 void DoomActiveEntries(DoomCheckFn check);
michael@0 301 void CloseAllStreams();
michael@0 302 void FireClearNetworkCacheStoredAnywhereNotification();
michael@0 303
michael@0 304 static
michael@0 305 PLDHashOperator GetActiveEntries(PLDHashTable * table,
michael@0 306 PLDHashEntryHdr * hdr,
michael@0 307 uint32_t number,
michael@0 308 void * arg);
michael@0 309 static
michael@0 310 PLDHashOperator RemoveActiveEntry(PLDHashTable * table,
michael@0 311 PLDHashEntryHdr * hdr,
michael@0 312 uint32_t number,
michael@0 313 void * arg);
michael@0 314
michael@0 315 static
michael@0 316 PLDHashOperator ShutdownCustomCacheDeviceEnum(const nsAString& aProfileDir,
michael@0 317 nsRefPtr<nsOfflineCacheDevice>& aDevice,
michael@0 318 void* aUserArg);
michael@0 319 #if defined(PR_LOGGING)
michael@0 320 void LogCacheStatistics();
michael@0 321 #endif
michael@0 322
michael@0 323 nsresult SetDiskSmartSize_Locked();
michael@0 324
michael@0 325 /**
michael@0 326 * Data Members
michael@0 327 */
michael@0 328
michael@0 329 static nsCacheService * gService; // there can be only one...
michael@0 330
michael@0 331 nsCOMPtr<mozIStorageService> mStorageService;
michael@0 332
michael@0 333 nsCacheProfilePrefObserver * mObserver;
michael@0 334
michael@0 335 mozilla::Mutex mLock;
michael@0 336 mozilla::CondVar mCondVar;
michael@0 337
michael@0 338 mozilla::Mutex mTimeStampLock;
michael@0 339 mozilla::TimeStamp mLockAcquiredTimeStamp;
michael@0 340
michael@0 341 nsCOMPtr<nsIThread> mCacheIOThread;
michael@0 342
michael@0 343 nsTArray<nsISupports*> mDoomedObjects;
michael@0 344 nsCOMPtr<nsITimer> mSmartSizeTimer;
michael@0 345
michael@0 346 bool mInitialized;
michael@0 347 bool mClearingEntries;
michael@0 348
michael@0 349 bool mEnableMemoryDevice;
michael@0 350 bool mEnableDiskDevice;
michael@0 351 bool mEnableOfflineDevice;
michael@0 352
michael@0 353 nsMemoryCacheDevice * mMemoryDevice;
michael@0 354 nsDiskCacheDevice * mDiskDevice;
michael@0 355 nsOfflineCacheDevice * mOfflineDevice;
michael@0 356
michael@0 357 nsRefPtrHashtable<nsStringHashKey, nsOfflineCacheDevice> mCustomOfflineDevices;
michael@0 358
michael@0 359 nsCacheEntryHashTable mActiveEntries;
michael@0 360 PRCList mDoomedEntries;
michael@0 361
michael@0 362 // stats
michael@0 363
michael@0 364 uint32_t mTotalEntries;
michael@0 365 uint32_t mCacheHits;
michael@0 366 uint32_t mCacheMisses;
michael@0 367 uint32_t mMaxKeyLength;
michael@0 368 uint32_t mMaxDataSize;
michael@0 369 uint32_t mMaxMetaSize;
michael@0 370
michael@0 371 // Unexpected error totals
michael@0 372 uint32_t mDeactivateFailures;
michael@0 373 uint32_t mDeactivatedUnboundEntries;
michael@0 374 };
michael@0 375
michael@0 376 /******************************************************************************
michael@0 377 * nsCacheServiceAutoLock
michael@0 378 ******************************************************************************/
michael@0 379
michael@0 380 #define LOCK_TELEM(x) \
michael@0 381 (::mozilla::Telemetry::CACHE_SERVICE_LOCK_WAIT_MAINTHREAD_##x)
michael@0 382
michael@0 383 // Instantiate this class to acquire the cache service lock for a particular
michael@0 384 // execution scope.
michael@0 385 class nsCacheServiceAutoLock {
michael@0 386 public:
michael@0 387 nsCacheServiceAutoLock(mozilla::Telemetry::ID mainThreadLockerID) {
michael@0 388 nsCacheService::Lock(mainThreadLockerID);
michael@0 389 }
michael@0 390 ~nsCacheServiceAutoLock() {
michael@0 391 nsCacheService::Unlock();
michael@0 392 }
michael@0 393 };
michael@0 394
michael@0 395 #endif // _nsCacheService_h_

mercurial