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