/src/mozilla-central/netwerk/cache2/CacheFile.h
Line | Count | Source (jump to first uncovered line) |
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/. */ |
4 | | |
5 | | #ifndef CacheFile__h__ |
6 | | #define CacheFile__h__ |
7 | | |
8 | | #include "CacheFileChunk.h" |
9 | | #include "CacheFileIOManager.h" |
10 | | #include "CacheFileMetadata.h" |
11 | | #include "nsRefPtrHashtable.h" |
12 | | #include "nsClassHashtable.h" |
13 | | #include "mozilla/Mutex.h" |
14 | | |
15 | | class nsIInputStream; |
16 | | class nsIOutputStream; |
17 | | class nsICacheEntryMetaDataVisitor; |
18 | | |
19 | | namespace mozilla { |
20 | | namespace net { |
21 | | |
22 | | class CacheFileInputStream; |
23 | | class CacheFileOutputStream; |
24 | | class CacheOutputCloseListener; |
25 | | class MetadataWriteTimer; |
26 | | |
27 | | #define CACHEFILELISTENER_IID \ |
28 | | { /* 95e7f284-84ba-48f9-b1fc-3a7336b4c33c */ \ |
29 | | 0x95e7f284, \ |
30 | | 0x84ba, \ |
31 | | 0x48f9, \ |
32 | | {0xb1, 0xfc, 0x3a, 0x73, 0x36, 0xb4, 0xc3, 0x3c} \ |
33 | | } |
34 | | |
35 | | class CacheFileListener : public nsISupports |
36 | | { |
37 | | public: |
38 | | NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILELISTENER_IID) |
39 | | |
40 | | NS_IMETHOD OnFileReady(nsresult aResult, bool aIsNew) = 0; |
41 | | NS_IMETHOD OnFileDoomed(nsresult aResult) = 0; |
42 | | }; |
43 | | |
44 | | NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileListener, CACHEFILELISTENER_IID) |
45 | | |
46 | | |
47 | | class CacheFile final : public CacheFileChunkListener |
48 | | , public CacheFileIOListener |
49 | | , public CacheFileMetadataListener |
50 | | { |
51 | | public: |
52 | | NS_DECL_THREADSAFE_ISUPPORTS |
53 | | |
54 | | CacheFile(); |
55 | | |
56 | | nsresult Init(const nsACString &aKey, |
57 | | bool aCreateNew, |
58 | | bool aMemoryOnly, |
59 | | bool aSkipSizeCheck, |
60 | | bool aPriority, |
61 | | bool aPinned, |
62 | | CacheFileListener *aCallback); |
63 | | |
64 | | NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) override; |
65 | | NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk) override; |
66 | | NS_IMETHOD OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx, |
67 | | CacheFileChunk *aChunk) override; |
68 | | NS_IMETHOD OnChunkUpdated(CacheFileChunk *aChunk) override; |
69 | | |
70 | | NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult) override; |
71 | | NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf, |
72 | | nsresult aResult) override; |
73 | | NS_IMETHOD OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult) override; |
74 | | NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult) override; |
75 | | NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult) override; |
76 | | NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult) override; |
77 | | virtual bool IsKilled() override; |
78 | | |
79 | | NS_IMETHOD OnMetadataRead(nsresult aResult) override; |
80 | | NS_IMETHOD OnMetadataWritten(nsresult aResult) override; |
81 | | |
82 | | NS_IMETHOD OpenInputStream(nsICacheEntry *aCacheEntryHandle, nsIInputStream **_retval); |
83 | | NS_IMETHOD OpenAlternativeInputStream(nsICacheEntry *aCacheEntryHandle, |
84 | | const char *aAltDataType, nsIInputStream **_retval); |
85 | | NS_IMETHOD OpenOutputStream(CacheOutputCloseListener *aCloseListener, nsIOutputStream **_retval); |
86 | | NS_IMETHOD OpenAlternativeOutputStream(CacheOutputCloseListener *aCloseListener, |
87 | | const char *aAltDataType, nsIOutputStream **_retval); |
88 | | NS_IMETHOD SetMemoryOnly(); |
89 | | NS_IMETHOD Doom(CacheFileListener *aCallback); |
90 | | |
91 | 0 | void Kill() { mKill = true; } |
92 | | nsresult ThrowMemoryCachedData(); |
93 | | |
94 | | nsresult GetAltDataSize(int64_t *aSize); |
95 | | |
96 | | // metadata forwarders |
97 | | nsresult GetElement(const char *aKey, char **_retval); |
98 | | nsresult SetElement(const char *aKey, const char *aValue); |
99 | | nsresult VisitMetaData(nsICacheEntryMetaDataVisitor *aVisitor); |
100 | | nsresult ElementsSize(uint32_t *_retval); |
101 | | nsresult SetExpirationTime(uint32_t aExpirationTime); |
102 | | nsresult GetExpirationTime(uint32_t *_retval); |
103 | | nsresult SetFrecency(uint32_t aFrecency); |
104 | | nsresult GetFrecency(uint32_t *_retval); |
105 | | nsresult SetNetworkTimes(uint64_t aOnStartTime, uint64_t aOnStopTime); |
106 | | nsresult GetOnStartTime(uint64_t *_retval); |
107 | | nsresult GetOnStopTime(uint64_t *_retval); |
108 | | nsresult GetLastModified(uint32_t *_retval); |
109 | | nsresult GetLastFetched(uint32_t *_retval); |
110 | | nsresult GetFetchCount(uint32_t *_retval); |
111 | | nsresult GetDiskStorageSizeInKB(uint32_t *aDiskStorageSize); |
112 | | // Called by upper layers to indicated the entry has been fetched, |
113 | | // i.e. delivered to the consumer. |
114 | | nsresult OnFetched(); |
115 | | |
116 | | bool DataSize(int64_t* aSize); |
117 | 0 | void Key(nsACString& aKey) { aKey = mKey; } |
118 | | bool IsDoomed(); |
119 | 0 | bool IsPinned() const { return mPinned; } |
120 | | bool IsWriteInProgress(); |
121 | | bool EntryWouldExceedLimit(int64_t aOffset, int64_t aSize, bool aIsAltData); |
122 | | |
123 | | // Memory reporting |
124 | | size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; |
125 | | size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; |
126 | | |
127 | | private: |
128 | | friend class CacheFileIOManager; |
129 | | friend class CacheFileChunk; |
130 | | friend class CacheFileInputStream; |
131 | | friend class CacheFileOutputStream; |
132 | | friend class CacheFileAutoLock; |
133 | | friend class MetadataWriteTimer; |
134 | | |
135 | | virtual ~CacheFile(); |
136 | | |
137 | | void Lock(); |
138 | | void Unlock(); |
139 | | void AssertOwnsLock() const; |
140 | | void ReleaseOutsideLock(RefPtr<nsISupports> aObject); |
141 | | |
142 | | enum ECallerType { |
143 | | READER = 0, |
144 | | WRITER = 1, |
145 | | PRELOADER = 2 |
146 | | }; |
147 | | |
148 | | nsresult DoomLocked(CacheFileListener *aCallback); |
149 | | |
150 | | nsresult GetChunkLocked(uint32_t aIndex, ECallerType aCaller, |
151 | | CacheFileChunkListener *aCallback, |
152 | | CacheFileChunk **_retval); |
153 | | |
154 | | void PreloadChunks(uint32_t aIndex); |
155 | | bool ShouldCacheChunk(uint32_t aIndex); |
156 | | bool MustKeepCachedChunk(uint32_t aIndex); |
157 | | |
158 | | nsresult DeactivateChunk(CacheFileChunk *aChunk); |
159 | | void RemoveChunkInternal(CacheFileChunk *aChunk, bool aCacheChunk); |
160 | | |
161 | | bool OutputStreamExists(bool aAlternativeData); |
162 | | // Returns number of bytes that are available and can be read by input stream |
163 | | // without waiting for the data. The amount is counted from the start of |
164 | | // aIndex chunk and it is guaranteed that this data won't be released by |
165 | | // CleanUpCachedChunks(). |
166 | | int64_t BytesFromChunk(uint32_t aIndex, bool aAlternativeData); |
167 | | nsresult Truncate(int64_t aOffset); |
168 | | |
169 | | nsresult RemoveInput(CacheFileInputStream *aInput, nsresult aStatus); |
170 | | nsresult RemoveOutput(CacheFileOutputStream *aOutput, nsresult aStatus); |
171 | | nsresult NotifyChunkListener(CacheFileChunkListener *aCallback, |
172 | | nsIEventTarget *aTarget, |
173 | | nsresult aResult, |
174 | | uint32_t aChunkIdx, |
175 | | CacheFileChunk *aChunk); |
176 | | nsresult QueueChunkListener(uint32_t aIndex, |
177 | | CacheFileChunkListener *aCallback); |
178 | | nsresult NotifyChunkListeners(uint32_t aIndex, nsresult aResult, |
179 | | CacheFileChunk *aChunk); |
180 | | bool HaveChunkListeners(uint32_t aIndex); |
181 | | void NotifyListenersAboutOutputRemoval(); |
182 | | |
183 | | bool IsDirty(); |
184 | | void WriteMetadataIfNeeded(); |
185 | | void WriteMetadataIfNeededLocked(bool aFireAndForget = false); |
186 | | void PostWriteTimer(); |
187 | | |
188 | | void CleanUpCachedChunks(); |
189 | | |
190 | | nsresult PadChunkWithZeroes(uint32_t aChunkIdx); |
191 | | |
192 | | void SetError(nsresult aStatus); |
193 | | nsresult SetAltMetadata(const char* aAltMetadata); |
194 | | |
195 | | nsresult InitIndexEntry(); |
196 | | |
197 | | mozilla::Mutex mLock; |
198 | | bool mOpeningFile; |
199 | | bool mReady; |
200 | | bool mMemoryOnly; |
201 | | bool mSkipSizeCheck; |
202 | | bool mOpenAsMemoryOnly; |
203 | | bool mPinned; |
204 | | bool mPriority; |
205 | | bool mDataAccessed; |
206 | | bool mDataIsDirty; |
207 | | bool mWritingMetadata; |
208 | | bool mPreloadWithoutInputStreams; |
209 | | uint32_t mPreloadChunkCount; |
210 | | nsresult mStatus; |
211 | | int64_t mDataSize; // Size of the whole data including eventual |
212 | | // alternative data represenation. |
213 | | int64_t mAltDataOffset; // If there is alternative data present, it |
214 | | // contains size of the original data, i.e. |
215 | | // offset where alternative data starts. |
216 | | // Otherwise it is -1. |
217 | | nsCString mKey; |
218 | | |
219 | | RefPtr<CacheFileHandle> mHandle; |
220 | | RefPtr<CacheFileMetadata> mMetadata; |
221 | | nsCOMPtr<CacheFileListener> mListener; |
222 | | nsCOMPtr<CacheFileIOListener> mDoomAfterOpenListener; |
223 | | Atomic<bool, Relaxed> mKill; |
224 | | |
225 | | nsRefPtrHashtable<nsUint32HashKey, CacheFileChunk> mChunks; |
226 | | nsClassHashtable<nsUint32HashKey, ChunkListeners> mChunkListeners; |
227 | | nsRefPtrHashtable<nsUint32HashKey, CacheFileChunk> mCachedChunks; |
228 | | // We can truncate data only if there is no input/output stream beyond the |
229 | | // truncate position, so only unused chunks can be thrown away. But it can |
230 | | // happen that we need to throw away a chunk that is still in mChunks (i.e. |
231 | | // an active chunk) because deactivation happens with a small delay. We cannot |
232 | | // delete such chunk immediately but we need to ensure that such chunk won't |
233 | | // be returned by GetChunkLocked, so we move this chunk into mDiscardedChunks |
234 | | // and mark it as discarded. |
235 | | nsTArray<RefPtr<CacheFileChunk> > mDiscardedChunks; |
236 | | |
237 | | nsTArray<CacheFileInputStream*> mInputs; |
238 | | CacheFileOutputStream *mOutput; |
239 | | |
240 | | nsTArray<RefPtr<nsISupports>> mObjsToRelease; |
241 | | }; |
242 | | |
243 | | class CacheFileAutoLock { |
244 | | public: |
245 | | explicit CacheFileAutoLock(CacheFile *aFile) |
246 | | : mFile(aFile) |
247 | | , mLocked(true) |
248 | 0 | { |
249 | 0 | mFile->Lock(); |
250 | 0 | } |
251 | | ~CacheFileAutoLock() |
252 | 0 | { |
253 | 0 | if (mLocked) |
254 | 0 | mFile->Unlock(); |
255 | 0 | } |
256 | | void Lock() |
257 | 0 | { |
258 | 0 | MOZ_ASSERT(!mLocked); |
259 | 0 | mFile->Lock(); |
260 | 0 | mLocked = true; |
261 | 0 | } |
262 | | void Unlock() |
263 | 0 | { |
264 | 0 | MOZ_ASSERT(mLocked); |
265 | 0 | mFile->Unlock(); |
266 | 0 | mLocked = false; |
267 | 0 | } |
268 | | |
269 | | private: |
270 | | RefPtr<CacheFile> mFile; |
271 | | bool mLocked; |
272 | | }; |
273 | | |
274 | | } // namespace net |
275 | | } // namespace mozilla |
276 | | |
277 | | #endif |