Line data Source code
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 CacheFileChunk__h__
6 : #define CacheFileChunk__h__
7 :
8 : #include "CacheFileIOManager.h"
9 : #include "CacheStorageService.h"
10 : #include "CacheHashUtils.h"
11 : #include "CacheFileUtils.h"
12 : #include "nsAutoPtr.h"
13 : #include "mozilla/Mutex.h"
14 :
15 : namespace mozilla {
16 : namespace net {
17 :
18 : #define kChunkSize (256 * 1024)
19 : #define kEmptyChunkHash 0x1826
20 :
21 : class CacheFileChunk;
22 : class CacheFile;
23 :
24 : class CacheFileChunkBuffer
25 : {
26 : public:
27 54 : NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheFileChunkBuffer)
28 :
29 : explicit CacheFileChunkBuffer(CacheFileChunk *aChunk);
30 :
31 : nsresult EnsureBufSize(uint32_t aSize);
32 : void CopyFrom(CacheFileChunkBuffer *aOther);
33 : nsresult FillInvalidRanges(CacheFileChunkBuffer *aOther,
34 : CacheFileUtils::ValidityMap *aMap);
35 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
36 :
37 14 : char * Buf() const { return mBuf; }
38 : void SetDataSize(uint32_t aDataSize);
39 16 : uint32_t DataSize() const { return mDataSize; }
40 6 : uint32_t ReadHandlesCount() const { return mReadHandlesCount; }
41 17 : bool WriteHandleExists() const { return mWriteHandleExists; }
42 :
43 : private:
44 : friend class CacheFileChunkHandle;
45 : friend class CacheFileChunkReadHandle;
46 : friend class CacheFileChunkWriteHandle;
47 :
48 : ~CacheFileChunkBuffer();
49 :
50 : void AssertOwnsLock() const;
51 :
52 : void RemoveReadHandle();
53 : void RemoveWriteHandle();
54 :
55 : // We keep a weak reference to the chunk to not create a reference cycle. The
56 : // buffer is referenced only by chunk and handles. Handles are always
57 : // destroyed before the chunk so it is guaranteed that mChunk is a valid
58 : // pointer for the whole buffer's lifetime.
59 : CacheFileChunk *mChunk;
60 : char *mBuf;
61 : uint32_t mBufSize;
62 : uint32_t mDataSize;
63 : uint32_t mReadHandlesCount;
64 : bool mWriteHandleExists;
65 : };
66 :
67 30 : class CacheFileChunkHandle
68 : {
69 : public:
70 : uint32_t DataSize();
71 : uint32_t Offset();
72 :
73 : protected:
74 : RefPtr<CacheFileChunkBuffer> mBuf;
75 : };
76 :
77 : class CacheFileChunkReadHandle : public CacheFileChunkHandle
78 : {
79 : public:
80 : explicit CacheFileChunkReadHandle(CacheFileChunkBuffer *aBuf);
81 : ~CacheFileChunkReadHandle();
82 :
83 : const char *Buf();
84 : };
85 :
86 : class CacheFileChunkWriteHandle : public CacheFileChunkHandle
87 : {
88 : public:
89 : explicit CacheFileChunkWriteHandle(CacheFileChunkBuffer *aBuf);
90 : ~CacheFileChunkWriteHandle();
91 :
92 : char *Buf();
93 : void UpdateDataSize(uint32_t aOffset, uint32_t aLen);
94 : };
95 :
96 : #define CACHEFILECHUNKLISTENER_IID \
97 : { /* baf16149-2ab5-499c-a9c2-5904eb95c288 */ \
98 : 0xbaf16149, \
99 : 0x2ab5, \
100 : 0x499c, \
101 : {0xa9, 0xc2, 0x59, 0x04, 0xeb, 0x95, 0xc2, 0x88} \
102 : }
103 :
104 11 : class CacheFileChunkListener : public nsISupports
105 : {
106 : public:
107 : NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILECHUNKLISTENER_IID)
108 :
109 : NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) = 0;
110 : NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk) = 0;
111 : NS_IMETHOD OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx,
112 : CacheFileChunk *aChunk) = 0;
113 : NS_IMETHOD OnChunkUpdated(CacheFileChunk *aChunk) = 0;
114 : };
115 :
116 : NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileChunkListener,
117 : CACHEFILECHUNKLISTENER_IID)
118 :
119 :
120 : class ChunkListenerItem {
121 : public:
122 2 : ChunkListenerItem() { MOZ_COUNT_CTOR(ChunkListenerItem); }
123 2 : ~ChunkListenerItem() { MOZ_COUNT_DTOR(ChunkListenerItem); }
124 :
125 : nsCOMPtr<nsIEventTarget> mTarget;
126 : nsCOMPtr<CacheFileChunkListener> mCallback;
127 : };
128 :
129 : class ChunkListeners {
130 : public:
131 2 : ChunkListeners() { MOZ_COUNT_CTOR(ChunkListeners); }
132 2 : ~ChunkListeners() { MOZ_COUNT_DTOR(ChunkListeners); }
133 :
134 : nsTArray<ChunkListenerItem *> mItems;
135 : };
136 :
137 : class CacheFileChunk : public CacheFileIOListener
138 : , public CacheMemoryConsumer
139 : {
140 : public:
141 : NS_DECL_THREADSAFE_ISUPPORTS
142 : bool DispatchRelease();
143 :
144 : CacheFileChunk(CacheFile *aFile, uint32_t aIndex, bool aInitByWriter);
145 :
146 : void InitNew();
147 : nsresult Read(CacheFileHandle *aHandle, uint32_t aLen,
148 : CacheHash::Hash16_t aHash,
149 : CacheFileChunkListener *aCallback);
150 : nsresult Write(CacheFileHandle *aHandle, CacheFileChunkListener *aCallback);
151 : void WaitForUpdate(CacheFileChunkListener *aCallback);
152 : nsresult CancelWait(CacheFileChunkListener *aCallback);
153 : nsresult NotifyUpdateListeners();
154 :
155 : uint32_t Index() const;
156 : CacheHash::Hash16_t Hash() const;
157 : uint32_t DataSize() const;
158 :
159 : NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult) override;
160 : NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf,
161 : nsresult aResult) override;
162 : NS_IMETHOD OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult) override;
163 : NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult) override;
164 : NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult) override;
165 : NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult) override;
166 : virtual bool IsKilled() override;
167 :
168 : bool IsReady() const;
169 : bool IsDirty() const;
170 :
171 : nsresult GetStatus();
172 : void SetError(nsresult aStatus);
173 :
174 : CacheFileChunkReadHandle GetReadHandle();
175 : CacheFileChunkWriteHandle GetWriteHandle(uint32_t aEnsuredBufSize);
176 :
177 : // Memory reporting
178 : size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
179 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
180 :
181 : private:
182 : friend class CacheFileChunkBuffer;
183 : friend class CacheFileChunkWriteHandle;
184 : friend class CacheFileInputStream;
185 : friend class CacheFileOutputStream;
186 : friend class CacheFile;
187 :
188 : virtual ~CacheFileChunk();
189 :
190 : void AssertOwnsLock() const;
191 :
192 : void UpdateDataSize(uint32_t aOffset, uint32_t aLen);
193 : nsresult Truncate(uint32_t aOffset);
194 :
195 : bool CanAllocate(uint32_t aSize) const;
196 : void BuffersAllocationChanged(uint32_t aFreed, uint32_t aAllocated);
197 :
198 : mozilla::Atomic<uint32_t, ReleaseAcquire>& ChunksMemoryUsage() const;
199 :
200 : enum EState {
201 : INITIAL = 0,
202 : READING = 1,
203 : WRITING = 2,
204 : READY = 3
205 : };
206 :
207 : uint32_t mIndex;
208 : EState mState;
209 : nsresult mStatus;
210 :
211 : Atomic<bool> mActiveChunk; // Is true iff the chunk is in CacheFile::mChunks.
212 : // Adding/removing chunk to/from mChunks as well as
213 : // changing this member happens under the
214 : // CacheFile's lock.
215 : bool mIsDirty : 1;
216 : bool mDiscardedChunk : 1;
217 :
218 : uint32_t mBuffersSize;
219 : bool const mLimitAllocation : 1; // Whether this chunk respects limit for disk
220 : // chunks memory usage.
221 : bool const mIsPriority : 1;
222 :
223 : // Buffer containing the chunk data. Multiple read handles can access the same
224 : // buffer. When write handle is created and some read handle exists a new copy
225 : // of the buffer is created. This prevents invalidating the buffer when
226 : // CacheFileInputStream::ReadSegments calls the handler outside the lock.
227 : RefPtr<CacheFileChunkBuffer> mBuf;
228 :
229 : // We need to keep pointers of the old buffers for memory reporting.
230 : nsTArray<RefPtr<CacheFileChunkBuffer>> mOldBufs;
231 :
232 : // Read handle that is used during writing the chunk to the disk.
233 : nsAutoPtr<CacheFileChunkReadHandle> mWritingStateHandle;
234 :
235 : // Buffer that is used to read the chunk from the disk. It is allowed to write
236 : // a new data to chunk while we wait for the data from the disk. In this case
237 : // this buffer is merged with mBuf in OnDataRead().
238 : RefPtr<CacheFileChunkBuffer> mReadingStateBuf;
239 : CacheHash::Hash16_t mExpectedHash;
240 :
241 : RefPtr<CacheFile> mFile; // is null if chunk is cached to
242 : // prevent reference cycles
243 : nsCOMPtr<CacheFileChunkListener> mListener;
244 : nsTArray<ChunkListenerItem *> mUpdateListeners;
245 : CacheFileUtils::ValidityMap mValidityMap;
246 : };
247 :
248 :
249 : } // namespace net
250 : } // namespace mozilla
251 :
252 : #endif
|