Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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 CacheStorageService__h__
6 #define CacheStorageService__h__
8 #include "nsICacheStorageService.h"
9 #include "nsIMemoryReporter.h"
11 #include "nsITimer.h"
12 #include "nsClassHashtable.h"
13 #include "nsString.h"
14 #include "nsThreadUtils.h"
15 #include "nsProxyRelease.h"
16 #include "mozilla/Mutex.h"
17 #include "mozilla/Atomics.h"
18 #include "nsTArray.h"
20 class nsIURI;
21 class nsICacheEntryOpenCallback;
22 class nsICacheEntryDoomCallback;
23 class nsICacheStorageVisitor;
24 class nsIRunnable;
25 class nsIThread;
26 class nsIEventTarget;
28 namespace mozilla {
29 namespace net {
31 class CacheStorageService;
32 class CacheStorage;
33 class CacheEntry;
34 class CacheEntryHandle;
35 class CacheEntryTable;
37 class CacheMemoryConsumer
38 {
39 private:
40 friend class CacheStorageService;
41 uint32_t mReportedMemoryConsumption : 30;
42 uint32_t mFlags : 2;
44 private:
45 CacheMemoryConsumer() MOZ_DELETE;
47 protected:
48 enum {
49 // No special treatment, reports always to the disk-entries pool.
50 NORMAL = 0,
51 // This consumer is belonging to a memory-only cache entry, used to decide
52 // which of the two disk and memory pools count this consumption at.
53 MEMORY_ONLY = 1 << 0,
54 // Prevent reports of this consumer at all, used for disk data chunks since
55 // we throw them away as soon as the entry is not used by any consumer and
56 // don't want to make them wipe the whole pool out during their short life.
57 DONT_REPORT = 1 << 1
58 };
60 CacheMemoryConsumer(uint32_t aFlags);
61 ~CacheMemoryConsumer() { DoMemoryReport(0); }
62 void DoMemoryReport(uint32_t aCurrentSize);
63 };
65 class CacheStorageService : public nsICacheStorageService
66 , public nsIMemoryReporter
67 , public nsITimerCallback
68 {
69 public:
70 NS_DECL_THREADSAFE_ISUPPORTS
71 NS_DECL_NSICACHESTORAGESERVICE
72 NS_DECL_NSIMEMORYREPORTER
73 NS_DECL_NSITIMERCALLBACK
75 CacheStorageService();
77 void Shutdown();
78 void DropPrivateBrowsingEntries();
80 // Wipes out the new or the old cache directory completely.
81 static void WipeCacheDirectory(uint32_t aVersion);
83 static CacheStorageService* Self() { return sSelf; }
84 static nsISupports* SelfISupports() { return static_cast<nsICacheStorageService*>(Self()); }
85 nsresult Dispatch(nsIRunnable* aEvent);
86 static bool IsRunning() { return sSelf && !sSelf->mShutdown; }
87 static bool IsOnManagementThread();
88 already_AddRefed<nsIEventTarget> Thread() const;
89 mozilla::Mutex& Lock() { return mLock; }
91 // Memory reporting
92 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
93 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
94 MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
96 private:
97 virtual ~CacheStorageService();
98 void ShutdownBackground();
100 private:
101 // The following methods may only be called on the management
102 // thread.
103 friend class CacheEntry;
105 /**
106 * Registers the entry in management ordered arrays, a mechanism
107 * helping with weighted purge of entries.
108 * Management arrays keep hard reference to the entry. Entry is
109 * responsible to remove it self or the service is responsible to
110 * remove the entry when it's no longer needed.
111 */
112 void RegisterEntry(CacheEntry* aEntry);
114 /**
115 * Deregisters the entry from management arrays. References are
116 * then released.
117 */
118 void UnregisterEntry(CacheEntry* aEntry);
120 /**
121 * Removes the entry from the related entry hash table, if still present.
122 */
123 bool RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced = false);
125 /**
126 * Tells the storage service whether this entry is only to be stored in
127 * memory.
128 */
129 void RecordMemoryOnlyEntry(CacheEntry* aEntry,
130 bool aOnlyInMemory,
131 bool aOverwrite);
133 private:
134 // Following methods are thread safe to call.
135 friend class CacheStorage;
137 /**
138 * Get, or create when not existing and demanded, an entry for the storage
139 * and uri+id extension.
140 */
141 nsresult AddStorageEntry(CacheStorage const* aStorage,
142 nsIURI* aURI,
143 const nsACString & aIdExtension,
144 bool aCreateIfNotExist,
145 bool aReplace,
146 CacheEntryHandle** aResult);
148 /**
149 * Removes the entry from the related entry hash table, if still present
150 * and returns it.
151 */
152 nsresult DoomStorageEntry(CacheStorage const* aStorage,
153 nsIURI* aURI,
154 const nsACString & aIdExtension,
155 nsICacheEntryDoomCallback* aCallback);
157 /**
158 * Removes and returns entry table for the storage.
159 */
160 nsresult DoomStorageEntries(CacheStorage const* aStorage,
161 nsICacheEntryDoomCallback* aCallback);
163 /**
164 * Walk all entiries beloging to the storage.
165 */
166 nsresult WalkStorageEntries(CacheStorage const* aStorage,
167 bool aVisitEntries,
168 nsICacheStorageVisitor* aVisitor);
170 private:
171 friend class CacheFileIOManager;
173 /**
174 * CacheFileIOManager uses this method to notify CacheStorageService that
175 * an active entry was removed. This method is called even if the entry
176 * removal was originated by CacheStorageService.
177 */
178 void CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
179 const nsACString & aIdExtension,
180 const nsACString & aURISpec);
182 private:
183 friend class CacheMemoryConsumer;
185 /**
186 * When memory consumption of this entry radically changes, this method
187 * is called to reflect the size of allocated memory. This call may purge
188 * unspecified number of entries from memory (but not from disk).
189 */
190 void OnMemoryConsumptionChange(CacheMemoryConsumer* aConsumer,
191 uint32_t aCurrentMemoryConsumption);
193 /**
194 * If not already pending, it schedules mPurgeTimer that fires after 1 second
195 * and dispatches PurgeOverMemoryLimit().
196 */
197 void SchedulePurgeOverMemoryLimit();
199 /**
200 * Called on the management thread, removes all expired and then least used
201 * entries from the memory, first from the disk pool and then from the memory
202 * pool.
203 */
204 void PurgeOverMemoryLimit();
206 private:
207 nsresult DoomStorageEntries(nsCSubstring const& aContextKey,
208 nsILoadContextInfo* aContext,
209 bool aDiskStorage,
210 nsICacheEntryDoomCallback* aCallback);
211 nsresult AddStorageEntry(nsCSubstring const& aContextKey,
212 nsIURI* aURI,
213 const nsACString & aIdExtension,
214 bool aWriteToDisk,
215 bool aCreateIfNotExist,
216 bool aReplace,
217 CacheEntryHandle** aResult);
219 static CacheStorageService* sSelf;
221 mozilla::Mutex mLock;
223 bool mShutdown;
225 // Accessible only on the service thread
226 class MemoryPool
227 {
228 public:
229 enum EType
230 {
231 DISK,
232 MEMORY,
233 } mType;
235 MemoryPool(EType aType);
236 ~MemoryPool();
238 nsTArray<nsRefPtr<CacheEntry> > mFrecencyArray;
239 nsTArray<nsRefPtr<CacheEntry> > mExpirationArray;
240 mozilla::Atomic<uint32_t> mMemorySize;
242 bool OnMemoryConsumptionChange(uint32_t aSavedMemorySize,
243 uint32_t aCurrentMemoryConsumption);
244 /**
245 * Purges entries from memory based on the frecency ordered array.
246 */
247 void PurgeOverMemoryLimit();
248 void PurgeExpired();
249 void PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat);
250 void PurgeAll(uint32_t aWhat);
252 private:
253 uint32_t const Limit() const;
254 MemoryPool() MOZ_DELETE;
255 };
257 MemoryPool mDiskPool;
258 MemoryPool mMemoryPool;
259 MemoryPool& Pool(bool aUsingDisk)
260 {
261 return aUsingDisk ? mDiskPool : mMemoryPool;
262 }
263 MemoryPool const& Pool(bool aUsingDisk) const
264 {
265 return aUsingDisk ? mDiskPool : mMemoryPool;
266 }
268 nsCOMPtr<nsITimer> mPurgeTimer;
270 class PurgeFromMemoryRunnable : public nsRunnable
271 {
272 public:
273 PurgeFromMemoryRunnable(CacheStorageService* aService, uint32_t aWhat)
274 : mService(aService), mWhat(aWhat) { }
276 private:
277 virtual ~PurgeFromMemoryRunnable() { }
279 NS_IMETHOD Run()
280 {
281 // TODO not all flags apply to both pools
282 mService->Pool(true).PurgeAll(mWhat);
283 mService->Pool(false).PurgeAll(mWhat);
284 return NS_OK;
285 }
287 nsRefPtr<CacheStorageService> mService;
288 uint32_t mWhat;
289 };
290 };
292 template<class T>
293 void ProxyRelease(nsCOMPtr<T> &object, nsIThread* thread)
294 {
295 T* release;
296 object.forget(&release);
298 NS_ProxyRelease(thread, release);
299 }
301 template<class T>
302 void ProxyReleaseMainThread(nsCOMPtr<T> &object)
303 {
304 nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
305 ProxyRelease(object, mainThread);
306 }
308 } // net
309 } // mozilla
311 #define NS_CACHE_STORAGE_SERVICE_CID \
312 { 0xea70b098, 0x5014, 0x4e21, \
313 { 0xae, 0xe1, 0x75, 0xe6, 0xb2, 0xc4, 0xb8, 0xe0 } } \
315 #define NS_CACHE_STORAGE_SERVICE_CONTRACTID \
316 "@mozilla.org/netwerk/cache-storage-service;1"
318 #endif