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