1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/netwerk/cache2/CacheFileIOManager.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,395 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#ifndef CacheFileIOManager__h__ 1.9 +#define CacheFileIOManager__h__ 1.10 + 1.11 +#include "CacheIOThread.h" 1.12 +#include "nsIEventTarget.h" 1.13 +#include "nsITimer.h" 1.14 +#include "nsCOMPtr.h" 1.15 +#include "mozilla/SHA1.h" 1.16 +#include "mozilla/TimeStamp.h" 1.17 +#include "nsTArray.h" 1.18 +#include "nsString.h" 1.19 +#include "nsTHashtable.h" 1.20 +#include "prio.h" 1.21 + 1.22 +//#define DEBUG_HANDLES 1 1.23 + 1.24 +class nsIFile; 1.25 +class nsITimer; 1.26 +class nsIDirectoryEnumerator; 1.27 +class nsILoadContextInfo; 1.28 + 1.29 +namespace mozilla { 1.30 +namespace net { 1.31 + 1.32 +class CacheFile; 1.33 +#ifdef DEBUG_HANDLES 1.34 +class CacheFileHandlesEntry; 1.35 +#endif 1.36 + 1.37 +const char kEntriesDir[] = "entries"; 1.38 +const char kDoomedDir[] = "doomed"; 1.39 +const char kTrashDir[] = "trash"; 1.40 + 1.41 + 1.42 +class CacheFileHandle : public nsISupports 1.43 +{ 1.44 +public: 1.45 + NS_DECL_THREADSAFE_ISUPPORTS 1.46 + bool DispatchRelease(); 1.47 + 1.48 + CacheFileHandle(const SHA1Sum::Hash *aHash, bool aPriority); 1.49 + CacheFileHandle(const nsACString &aKey, bool aPriority); 1.50 + CacheFileHandle(const CacheFileHandle &aOther); 1.51 + void Log(); 1.52 + bool IsDoomed() const { return mIsDoomed; } 1.53 + const SHA1Sum::Hash *Hash() const { return mHash; } 1.54 + int64_t FileSize() const { return mFileSize; } 1.55 + uint32_t FileSizeInK() const; 1.56 + bool IsPriority() const { return mPriority; } 1.57 + bool FileExists() const { return mFileExists; } 1.58 + bool IsClosed() const { return mClosed; } 1.59 + bool IsSpecialFile() const { return !mHash; } 1.60 + nsCString & Key() { return mKey; } 1.61 + 1.62 + // Memory reporting 1.63 + size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 1.64 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 1.65 + 1.66 +private: 1.67 + friend class CacheFileIOManager; 1.68 + friend class CacheFileHandles; 1.69 + friend class ReleaseNSPRHandleEvent; 1.70 + 1.71 + virtual ~CacheFileHandle(); 1.72 + 1.73 + const SHA1Sum::Hash *mHash; 1.74 + bool mIsDoomed; 1.75 + bool mPriority; 1.76 + bool mClosed; 1.77 + bool mInvalid; 1.78 + bool mFileExists; // This means that the file should exists, 1.79 + // but it can be still deleted by OS/user 1.80 + // and then a subsequent OpenNSPRFileDesc() 1.81 + // will fail. 1.82 + nsCOMPtr<nsIFile> mFile; 1.83 + int64_t mFileSize; 1.84 + PRFileDesc *mFD; // if null then the file doesn't exists on the disk 1.85 + nsCString mKey; 1.86 +}; 1.87 + 1.88 +class CacheFileHandles { 1.89 +public: 1.90 + CacheFileHandles(); 1.91 + ~CacheFileHandles(); 1.92 + 1.93 + nsresult GetHandle(const SHA1Sum::Hash *aHash, bool aReturnDoomed, CacheFileHandle **_retval); 1.94 + nsresult NewHandle(const SHA1Sum::Hash *aHash, bool aPriority, CacheFileHandle **_retval); 1.95 + void RemoveHandle(CacheFileHandle *aHandlle); 1.96 + void GetAllHandles(nsTArray<nsRefPtr<CacheFileHandle> > *_retval); 1.97 + void GetActiveHandles(nsTArray<nsRefPtr<CacheFileHandle> > *_retval); 1.98 + void ClearAll(); 1.99 + uint32_t HandleCount(); 1.100 + 1.101 +#ifdef DEBUG_HANDLES 1.102 + void Log(CacheFileHandlesEntry *entry); 1.103 +#endif 1.104 + 1.105 + // Memory reporting 1.106 + size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 1.107 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 1.108 + 1.109 + class HandleHashKey : public PLDHashEntryHdr 1.110 + { 1.111 + public: 1.112 + typedef const SHA1Sum::Hash& KeyType; 1.113 + typedef const SHA1Sum::Hash* KeyTypePointer; 1.114 + 1.115 + HandleHashKey(KeyTypePointer aKey) 1.116 + { 1.117 + MOZ_COUNT_CTOR(HandleHashKey); 1.118 + mHash = (SHA1Sum::Hash*)new uint8_t[SHA1Sum::HashSize]; 1.119 + memcpy(mHash, aKey, sizeof(SHA1Sum::Hash)); 1.120 + } 1.121 + HandleHashKey(const HandleHashKey& aOther) 1.122 + { 1.123 + NS_NOTREACHED("HandleHashKey copy constructor is forbidden!"); 1.124 + } 1.125 + ~HandleHashKey() 1.126 + { 1.127 + MOZ_COUNT_DTOR(HandleHashKey); 1.128 + } 1.129 + 1.130 + bool KeyEquals(KeyTypePointer aKey) const 1.131 + { 1.132 + return memcmp(mHash, aKey, sizeof(SHA1Sum::Hash)) == 0; 1.133 + } 1.134 + static KeyTypePointer KeyToPointer(KeyType aKey) 1.135 + { 1.136 + return &aKey; 1.137 + } 1.138 + static PLDHashNumber HashKey(KeyTypePointer aKey) 1.139 + { 1.140 + return (reinterpret_cast<const uint32_t *>(aKey))[0]; 1.141 + } 1.142 + 1.143 + void AddHandle(CacheFileHandle* aHandle); 1.144 + void RemoveHandle(CacheFileHandle* aHandle); 1.145 + already_AddRefed<CacheFileHandle> GetNewestHandle(); 1.146 + void GetHandles(nsTArray<nsRefPtr<CacheFileHandle> > &aResult); 1.147 + 1.148 + SHA1Sum::Hash *Hash() const { return mHash; } 1.149 + bool IsEmpty() const { return mHandles.Length() == 0; } 1.150 + 1.151 + enum { ALLOW_MEMMOVE = true }; 1.152 + 1.153 +#ifdef DEBUG 1.154 + void AssertHandlesState(); 1.155 +#endif 1.156 + 1.157 + // Memory reporting 1.158 + size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 1.159 + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; 1.160 + 1.161 + private: 1.162 + nsAutoArrayPtr<SHA1Sum::Hash> mHash; 1.163 + // Use weak pointers since the hash table access is on a single thread 1.164 + // only and CacheFileHandle removes itself from this table in its dtor 1.165 + // that may only be called on the same thread as we work with the hashtable 1.166 + // since we dispatch its Release() to this thread. 1.167 + nsTArray<CacheFileHandle*> mHandles; 1.168 + }; 1.169 + 1.170 +private: 1.171 + nsTHashtable<HandleHashKey> mTable; 1.172 +}; 1.173 + 1.174 +//////////////////////////////////////////////////////////////////////////////// 1.175 + 1.176 +class OpenFileEvent; 1.177 +class CloseFileEvent; 1.178 +class ReadEvent; 1.179 +class WriteEvent; 1.180 +class MetadataWriteScheduleEvent; 1.181 +class CacheFileContextEvictor; 1.182 + 1.183 +#define CACHEFILEIOLISTENER_IID \ 1.184 +{ /* dcaf2ddc-17cf-4242-bca1-8c86936375a5 */ \ 1.185 + 0xdcaf2ddc, \ 1.186 + 0x17cf, \ 1.187 + 0x4242, \ 1.188 + {0xbc, 0xa1, 0x8c, 0x86, 0x93, 0x63, 0x75, 0xa5} \ 1.189 +} 1.190 + 1.191 +class CacheFileIOListener : public nsISupports 1.192 +{ 1.193 +public: 1.194 + NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILEIOLISTENER_IID) 1.195 + 1.196 + NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult) = 0; 1.197 + NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf, 1.198 + nsresult aResult) = 0; 1.199 + NS_IMETHOD OnDataRead(CacheFileHandle *aHandle, char *aBuf, 1.200 + nsresult aResult) = 0; 1.201 + NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult) = 0; 1.202 + NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult) = 0; 1.203 + NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult) = 0; 1.204 +}; 1.205 + 1.206 +NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileIOListener, CACHEFILEIOLISTENER_IID) 1.207 + 1.208 + 1.209 +class CacheFileIOManager : public nsITimerCallback 1.210 +{ 1.211 +public: 1.212 + NS_DECL_THREADSAFE_ISUPPORTS 1.213 + NS_DECL_NSITIMERCALLBACK 1.214 + 1.215 + enum { 1.216 + OPEN = 0U, 1.217 + CREATE = 1U, 1.218 + CREATE_NEW = 2U, 1.219 + PRIORITY = 4U, 1.220 + SPECIAL_FILE = 8U 1.221 + }; 1.222 + 1.223 + CacheFileIOManager(); 1.224 + 1.225 + static nsresult Init(); 1.226 + static nsresult Shutdown(); 1.227 + static nsresult OnProfile(); 1.228 + static already_AddRefed<nsIEventTarget> IOTarget(); 1.229 + static already_AddRefed<CacheIOThread> IOThread(); 1.230 + static bool IsOnIOThread(); 1.231 + static bool IsOnIOThreadOrCeased(); 1.232 + static bool IsShutdown(); 1.233 + 1.234 + // Make aFile's WriteMetadataIfNeeded be called automatically after 1.235 + // a short interval. 1.236 + static nsresult ScheduleMetadataWrite(CacheFile * aFile); 1.237 + // Remove aFile from the scheduling registry array. 1.238 + // WriteMetadataIfNeeded will not be automatically called. 1.239 + static nsresult UnscheduleMetadataWrite(CacheFile * aFile); 1.240 + // Shuts the scheduling off and flushes all pending metadata writes. 1.241 + static nsresult ShutdownMetadataWriteScheduling(); 1.242 + 1.243 + static nsresult OpenFile(const nsACString &aKey, 1.244 + uint32_t aFlags, bool aResultOnAnyThread, 1.245 + CacheFileIOListener *aCallback); 1.246 + static nsresult Read(CacheFileHandle *aHandle, int64_t aOffset, 1.247 + char *aBuf, int32_t aCount, bool aResultOnAnyThread, 1.248 + CacheFileIOListener *aCallback); 1.249 + static nsresult Write(CacheFileHandle *aHandle, int64_t aOffset, 1.250 + const char *aBuf, int32_t aCount, bool aValidate, 1.251 + CacheFileIOListener *aCallback); 1.252 + static nsresult DoomFile(CacheFileHandle *aHandle, 1.253 + CacheFileIOListener *aCallback); 1.254 + static nsresult DoomFileByKey(const nsACString &aKey, 1.255 + CacheFileIOListener *aCallback); 1.256 + static nsresult ReleaseNSPRHandle(CacheFileHandle *aHandle); 1.257 + static nsresult TruncateSeekSetEOF(CacheFileHandle *aHandle, 1.258 + int64_t aTruncatePos, int64_t aEOFPos, 1.259 + CacheFileIOListener *aCallback); 1.260 + static nsresult RenameFile(CacheFileHandle *aHandle, 1.261 + const nsACString &aNewName, 1.262 + CacheFileIOListener *aCallback); 1.263 + static nsresult EvictIfOverLimit(); 1.264 + static nsresult EvictAll(); 1.265 + static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo); 1.266 + 1.267 + static nsresult InitIndexEntry(CacheFileHandle *aHandle, 1.268 + uint32_t aAppId, 1.269 + bool aAnonymous, 1.270 + bool aInBrowser); 1.271 + static nsresult UpdateIndexEntry(CacheFileHandle *aHandle, 1.272 + const uint32_t *aFrecency, 1.273 + const uint32_t *aExpirationTime); 1.274 + 1.275 + static nsresult UpdateIndexEntry(); 1.276 + 1.277 + enum EEnumerateMode { 1.278 + ENTRIES, 1.279 + DOOMED 1.280 + }; 1.281 + 1.282 + static void GetCacheDirectory(nsIFile** result); 1.283 + 1.284 + // Memory reporting 1.285 + static size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.286 + static size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf); 1.287 + 1.288 +private: 1.289 + friend class CacheFileHandle; 1.290 + friend class CacheFileChunk; 1.291 + friend class CacheFile; 1.292 + friend class ShutdownEvent; 1.293 + friend class OpenFileEvent; 1.294 + friend class CloseHandleEvent; 1.295 + friend class ReadEvent; 1.296 + friend class WriteEvent; 1.297 + friend class DoomFileEvent; 1.298 + friend class DoomFileByKeyEvent; 1.299 + friend class ReleaseNSPRHandleEvent; 1.300 + friend class TruncateSeekSetEOFEvent; 1.301 + friend class RenameFileEvent; 1.302 + friend class CacheIndex; 1.303 + friend class MetadataWriteScheduleEvent; 1.304 + friend class CacheFileContextEvictor; 1.305 + 1.306 + virtual ~CacheFileIOManager(); 1.307 + 1.308 + nsresult InitInternal(); 1.309 + nsresult ShutdownInternal(); 1.310 + 1.311 + nsresult OpenFileInternal(const SHA1Sum::Hash *aHash, 1.312 + const nsACString &aKey, 1.313 + uint32_t aFlags, 1.314 + CacheFileHandle **_retval); 1.315 + nsresult OpenSpecialFileInternal(const nsACString &aKey, 1.316 + uint32_t aFlags, 1.317 + CacheFileHandle **_retval); 1.318 + nsresult CloseHandleInternal(CacheFileHandle *aHandle); 1.319 + nsresult ReadInternal(CacheFileHandle *aHandle, int64_t aOffset, 1.320 + char *aBuf, int32_t aCount); 1.321 + nsresult WriteInternal(CacheFileHandle *aHandle, int64_t aOffset, 1.322 + const char *aBuf, int32_t aCount, bool aValidate); 1.323 + nsresult DoomFileInternal(CacheFileHandle *aHandle); 1.324 + nsresult DoomFileByKeyInternal(const SHA1Sum::Hash *aHash); 1.325 + nsresult ReleaseNSPRHandleInternal(CacheFileHandle *aHandle); 1.326 + nsresult TruncateSeekSetEOFInternal(CacheFileHandle *aHandle, 1.327 + int64_t aTruncatePos, int64_t aEOFPos); 1.328 + nsresult RenameFileInternal(CacheFileHandle *aHandle, 1.329 + const nsACString &aNewName); 1.330 + nsresult EvictIfOverLimitInternal(); 1.331 + nsresult OverLimitEvictionInternal(); 1.332 + nsresult EvictAllInternal(); 1.333 + nsresult EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo); 1.334 + 1.335 + nsresult TrashDirectory(nsIFile *aFile); 1.336 + static void OnTrashTimer(nsITimer *aTimer, void *aClosure); 1.337 + nsresult StartRemovingTrash(); 1.338 + nsresult RemoveTrashInternal(); 1.339 + nsresult FindTrashDirToRemove(); 1.340 + 1.341 + nsresult CreateFile(CacheFileHandle *aHandle); 1.342 + static void HashToStr(const SHA1Sum::Hash *aHash, nsACString &_retval); 1.343 + static nsresult StrToHash(const nsACString &aHash, SHA1Sum::Hash *_retval); 1.344 + nsresult GetFile(const SHA1Sum::Hash *aHash, nsIFile **_retval); 1.345 + nsresult GetSpecialFile(const nsACString &aKey, nsIFile **_retval); 1.346 + nsresult GetDoomedFile(nsIFile **_retval); 1.347 + nsresult IsEmptyDirectory(nsIFile *aFile, bool *_retval); 1.348 + nsresult CheckAndCreateDir(nsIFile *aFile, const char *aDir, 1.349 + bool aEnsureEmptyDir); 1.350 + nsresult CreateCacheTree(); 1.351 + nsresult OpenNSPRHandle(CacheFileHandle *aHandle, bool aCreate = false); 1.352 + void NSPRHandleUsed(CacheFileHandle *aHandle); 1.353 + 1.354 + // Removing all cache files during shutdown 1.355 + nsresult SyncRemoveDir(nsIFile *aFile, const char *aDir); 1.356 + void SyncRemoveAllCacheFiles(); 1.357 + 1.358 + nsresult ScheduleMetadataWriteInternal(CacheFile * aFile); 1.359 + nsresult UnscheduleMetadataWriteInternal(CacheFile * aFile); 1.360 + nsresult ShutdownMetadataWriteSchedulingInternal(); 1.361 + 1.362 + static nsresult CacheIndexStateChanged(); 1.363 + nsresult CacheIndexStateChangedInternal(); 1.364 + 1.365 + // Smart size calculation. UpdateSmartCacheSize() must be called on IO thread. 1.366 + // It is called in EvictIfOverLimitInternal() just before we decide whether to 1.367 + // start overlimit eviction or not and also in OverLimitEvictionInternal() 1.368 + // before we start an eviction loop. 1.369 + nsresult UpdateSmartCacheSize(); 1.370 + 1.371 + // Memory reporting (private part) 1.372 + size_t SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const; 1.373 + 1.374 + static CacheFileIOManager *gInstance; 1.375 + TimeStamp mStartTime; 1.376 + bool mShuttingDown; 1.377 + nsRefPtr<CacheIOThread> mIOThread; 1.378 + nsCOMPtr<nsIFile> mCacheDirectory; 1.379 + bool mTreeCreated; 1.380 + CacheFileHandles mHandles; 1.381 + nsTArray<CacheFileHandle *> mHandlesByLastUsed; 1.382 + nsTArray<CacheFileHandle *> mSpecialHandles; 1.383 + nsTArray<nsRefPtr<CacheFile> > mScheduledMetadataWrites; 1.384 + nsCOMPtr<nsITimer> mMetadataWritesTimer; 1.385 + bool mOverLimitEvicting; 1.386 + bool mRemovingTrashDirs; 1.387 + nsCOMPtr<nsITimer> mTrashTimer; 1.388 + nsCOMPtr<nsIFile> mTrashDir; 1.389 + nsCOMPtr<nsIDirectoryEnumerator> mTrashDirEnumerator; 1.390 + nsTArray<nsCString> mFailedTrashDirs; 1.391 + nsRefPtr<CacheFileContextEvictor> mContextEvictor; 1.392 + TimeStamp mLastSmartSizeTime; 1.393 +}; 1.394 + 1.395 +} // net 1.396 +} // mozilla 1.397 + 1.398 +#endif