netwerk/cache2/CacheFileIOManager.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #ifndef CacheFileIOManager__h__
michael@0 6 #define CacheFileIOManager__h__
michael@0 7
michael@0 8 #include "CacheIOThread.h"
michael@0 9 #include "nsIEventTarget.h"
michael@0 10 #include "nsITimer.h"
michael@0 11 #include "nsCOMPtr.h"
michael@0 12 #include "mozilla/SHA1.h"
michael@0 13 #include "mozilla/TimeStamp.h"
michael@0 14 #include "nsTArray.h"
michael@0 15 #include "nsString.h"
michael@0 16 #include "nsTHashtable.h"
michael@0 17 #include "prio.h"
michael@0 18
michael@0 19 //#define DEBUG_HANDLES 1
michael@0 20
michael@0 21 class nsIFile;
michael@0 22 class nsITimer;
michael@0 23 class nsIDirectoryEnumerator;
michael@0 24 class nsILoadContextInfo;
michael@0 25
michael@0 26 namespace mozilla {
michael@0 27 namespace net {
michael@0 28
michael@0 29 class CacheFile;
michael@0 30 #ifdef DEBUG_HANDLES
michael@0 31 class CacheFileHandlesEntry;
michael@0 32 #endif
michael@0 33
michael@0 34 const char kEntriesDir[] = "entries";
michael@0 35 const char kDoomedDir[] = "doomed";
michael@0 36 const char kTrashDir[] = "trash";
michael@0 37
michael@0 38
michael@0 39 class CacheFileHandle : public nsISupports
michael@0 40 {
michael@0 41 public:
michael@0 42 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 43 bool DispatchRelease();
michael@0 44
michael@0 45 CacheFileHandle(const SHA1Sum::Hash *aHash, bool aPriority);
michael@0 46 CacheFileHandle(const nsACString &aKey, bool aPriority);
michael@0 47 CacheFileHandle(const CacheFileHandle &aOther);
michael@0 48 void Log();
michael@0 49 bool IsDoomed() const { return mIsDoomed; }
michael@0 50 const SHA1Sum::Hash *Hash() const { return mHash; }
michael@0 51 int64_t FileSize() const { return mFileSize; }
michael@0 52 uint32_t FileSizeInK() const;
michael@0 53 bool IsPriority() const { return mPriority; }
michael@0 54 bool FileExists() const { return mFileExists; }
michael@0 55 bool IsClosed() const { return mClosed; }
michael@0 56 bool IsSpecialFile() const { return !mHash; }
michael@0 57 nsCString & Key() { return mKey; }
michael@0 58
michael@0 59 // Memory reporting
michael@0 60 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
michael@0 61 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
michael@0 62
michael@0 63 private:
michael@0 64 friend class CacheFileIOManager;
michael@0 65 friend class CacheFileHandles;
michael@0 66 friend class ReleaseNSPRHandleEvent;
michael@0 67
michael@0 68 virtual ~CacheFileHandle();
michael@0 69
michael@0 70 const SHA1Sum::Hash *mHash;
michael@0 71 bool mIsDoomed;
michael@0 72 bool mPriority;
michael@0 73 bool mClosed;
michael@0 74 bool mInvalid;
michael@0 75 bool mFileExists; // This means that the file should exists,
michael@0 76 // but it can be still deleted by OS/user
michael@0 77 // and then a subsequent OpenNSPRFileDesc()
michael@0 78 // will fail.
michael@0 79 nsCOMPtr<nsIFile> mFile;
michael@0 80 int64_t mFileSize;
michael@0 81 PRFileDesc *mFD; // if null then the file doesn't exists on the disk
michael@0 82 nsCString mKey;
michael@0 83 };
michael@0 84
michael@0 85 class CacheFileHandles {
michael@0 86 public:
michael@0 87 CacheFileHandles();
michael@0 88 ~CacheFileHandles();
michael@0 89
michael@0 90 nsresult GetHandle(const SHA1Sum::Hash *aHash, bool aReturnDoomed, CacheFileHandle **_retval);
michael@0 91 nsresult NewHandle(const SHA1Sum::Hash *aHash, bool aPriority, CacheFileHandle **_retval);
michael@0 92 void RemoveHandle(CacheFileHandle *aHandlle);
michael@0 93 void GetAllHandles(nsTArray<nsRefPtr<CacheFileHandle> > *_retval);
michael@0 94 void GetActiveHandles(nsTArray<nsRefPtr<CacheFileHandle> > *_retval);
michael@0 95 void ClearAll();
michael@0 96 uint32_t HandleCount();
michael@0 97
michael@0 98 #ifdef DEBUG_HANDLES
michael@0 99 void Log(CacheFileHandlesEntry *entry);
michael@0 100 #endif
michael@0 101
michael@0 102 // Memory reporting
michael@0 103 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
michael@0 104 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
michael@0 105
michael@0 106 class HandleHashKey : public PLDHashEntryHdr
michael@0 107 {
michael@0 108 public:
michael@0 109 typedef const SHA1Sum::Hash& KeyType;
michael@0 110 typedef const SHA1Sum::Hash* KeyTypePointer;
michael@0 111
michael@0 112 HandleHashKey(KeyTypePointer aKey)
michael@0 113 {
michael@0 114 MOZ_COUNT_CTOR(HandleHashKey);
michael@0 115 mHash = (SHA1Sum::Hash*)new uint8_t[SHA1Sum::HashSize];
michael@0 116 memcpy(mHash, aKey, sizeof(SHA1Sum::Hash));
michael@0 117 }
michael@0 118 HandleHashKey(const HandleHashKey& aOther)
michael@0 119 {
michael@0 120 NS_NOTREACHED("HandleHashKey copy constructor is forbidden!");
michael@0 121 }
michael@0 122 ~HandleHashKey()
michael@0 123 {
michael@0 124 MOZ_COUNT_DTOR(HandleHashKey);
michael@0 125 }
michael@0 126
michael@0 127 bool KeyEquals(KeyTypePointer aKey) const
michael@0 128 {
michael@0 129 return memcmp(mHash, aKey, sizeof(SHA1Sum::Hash)) == 0;
michael@0 130 }
michael@0 131 static KeyTypePointer KeyToPointer(KeyType aKey)
michael@0 132 {
michael@0 133 return &aKey;
michael@0 134 }
michael@0 135 static PLDHashNumber HashKey(KeyTypePointer aKey)
michael@0 136 {
michael@0 137 return (reinterpret_cast<const uint32_t *>(aKey))[0];
michael@0 138 }
michael@0 139
michael@0 140 void AddHandle(CacheFileHandle* aHandle);
michael@0 141 void RemoveHandle(CacheFileHandle* aHandle);
michael@0 142 already_AddRefed<CacheFileHandle> GetNewestHandle();
michael@0 143 void GetHandles(nsTArray<nsRefPtr<CacheFileHandle> > &aResult);
michael@0 144
michael@0 145 SHA1Sum::Hash *Hash() const { return mHash; }
michael@0 146 bool IsEmpty() const { return mHandles.Length() == 0; }
michael@0 147
michael@0 148 enum { ALLOW_MEMMOVE = true };
michael@0 149
michael@0 150 #ifdef DEBUG
michael@0 151 void AssertHandlesState();
michael@0 152 #endif
michael@0 153
michael@0 154 // Memory reporting
michael@0 155 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
michael@0 156 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
michael@0 157
michael@0 158 private:
michael@0 159 nsAutoArrayPtr<SHA1Sum::Hash> mHash;
michael@0 160 // Use weak pointers since the hash table access is on a single thread
michael@0 161 // only and CacheFileHandle removes itself from this table in its dtor
michael@0 162 // that may only be called on the same thread as we work with the hashtable
michael@0 163 // since we dispatch its Release() to this thread.
michael@0 164 nsTArray<CacheFileHandle*> mHandles;
michael@0 165 };
michael@0 166
michael@0 167 private:
michael@0 168 nsTHashtable<HandleHashKey> mTable;
michael@0 169 };
michael@0 170
michael@0 171 ////////////////////////////////////////////////////////////////////////////////
michael@0 172
michael@0 173 class OpenFileEvent;
michael@0 174 class CloseFileEvent;
michael@0 175 class ReadEvent;
michael@0 176 class WriteEvent;
michael@0 177 class MetadataWriteScheduleEvent;
michael@0 178 class CacheFileContextEvictor;
michael@0 179
michael@0 180 #define CACHEFILEIOLISTENER_IID \
michael@0 181 { /* dcaf2ddc-17cf-4242-bca1-8c86936375a5 */ \
michael@0 182 0xdcaf2ddc, \
michael@0 183 0x17cf, \
michael@0 184 0x4242, \
michael@0 185 {0xbc, 0xa1, 0x8c, 0x86, 0x93, 0x63, 0x75, 0xa5} \
michael@0 186 }
michael@0 187
michael@0 188 class CacheFileIOListener : public nsISupports
michael@0 189 {
michael@0 190 public:
michael@0 191 NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILEIOLISTENER_IID)
michael@0 192
michael@0 193 NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult) = 0;
michael@0 194 NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf,
michael@0 195 nsresult aResult) = 0;
michael@0 196 NS_IMETHOD OnDataRead(CacheFileHandle *aHandle, char *aBuf,
michael@0 197 nsresult aResult) = 0;
michael@0 198 NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult) = 0;
michael@0 199 NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult) = 0;
michael@0 200 NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult) = 0;
michael@0 201 };
michael@0 202
michael@0 203 NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileIOListener, CACHEFILEIOLISTENER_IID)
michael@0 204
michael@0 205
michael@0 206 class CacheFileIOManager : public nsITimerCallback
michael@0 207 {
michael@0 208 public:
michael@0 209 NS_DECL_THREADSAFE_ISUPPORTS
michael@0 210 NS_DECL_NSITIMERCALLBACK
michael@0 211
michael@0 212 enum {
michael@0 213 OPEN = 0U,
michael@0 214 CREATE = 1U,
michael@0 215 CREATE_NEW = 2U,
michael@0 216 PRIORITY = 4U,
michael@0 217 SPECIAL_FILE = 8U
michael@0 218 };
michael@0 219
michael@0 220 CacheFileIOManager();
michael@0 221
michael@0 222 static nsresult Init();
michael@0 223 static nsresult Shutdown();
michael@0 224 static nsresult OnProfile();
michael@0 225 static already_AddRefed<nsIEventTarget> IOTarget();
michael@0 226 static already_AddRefed<CacheIOThread> IOThread();
michael@0 227 static bool IsOnIOThread();
michael@0 228 static bool IsOnIOThreadOrCeased();
michael@0 229 static bool IsShutdown();
michael@0 230
michael@0 231 // Make aFile's WriteMetadataIfNeeded be called automatically after
michael@0 232 // a short interval.
michael@0 233 static nsresult ScheduleMetadataWrite(CacheFile * aFile);
michael@0 234 // Remove aFile from the scheduling registry array.
michael@0 235 // WriteMetadataIfNeeded will not be automatically called.
michael@0 236 static nsresult UnscheduleMetadataWrite(CacheFile * aFile);
michael@0 237 // Shuts the scheduling off and flushes all pending metadata writes.
michael@0 238 static nsresult ShutdownMetadataWriteScheduling();
michael@0 239
michael@0 240 static nsresult OpenFile(const nsACString &aKey,
michael@0 241 uint32_t aFlags, bool aResultOnAnyThread,
michael@0 242 CacheFileIOListener *aCallback);
michael@0 243 static nsresult Read(CacheFileHandle *aHandle, int64_t aOffset,
michael@0 244 char *aBuf, int32_t aCount, bool aResultOnAnyThread,
michael@0 245 CacheFileIOListener *aCallback);
michael@0 246 static nsresult Write(CacheFileHandle *aHandle, int64_t aOffset,
michael@0 247 const char *aBuf, int32_t aCount, bool aValidate,
michael@0 248 CacheFileIOListener *aCallback);
michael@0 249 static nsresult DoomFile(CacheFileHandle *aHandle,
michael@0 250 CacheFileIOListener *aCallback);
michael@0 251 static nsresult DoomFileByKey(const nsACString &aKey,
michael@0 252 CacheFileIOListener *aCallback);
michael@0 253 static nsresult ReleaseNSPRHandle(CacheFileHandle *aHandle);
michael@0 254 static nsresult TruncateSeekSetEOF(CacheFileHandle *aHandle,
michael@0 255 int64_t aTruncatePos, int64_t aEOFPos,
michael@0 256 CacheFileIOListener *aCallback);
michael@0 257 static nsresult RenameFile(CacheFileHandle *aHandle,
michael@0 258 const nsACString &aNewName,
michael@0 259 CacheFileIOListener *aCallback);
michael@0 260 static nsresult EvictIfOverLimit();
michael@0 261 static nsresult EvictAll();
michael@0 262 static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo);
michael@0 263
michael@0 264 static nsresult InitIndexEntry(CacheFileHandle *aHandle,
michael@0 265 uint32_t aAppId,
michael@0 266 bool aAnonymous,
michael@0 267 bool aInBrowser);
michael@0 268 static nsresult UpdateIndexEntry(CacheFileHandle *aHandle,
michael@0 269 const uint32_t *aFrecency,
michael@0 270 const uint32_t *aExpirationTime);
michael@0 271
michael@0 272 static nsresult UpdateIndexEntry();
michael@0 273
michael@0 274 enum EEnumerateMode {
michael@0 275 ENTRIES,
michael@0 276 DOOMED
michael@0 277 };
michael@0 278
michael@0 279 static void GetCacheDirectory(nsIFile** result);
michael@0 280
michael@0 281 // Memory reporting
michael@0 282 static size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
michael@0 283 static size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
michael@0 284
michael@0 285 private:
michael@0 286 friend class CacheFileHandle;
michael@0 287 friend class CacheFileChunk;
michael@0 288 friend class CacheFile;
michael@0 289 friend class ShutdownEvent;
michael@0 290 friend class OpenFileEvent;
michael@0 291 friend class CloseHandleEvent;
michael@0 292 friend class ReadEvent;
michael@0 293 friend class WriteEvent;
michael@0 294 friend class DoomFileEvent;
michael@0 295 friend class DoomFileByKeyEvent;
michael@0 296 friend class ReleaseNSPRHandleEvent;
michael@0 297 friend class TruncateSeekSetEOFEvent;
michael@0 298 friend class RenameFileEvent;
michael@0 299 friend class CacheIndex;
michael@0 300 friend class MetadataWriteScheduleEvent;
michael@0 301 friend class CacheFileContextEvictor;
michael@0 302
michael@0 303 virtual ~CacheFileIOManager();
michael@0 304
michael@0 305 nsresult InitInternal();
michael@0 306 nsresult ShutdownInternal();
michael@0 307
michael@0 308 nsresult OpenFileInternal(const SHA1Sum::Hash *aHash,
michael@0 309 const nsACString &aKey,
michael@0 310 uint32_t aFlags,
michael@0 311 CacheFileHandle **_retval);
michael@0 312 nsresult OpenSpecialFileInternal(const nsACString &aKey,
michael@0 313 uint32_t aFlags,
michael@0 314 CacheFileHandle **_retval);
michael@0 315 nsresult CloseHandleInternal(CacheFileHandle *aHandle);
michael@0 316 nsresult ReadInternal(CacheFileHandle *aHandle, int64_t aOffset,
michael@0 317 char *aBuf, int32_t aCount);
michael@0 318 nsresult WriteInternal(CacheFileHandle *aHandle, int64_t aOffset,
michael@0 319 const char *aBuf, int32_t aCount, bool aValidate);
michael@0 320 nsresult DoomFileInternal(CacheFileHandle *aHandle);
michael@0 321 nsresult DoomFileByKeyInternal(const SHA1Sum::Hash *aHash);
michael@0 322 nsresult ReleaseNSPRHandleInternal(CacheFileHandle *aHandle);
michael@0 323 nsresult TruncateSeekSetEOFInternal(CacheFileHandle *aHandle,
michael@0 324 int64_t aTruncatePos, int64_t aEOFPos);
michael@0 325 nsresult RenameFileInternal(CacheFileHandle *aHandle,
michael@0 326 const nsACString &aNewName);
michael@0 327 nsresult EvictIfOverLimitInternal();
michael@0 328 nsresult OverLimitEvictionInternal();
michael@0 329 nsresult EvictAllInternal();
michael@0 330 nsresult EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo);
michael@0 331
michael@0 332 nsresult TrashDirectory(nsIFile *aFile);
michael@0 333 static void OnTrashTimer(nsITimer *aTimer, void *aClosure);
michael@0 334 nsresult StartRemovingTrash();
michael@0 335 nsresult RemoveTrashInternal();
michael@0 336 nsresult FindTrashDirToRemove();
michael@0 337
michael@0 338 nsresult CreateFile(CacheFileHandle *aHandle);
michael@0 339 static void HashToStr(const SHA1Sum::Hash *aHash, nsACString &_retval);
michael@0 340 static nsresult StrToHash(const nsACString &aHash, SHA1Sum::Hash *_retval);
michael@0 341 nsresult GetFile(const SHA1Sum::Hash *aHash, nsIFile **_retval);
michael@0 342 nsresult GetSpecialFile(const nsACString &aKey, nsIFile **_retval);
michael@0 343 nsresult GetDoomedFile(nsIFile **_retval);
michael@0 344 nsresult IsEmptyDirectory(nsIFile *aFile, bool *_retval);
michael@0 345 nsresult CheckAndCreateDir(nsIFile *aFile, const char *aDir,
michael@0 346 bool aEnsureEmptyDir);
michael@0 347 nsresult CreateCacheTree();
michael@0 348 nsresult OpenNSPRHandle(CacheFileHandle *aHandle, bool aCreate = false);
michael@0 349 void NSPRHandleUsed(CacheFileHandle *aHandle);
michael@0 350
michael@0 351 // Removing all cache files during shutdown
michael@0 352 nsresult SyncRemoveDir(nsIFile *aFile, const char *aDir);
michael@0 353 void SyncRemoveAllCacheFiles();
michael@0 354
michael@0 355 nsresult ScheduleMetadataWriteInternal(CacheFile * aFile);
michael@0 356 nsresult UnscheduleMetadataWriteInternal(CacheFile * aFile);
michael@0 357 nsresult ShutdownMetadataWriteSchedulingInternal();
michael@0 358
michael@0 359 static nsresult CacheIndexStateChanged();
michael@0 360 nsresult CacheIndexStateChangedInternal();
michael@0 361
michael@0 362 // Smart size calculation. UpdateSmartCacheSize() must be called on IO thread.
michael@0 363 // It is called in EvictIfOverLimitInternal() just before we decide whether to
michael@0 364 // start overlimit eviction or not and also in OverLimitEvictionInternal()
michael@0 365 // before we start an eviction loop.
michael@0 366 nsresult UpdateSmartCacheSize();
michael@0 367
michael@0 368 // Memory reporting (private part)
michael@0 369 size_t SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const;
michael@0 370
michael@0 371 static CacheFileIOManager *gInstance;
michael@0 372 TimeStamp mStartTime;
michael@0 373 bool mShuttingDown;
michael@0 374 nsRefPtr<CacheIOThread> mIOThread;
michael@0 375 nsCOMPtr<nsIFile> mCacheDirectory;
michael@0 376 bool mTreeCreated;
michael@0 377 CacheFileHandles mHandles;
michael@0 378 nsTArray<CacheFileHandle *> mHandlesByLastUsed;
michael@0 379 nsTArray<CacheFileHandle *> mSpecialHandles;
michael@0 380 nsTArray<nsRefPtr<CacheFile> > mScheduledMetadataWrites;
michael@0 381 nsCOMPtr<nsITimer> mMetadataWritesTimer;
michael@0 382 bool mOverLimitEvicting;
michael@0 383 bool mRemovingTrashDirs;
michael@0 384 nsCOMPtr<nsITimer> mTrashTimer;
michael@0 385 nsCOMPtr<nsIFile> mTrashDir;
michael@0 386 nsCOMPtr<nsIDirectoryEnumerator> mTrashDirEnumerator;
michael@0 387 nsTArray<nsCString> mFailedTrashDirs;
michael@0 388 nsRefPtr<CacheFileContextEvictor> mContextEvictor;
michael@0 389 TimeStamp mLastSmartSizeTime;
michael@0 390 };
michael@0 391
michael@0 392 } // net
michael@0 393 } // mozilla
michael@0 394
michael@0 395 #endif

mercurial