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 CacheFileChunk__h__
6 #define CacheFileChunk__h__
8 #include "CacheFileIOManager.h"
9 #include "CacheStorageService.h"
10 #include "CacheHashUtils.h"
11 #include "CacheFileUtils.h"
12 #include "mozilla/Mutex.h"
13 #include "mozilla/UniquePtr.h"
18 constexpr int32_t kChunkSize
= 256 * 1024;
19 constexpr size_t kEmptyChunkHash
= 0x1826;
24 class CacheFileChunkBuffer
{
26 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheFileChunkBuffer
)
28 explicit CacheFileChunkBuffer(CacheFileChunk
* aChunk
);
30 nsresult
EnsureBufSize(uint32_t aBufSize
);
31 void CopyFrom(CacheFileChunkBuffer
* aOther
);
32 nsresult
FillInvalidRanges(CacheFileChunkBuffer
* aOther
,
33 CacheFileUtils::ValidityMap
* aMap
);
34 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
) const;
36 char* Buf() const { return mBuf
; }
37 void SetDataSize(uint32_t aDataSize
);
38 uint32_t DataSize() const { return mDataSize
; }
39 uint32_t ReadHandlesCount() const { return mReadHandlesCount
; }
40 bool WriteHandleExists() const { return mWriteHandleExists
; }
43 friend class CacheFileChunkHandle
;
44 friend class CacheFileChunkReadHandle
;
45 friend class CacheFileChunkWriteHandle
;
47 ~CacheFileChunkBuffer();
49 void AssertOwnsLock() const;
51 void RemoveReadHandle();
52 void RemoveWriteHandle();
54 // We keep a weak reference to the chunk to not create a reference cycle. The
55 // buffer is referenced only by chunk and handles. Handles are always
56 // destroyed before the chunk so it is guaranteed that mChunk is a valid
57 // pointer for the whole buffer's lifetime.
58 CacheFileChunk
* mChunk
;
62 uint32_t mReadHandlesCount
;
63 bool mWriteHandleExists
;
66 class CacheFileChunkHandle
{
72 RefPtr
<CacheFileChunkBuffer
> mBuf
;
75 class CacheFileChunkReadHandle
: public CacheFileChunkHandle
{
77 explicit CacheFileChunkReadHandle(CacheFileChunkBuffer
* aBuf
);
78 ~CacheFileChunkReadHandle();
83 class CacheFileChunkWriteHandle
: public CacheFileChunkHandle
{
85 explicit CacheFileChunkWriteHandle(CacheFileChunkBuffer
* aBuf
);
86 ~CacheFileChunkWriteHandle();
89 void UpdateDataSize(uint32_t aOffset
, uint32_t aLen
);
92 #define CACHEFILECHUNKLISTENER_IID \
93 { /* baf16149-2ab5-499c-a9c2-5904eb95c288 */ \
94 0xbaf16149, 0x2ab5, 0x499c, { \
95 0xa9, 0xc2, 0x59, 0x04, 0xeb, 0x95, 0xc2, 0x88 \
99 class CacheFileChunkListener
: public nsISupports
{
101 NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILECHUNKLISTENER_IID
)
103 NS_IMETHOD
OnChunkRead(nsresult aResult
, CacheFileChunk
* aChunk
) = 0;
104 NS_IMETHOD
OnChunkWritten(nsresult aResult
, CacheFileChunk
* aChunk
) = 0;
105 NS_IMETHOD
OnChunkAvailable(nsresult aResult
, uint32_t aChunkIdx
,
106 CacheFileChunk
* aChunk
) = 0;
107 NS_IMETHOD
OnChunkUpdated(CacheFileChunk
* aChunk
) = 0;
110 NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileChunkListener
,
111 CACHEFILECHUNKLISTENER_IID
)
113 class ChunkListenerItem
{
115 MOZ_COUNTED_DEFAULT_CTOR(ChunkListenerItem
)
116 MOZ_COUNTED_DTOR(ChunkListenerItem
)
118 nsCOMPtr
<nsIEventTarget
> mTarget
;
119 nsCOMPtr
<CacheFileChunkListener
> mCallback
;
122 class ChunkListeners
{
124 MOZ_COUNTED_DEFAULT_CTOR(ChunkListeners
)
125 MOZ_COUNTED_DTOR(ChunkListeners
)
127 nsTArray
<ChunkListenerItem
*> mItems
;
130 class CacheFileChunk final
: public CacheFileIOListener
,
131 public CacheMemoryConsumer
{
133 NS_DECL_THREADSAFE_ISUPPORTS
134 bool DispatchRelease();
136 CacheFileChunk(CacheFile
* aFile
, uint32_t aIndex
, bool aInitByWriter
);
139 nsresult
Read(CacheFileHandle
* aHandle
, uint32_t aLen
,
140 CacheHash::Hash16_t aHash
, CacheFileChunkListener
* aCallback
);
141 nsresult
Write(CacheFileHandle
* aHandle
, CacheFileChunkListener
* aCallback
);
142 void WaitForUpdate(CacheFileChunkListener
* aCallback
);
143 void CancelWait(CacheFileChunkListener
* aCallback
);
144 nsresult
NotifyUpdateListeners();
146 uint32_t Index() const;
147 CacheHash::Hash16_t
Hash() const;
148 uint32_t DataSize() const;
150 NS_IMETHOD
OnFileOpened(CacheFileHandle
* aHandle
, nsresult aResult
) override
;
151 NS_IMETHOD
OnDataWritten(CacheFileHandle
* aHandle
, const char* aBuf
,
152 nsresult aResult
) override
;
153 NS_IMETHOD
OnDataRead(CacheFileHandle
* aHandle
, char* aBuf
,
154 nsresult aResult
) override
;
155 NS_IMETHOD
OnFileDoomed(CacheFileHandle
* aHandle
, nsresult aResult
) override
;
156 NS_IMETHOD
OnEOFSet(CacheFileHandle
* aHandle
, nsresult aResult
) override
;
157 NS_IMETHOD
OnFileRenamed(CacheFileHandle
* aHandle
, nsresult aResult
) override
;
158 virtual bool IsKilled() override
;
160 bool IsReady() const;
161 bool IsDirty() const;
163 nsresult
GetStatus();
164 void SetError(nsresult aStatus
);
166 CacheFileChunkReadHandle
GetReadHandle();
167 CacheFileChunkWriteHandle
GetWriteHandle(uint32_t aEnsuredBufSize
);
170 size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf
) const;
171 size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf
) const;
174 friend class CacheFileChunkBuffer
;
175 friend class CacheFileChunkWriteHandle
;
176 friend class CacheFileInputStream
;
177 friend class CacheFileOutputStream
;
178 friend class CacheFile
;
180 virtual ~CacheFileChunk();
182 void AssertOwnsLock() const;
184 void UpdateDataSize(uint32_t aOffset
, uint32_t aLen
);
185 void Truncate(uint32_t aOffset
);
187 bool CanAllocate(uint32_t aSize
) const;
188 void BuffersAllocationChanged(uint32_t aFreed
, uint32_t aAllocated
);
190 mozilla::Atomic
<uint32_t, ReleaseAcquire
>& ChunksMemoryUsage() const;
192 enum EState
{ INITIAL
= 0, READING
= 1, WRITING
= 2, READY
= 3 };
198 Atomic
<bool> mActiveChunk
; // Is true iff the chunk is in CacheFile::mChunks.
199 // Adding/removing chunk to/from mChunks as well
200 // as changing this member happens under the
203 bool mDiscardedChunk
: 1;
205 uint32_t mBuffersSize
;
206 bool const mLimitAllocation
: 1; // Whether this chunk respects limit for
207 // disk chunks memory usage.
208 bool const mIsPriority
: 1;
210 // Buffer containing the chunk data. Multiple read handles can access the same
211 // buffer. When write handle is created and some read handle exists a new copy
212 // of the buffer is created. This prevents invalidating the buffer when
213 // CacheFileInputStream::ReadSegments calls the handler outside the lock.
214 RefPtr
<CacheFileChunkBuffer
> mBuf
;
216 // We need to keep pointers of the old buffers for memory reporting.
217 nsTArray
<RefPtr
<CacheFileChunkBuffer
>> mOldBufs
;
219 // Read handle that is used during writing the chunk to the disk.
220 UniquePtr
<CacheFileChunkReadHandle
> mWritingStateHandle
;
222 // Buffer that is used to read the chunk from the disk. It is allowed to write
223 // a new data to chunk while we wait for the data from the disk. In this case
224 // this buffer is merged with mBuf in OnDataRead().
225 RefPtr
<CacheFileChunkBuffer
> mReadingStateBuf
;
226 CacheHash::Hash16_t mExpectedHash
;
228 RefPtr
<CacheFile
> mFile
; // is null if chunk is cached to
229 // prevent reference cycles
230 nsCOMPtr
<CacheFileChunkListener
> mListener
;
231 nsTArray
<ChunkListenerItem
*> mUpdateListeners
;
232 CacheFileUtils::ValidityMap mValidityMap
;
236 } // namespace mozilla