Bumping manifests a=b2g-bump
[gecko.git] / netwerk / cache2 / CacheFileIOManager.h
blobd44048db221dfb57b73c6a812ff3342937da21e9
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 CacheFileIOManager__h__
6 #define CacheFileIOManager__h__
8 #include "CacheIOThread.h"
9 #include "CacheStorageService.h"
10 #include "nsIEventTarget.h"
11 #include "nsITimer.h"
12 #include "nsCOMPtr.h"
13 #include "mozilla/SHA1.h"
14 #include "mozilla/TimeStamp.h"
15 #include "nsTArray.h"
16 #include "nsString.h"
17 #include "nsTHashtable.h"
18 #include "prio.h"
20 //#define DEBUG_HANDLES 1
22 class nsIFile;
23 class nsITimer;
24 class nsIDirectoryEnumerator;
25 class nsILoadContextInfo;
26 class nsICacheStorageVisitor;
28 namespace mozilla {
29 namespace net {
31 class CacheFile;
32 #ifdef DEBUG_HANDLES
33 class CacheFileHandlesEntry;
34 #endif
36 const char kEntriesDir[] = "entries";
37 const char kDoomedDir[] = "doomed";
38 const char kTrashDir[] = "trash";
41 class CacheFileHandle : public nsISupports
43 public:
44 NS_DECL_THREADSAFE_ISUPPORTS
45 bool DispatchRelease();
47 CacheFileHandle(const SHA1Sum::Hash *aHash, bool aPriority);
48 CacheFileHandle(const nsACString &aKey, bool aPriority);
49 CacheFileHandle(const CacheFileHandle &aOther);
50 void Log();
51 bool IsDoomed() const { return mIsDoomed; }
52 const SHA1Sum::Hash *Hash() const { return mHash; }
53 int64_t FileSize() const { return mFileSize; }
54 uint32_t FileSizeInK() const;
55 bool IsPriority() const { return mPriority; }
56 bool FileExists() const { return mFileExists; }
57 bool IsClosed() const { return mClosed; }
58 bool IsSpecialFile() const { return mSpecialFile; }
59 nsCString & Key() { return mKey; }
61 // Memory reporting
62 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
63 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
65 private:
66 friend class CacheFileIOManager;
67 friend class CacheFileHandles;
68 friend class ReleaseNSPRHandleEvent;
70 virtual ~CacheFileHandle();
72 const SHA1Sum::Hash *mHash;
73 bool mIsDoomed;
74 bool mPriority;
75 bool mClosed;
76 bool mSpecialFile;
77 bool mInvalid;
78 bool mFileExists; // This means that the file should exists,
79 // but it can be still deleted by OS/user
80 // and then a subsequent OpenNSPRFileDesc()
81 // will fail.
82 nsCOMPtr<nsIFile> mFile;
83 int64_t mFileSize;
84 PRFileDesc *mFD; // if null then the file doesn't exists on the disk
85 nsCString mKey;
88 class CacheFileHandles {
89 public:
90 CacheFileHandles();
91 ~CacheFileHandles();
93 nsresult GetHandle(const SHA1Sum::Hash *aHash, bool aReturnDoomed, CacheFileHandle **_retval);
94 nsresult NewHandle(const SHA1Sum::Hash *aHash, bool aPriority, CacheFileHandle **_retval);
95 void RemoveHandle(CacheFileHandle *aHandlle);
96 void GetAllHandles(nsTArray<nsRefPtr<CacheFileHandle> > *_retval);
97 void GetActiveHandles(nsTArray<nsRefPtr<CacheFileHandle> > *_retval);
98 void ClearAll();
99 uint32_t HandleCount();
101 #ifdef DEBUG_HANDLES
102 void Log(CacheFileHandlesEntry *entry);
103 #endif
105 // Memory reporting
106 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
107 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
109 class HandleHashKey : public PLDHashEntryHdr
111 public:
112 typedef const SHA1Sum::Hash& KeyType;
113 typedef const SHA1Sum::Hash* KeyTypePointer;
115 explicit HandleHashKey(KeyTypePointer aKey)
117 MOZ_COUNT_CTOR(HandleHashKey);
118 mHash = (SHA1Sum::Hash*)new uint8_t[SHA1Sum::kHashSize];
119 memcpy(mHash, aKey, sizeof(SHA1Sum::Hash));
121 HandleHashKey(const HandleHashKey& aOther)
123 NS_NOTREACHED("HandleHashKey copy constructor is forbidden!");
125 ~HandleHashKey()
127 MOZ_COUNT_DTOR(HandleHashKey);
130 bool KeyEquals(KeyTypePointer aKey) const
132 return memcmp(mHash, aKey, sizeof(SHA1Sum::Hash)) == 0;
134 static KeyTypePointer KeyToPointer(KeyType aKey)
136 return &aKey;
138 static PLDHashNumber HashKey(KeyTypePointer aKey)
140 return (reinterpret_cast<const uint32_t *>(aKey))[0];
143 void AddHandle(CacheFileHandle* aHandle);
144 void RemoveHandle(CacheFileHandle* aHandle);
145 already_AddRefed<CacheFileHandle> GetNewestHandle();
146 void GetHandles(nsTArray<nsRefPtr<CacheFileHandle> > &aResult);
148 SHA1Sum::Hash *Hash() const { return mHash; }
149 bool IsEmpty() const { return mHandles.Length() == 0; }
151 enum { ALLOW_MEMMOVE = true };
153 #ifdef DEBUG
154 void AssertHandlesState();
155 #endif
157 // Memory reporting
158 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
159 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
161 private:
162 nsAutoArrayPtr<SHA1Sum::Hash> mHash;
163 // Use weak pointers since the hash table access is on a single thread
164 // only and CacheFileHandle removes itself from this table in its dtor
165 // that may only be called on the same thread as we work with the hashtable
166 // since we dispatch its Release() to this thread.
167 nsTArray<CacheFileHandle*> mHandles;
170 private:
171 nsTHashtable<HandleHashKey> mTable;
174 ////////////////////////////////////////////////////////////////////////////////
176 class OpenFileEvent;
177 class CloseFileEvent;
178 class ReadEvent;
179 class WriteEvent;
180 class MetadataWriteScheduleEvent;
181 class CacheFileContextEvictor;
183 #define CACHEFILEIOLISTENER_IID \
184 { /* dcaf2ddc-17cf-4242-bca1-8c86936375a5 */ \
185 0xdcaf2ddc, \
186 0x17cf, \
187 0x4242, \
188 {0xbc, 0xa1, 0x8c, 0x86, 0x93, 0x63, 0x75, 0xa5} \
191 class CacheFileIOListener : public nsISupports
193 public:
194 NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILEIOLISTENER_IID)
196 NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult) = 0;
197 NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf,
198 nsresult aResult) = 0;
199 NS_IMETHOD OnDataRead(CacheFileHandle *aHandle, char *aBuf,
200 nsresult aResult) = 0;
201 NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult) = 0;
202 NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult) = 0;
203 NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult) = 0;
206 NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileIOListener, CACHEFILEIOLISTENER_IID)
209 class CacheFileIOManager : public nsITimerCallback
211 public:
212 NS_DECL_THREADSAFE_ISUPPORTS
213 NS_DECL_NSITIMERCALLBACK
215 enum {
216 OPEN = 0U,
217 CREATE = 1U,
218 CREATE_NEW = 2U,
219 PRIORITY = 4U,
220 SPECIAL_FILE = 8U
223 CacheFileIOManager();
225 static nsresult Init();
226 static nsresult Shutdown();
227 static nsresult OnProfile();
228 static already_AddRefed<nsIEventTarget> IOTarget();
229 static already_AddRefed<CacheIOThread> IOThread();
230 static bool IsOnIOThread();
231 static bool IsOnIOThreadOrCeased();
232 static bool IsShutdown();
234 // Make aFile's WriteMetadataIfNeeded be called automatically after
235 // a short interval.
236 static nsresult ScheduleMetadataWrite(CacheFile * aFile);
237 // Remove aFile from the scheduling registry array.
238 // WriteMetadataIfNeeded will not be automatically called.
239 static nsresult UnscheduleMetadataWrite(CacheFile * aFile);
240 // Shuts the scheduling off and flushes all pending metadata writes.
241 static nsresult ShutdownMetadataWriteScheduling();
243 static nsresult OpenFile(const nsACString &aKey,
244 uint32_t aFlags, CacheFileIOListener *aCallback);
245 static nsresult Read(CacheFileHandle *aHandle, int64_t aOffset,
246 char *aBuf, int32_t aCount,
247 CacheFileIOListener *aCallback);
248 static nsresult Write(CacheFileHandle *aHandle, int64_t aOffset,
249 const char *aBuf, int32_t aCount, bool aValidate,
250 CacheFileIOListener *aCallback);
251 static nsresult DoomFile(CacheFileHandle *aHandle,
252 CacheFileIOListener *aCallback);
253 static nsresult DoomFileByKey(const nsACString &aKey,
254 CacheFileIOListener *aCallback);
255 static nsresult ReleaseNSPRHandle(CacheFileHandle *aHandle);
256 static nsresult TruncateSeekSetEOF(CacheFileHandle *aHandle,
257 int64_t aTruncatePos, int64_t aEOFPos,
258 CacheFileIOListener *aCallback);
259 static nsresult RenameFile(CacheFileHandle *aHandle,
260 const nsACString &aNewName,
261 CacheFileIOListener *aCallback);
262 static nsresult EvictIfOverLimit();
263 static nsresult EvictAll();
264 static nsresult EvictByContext(nsILoadContextInfo *aLoadContextInfo);
266 static nsresult InitIndexEntry(CacheFileHandle *aHandle,
267 uint32_t aAppId,
268 bool aAnonymous,
269 bool aInBrowser);
270 static nsresult UpdateIndexEntry(CacheFileHandle *aHandle,
271 const uint32_t *aFrecency,
272 const uint32_t *aExpirationTime);
274 static nsresult UpdateIndexEntry();
276 enum EEnumerateMode {
277 ENTRIES,
278 DOOMED
281 static void GetCacheDirectory(nsIFile** result);
282 #if defined(MOZ_WIDGET_ANDROID)
283 static void GetProfilelessCacheDirectory(nsIFile** result);
284 #endif
286 // Calls synchronously OnEntryInfo for an entry with the given hash.
287 // Tries to find an existing entry in the service hashtables first, if not
288 // found, loads synchronously from disk file.
289 // Callable on the IO thread only.
290 static nsresult GetEntryInfo(const SHA1Sum::Hash *aHash,
291 CacheStorageService::EntryInfoCallback *aCallback);
293 // Memory reporting
294 static size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
295 static size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
297 private:
298 friend class CacheFileHandle;
299 friend class CacheFileChunk;
300 friend class CacheFile;
301 friend class ShutdownEvent;
302 friend class OpenFileEvent;
303 friend class CloseHandleEvent;
304 friend class ReadEvent;
305 friend class WriteEvent;
306 friend class DoomFileEvent;
307 friend class DoomFileByKeyEvent;
308 friend class ReleaseNSPRHandleEvent;
309 friend class TruncateSeekSetEOFEvent;
310 friend class RenameFileEvent;
311 friend class CacheIndex;
312 friend class MetadataWriteScheduleEvent;
313 friend class CacheFileContextEvictor;
315 virtual ~CacheFileIOManager();
317 nsresult InitInternal();
318 nsresult ShutdownInternal();
320 nsresult OpenFileInternal(const SHA1Sum::Hash *aHash,
321 const nsACString &aKey,
322 uint32_t aFlags,
323 CacheFileHandle **_retval);
324 nsresult OpenSpecialFileInternal(const nsACString &aKey,
325 uint32_t aFlags,
326 CacheFileHandle **_retval);
327 nsresult CloseHandleInternal(CacheFileHandle *aHandle);
328 nsresult ReadInternal(CacheFileHandle *aHandle, int64_t aOffset,
329 char *aBuf, int32_t aCount);
330 nsresult WriteInternal(CacheFileHandle *aHandle, int64_t aOffset,
331 const char *aBuf, int32_t aCount, bool aValidate);
332 nsresult DoomFileInternal(CacheFileHandle *aHandle);
333 nsresult DoomFileByKeyInternal(const SHA1Sum::Hash *aHash,
334 bool aFailIfAlreadyDoomed);
335 nsresult ReleaseNSPRHandleInternal(CacheFileHandle *aHandle);
336 nsresult TruncateSeekSetEOFInternal(CacheFileHandle *aHandle,
337 int64_t aTruncatePos, int64_t aEOFPos);
338 nsresult RenameFileInternal(CacheFileHandle *aHandle,
339 const nsACString &aNewName);
340 nsresult EvictIfOverLimitInternal();
341 nsresult OverLimitEvictionInternal();
342 nsresult EvictAllInternal();
343 nsresult EvictByContextInternal(nsILoadContextInfo *aLoadContextInfo);
345 nsresult TrashDirectory(nsIFile *aFile);
346 static void OnTrashTimer(nsITimer *aTimer, void *aClosure);
347 nsresult StartRemovingTrash();
348 nsresult RemoveTrashInternal();
349 nsresult FindTrashDirToRemove();
351 nsresult CreateFile(CacheFileHandle *aHandle);
352 static void HashToStr(const SHA1Sum::Hash *aHash, nsACString &_retval);
353 static nsresult StrToHash(const nsACString &aHash, SHA1Sum::Hash *_retval);
354 nsresult GetFile(const SHA1Sum::Hash *aHash, nsIFile **_retval);
355 nsresult GetSpecialFile(const nsACString &aKey, nsIFile **_retval);
356 nsresult GetDoomedFile(nsIFile **_retval);
357 nsresult IsEmptyDirectory(nsIFile *aFile, bool *_retval);
358 nsresult CheckAndCreateDir(nsIFile *aFile, const char *aDir,
359 bool aEnsureEmptyDir);
360 nsresult CreateCacheTree();
361 nsresult OpenNSPRHandle(CacheFileHandle *aHandle, bool aCreate = false);
362 void NSPRHandleUsed(CacheFileHandle *aHandle);
364 // Removing all cache files during shutdown
365 nsresult SyncRemoveDir(nsIFile *aFile, const char *aDir);
366 void SyncRemoveAllCacheFiles();
368 nsresult ScheduleMetadataWriteInternal(CacheFile * aFile);
369 nsresult UnscheduleMetadataWriteInternal(CacheFile * aFile);
370 nsresult ShutdownMetadataWriteSchedulingInternal();
372 static nsresult CacheIndexStateChanged();
373 nsresult CacheIndexStateChangedInternal();
375 // Smart size calculation. UpdateSmartCacheSize() must be called on IO thread.
376 // It is called in EvictIfOverLimitInternal() just before we decide whether to
377 // start overlimit eviction or not and also in OverLimitEvictionInternal()
378 // before we start an eviction loop.
379 nsresult UpdateSmartCacheSize(int64_t aFreeSpace);
381 // Memory reporting (private part)
382 size_t SizeOfExcludingThisInternal(mozilla::MallocSizeOf mallocSizeOf) const;
384 static CacheFileIOManager *gInstance;
385 TimeStamp mStartTime;
386 bool mShuttingDown;
387 nsRefPtr<CacheIOThread> mIOThread;
388 nsCOMPtr<nsIFile> mCacheDirectory;
389 #if defined(MOZ_WIDGET_ANDROID)
390 // On Android we add the active profile directory name between the path
391 // and the 'cache2' leaf name. However, to delete any leftover data from
392 // times before we were doing it, we still need to access the directory
393 // w/o the profile name in the path. Here it is stored.
394 nsCOMPtr<nsIFile> mCacheProfilelessDirectory;
395 #endif
396 bool mTreeCreated;
397 CacheFileHandles mHandles;
398 nsTArray<CacheFileHandle *> mHandlesByLastUsed;
399 nsTArray<CacheFileHandle *> mSpecialHandles;
400 nsTArray<nsRefPtr<CacheFile> > mScheduledMetadataWrites;
401 nsCOMPtr<nsITimer> mMetadataWritesTimer;
402 bool mOverLimitEvicting;
403 bool mRemovingTrashDirs;
404 nsCOMPtr<nsITimer> mTrashTimer;
405 nsCOMPtr<nsIFile> mTrashDir;
406 nsCOMPtr<nsIDirectoryEnumerator> mTrashDirEnumerator;
407 nsTArray<nsCString> mFailedTrashDirs;
408 nsRefPtr<CacheFileContextEvictor> mContextEvictor;
409 TimeStamp mLastSmartSizeTime;
412 } // net
413 } // mozilla
415 #endif