diff options
Diffstat (limited to 'netwerk/cache2/CacheFileChunk.h')
-rw-r--r-- | netwerk/cache2/CacheFileChunk.h | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/netwerk/cache2/CacheFileChunk.h b/netwerk/cache2/CacheFileChunk.h new file mode 100644 index 000000000..09acb62c5 --- /dev/null +++ b/netwerk/cache2/CacheFileChunk.h @@ -0,0 +1,252 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef CacheFileChunk__h__ +#define CacheFileChunk__h__ + +#include "CacheFileIOManager.h" +#include "CacheStorageService.h" +#include "CacheHashUtils.h" +#include "CacheFileUtils.h" +#include "nsAutoPtr.h" +#include "mozilla/Mutex.h" + +namespace mozilla { +namespace net { + +#define kChunkSize (256 * 1024) +#define kEmptyChunkHash 0x1826 + +class CacheFileChunk; +class CacheFile; + +class CacheFileChunkBuffer +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CacheFileChunkBuffer) + + explicit CacheFileChunkBuffer(CacheFileChunk *aChunk); + + nsresult EnsureBufSize(uint32_t aSize); + void CopyFrom(CacheFileChunkBuffer *aOther); + nsresult FillInvalidRanges(CacheFileChunkBuffer *aOther, + CacheFileUtils::ValidityMap *aMap); + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + + char * Buf() const { return mBuf; } + void SetDataSize(uint32_t aDataSize); + uint32_t DataSize() const { return mDataSize; } + uint32_t ReadHandlesCount() const { return mReadHandlesCount; } + bool WriteHandleExists() const { return mWriteHandleExists; } + +private: + friend class CacheFileChunkHandle; + friend class CacheFileChunkReadHandle; + friend class CacheFileChunkWriteHandle; + + ~CacheFileChunkBuffer(); + + void AssertOwnsLock() const; + + void RemoveReadHandle(); + void RemoveWriteHandle(); + + // We keep a weak reference to the chunk to not create a reference cycle. The + // buffer is referenced only by chunk and handles. Handles are always + // destroyed before the chunk so it is guaranteed that mChunk is a valid + // pointer for the whole buffer's lifetime. + CacheFileChunk *mChunk; + char *mBuf; + uint32_t mBufSize; + uint32_t mDataSize; + uint32_t mReadHandlesCount; + bool mWriteHandleExists; +}; + +class CacheFileChunkHandle +{ +public: + uint32_t DataSize(); + uint32_t Offset(); + +protected: + RefPtr<CacheFileChunkBuffer> mBuf; +}; + +class CacheFileChunkReadHandle : public CacheFileChunkHandle +{ +public: + explicit CacheFileChunkReadHandle(CacheFileChunkBuffer *aBuf); + ~CacheFileChunkReadHandle(); + + const char *Buf(); +}; + +class CacheFileChunkWriteHandle : public CacheFileChunkHandle +{ +public: + explicit CacheFileChunkWriteHandle(CacheFileChunkBuffer *aBuf); + ~CacheFileChunkWriteHandle(); + + char *Buf(); + void UpdateDataSize(uint32_t aOffset, uint32_t aLen); +}; + +#define CACHEFILECHUNKLISTENER_IID \ +{ /* baf16149-2ab5-499c-a9c2-5904eb95c288 */ \ + 0xbaf16149, \ + 0x2ab5, \ + 0x499c, \ + {0xa9, 0xc2, 0x59, 0x04, 0xeb, 0x95, 0xc2, 0x88} \ +} + +class CacheFileChunkListener : public nsISupports +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILECHUNKLISTENER_IID) + + NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk) = 0; + NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk) = 0; + NS_IMETHOD OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx, + CacheFileChunk *aChunk) = 0; + NS_IMETHOD OnChunkUpdated(CacheFileChunk *aChunk) = 0; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileChunkListener, + CACHEFILECHUNKLISTENER_IID) + + +class ChunkListenerItem { +public: + ChunkListenerItem() { MOZ_COUNT_CTOR(ChunkListenerItem); } + ~ChunkListenerItem() { MOZ_COUNT_DTOR(ChunkListenerItem); } + + nsCOMPtr<nsIEventTarget> mTarget; + nsCOMPtr<CacheFileChunkListener> mCallback; +}; + +class ChunkListeners { +public: + ChunkListeners() { MOZ_COUNT_CTOR(ChunkListeners); } + ~ChunkListeners() { MOZ_COUNT_DTOR(ChunkListeners); } + + nsTArray<ChunkListenerItem *> mItems; +}; + +class CacheFileChunk : public CacheFileIOListener + , public CacheMemoryConsumer +{ +public: + NS_DECL_THREADSAFE_ISUPPORTS + bool DispatchRelease(); + + CacheFileChunk(CacheFile *aFile, uint32_t aIndex, bool aInitByWriter); + + void InitNew(); + nsresult Read(CacheFileHandle *aHandle, uint32_t aLen, + CacheHash::Hash16_t aHash, + CacheFileChunkListener *aCallback); + nsresult Write(CacheFileHandle *aHandle, CacheFileChunkListener *aCallback); + void WaitForUpdate(CacheFileChunkListener *aCallback); + nsresult CancelWait(CacheFileChunkListener *aCallback); + nsresult NotifyUpdateListeners(); + + uint32_t Index() const; + CacheHash::Hash16_t Hash() const; + uint32_t DataSize() const; + + NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult) override; + NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf, + nsresult aResult) override; + NS_IMETHOD OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult) override; + NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult) override; + NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult) override; + NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult) override; + virtual bool IsKilled() override; + + bool IsReady() const; + bool IsDirty() const; + + nsresult GetStatus(); + void SetError(nsresult aStatus); + + CacheFileChunkReadHandle GetReadHandle(); + CacheFileChunkWriteHandle GetWriteHandle(uint32_t aEnsuredBufSize); + + // Memory reporting + size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; + +private: + friend class CacheFileChunkBuffer; + friend class CacheFileChunkWriteHandle; + friend class CacheFileInputStream; + friend class CacheFileOutputStream; + friend class CacheFile; + + virtual ~CacheFileChunk(); + + void AssertOwnsLock() const; + + void UpdateDataSize(uint32_t aOffset, uint32_t aLen); + nsresult Truncate(uint32_t aOffset); + + bool CanAllocate(uint32_t aSize) const; + void BuffersAllocationChanged(uint32_t aFreed, uint32_t aAllocated); + + mozilla::Atomic<uint32_t, ReleaseAcquire>& ChunksMemoryUsage() const; + + enum EState { + INITIAL = 0, + READING = 1, + WRITING = 2, + READY = 3 + }; + + uint32_t mIndex; + EState mState; + nsresult mStatus; + + Atomic<bool> mActiveChunk; // Is true iff the chunk is in CacheFile::mChunks. + // Adding/removing chunk to/from mChunks as well as + // changing this member happens under the + // CacheFile's lock. + bool mIsDirty : 1; + bool mDiscardedChunk : 1; + + uint32_t mBuffersSize; + bool const mLimitAllocation : 1; // Whether this chunk respects limit for disk + // chunks memory usage. + bool const mIsPriority : 1; + + // Buffer containing the chunk data. Multiple read handles can access the same + // buffer. When write handle is created and some read handle exists a new copy + // of the buffer is created. This prevents invalidating the buffer when + // CacheFileInputStream::ReadSegments calls the handler outside the lock. + RefPtr<CacheFileChunkBuffer> mBuf; + + // We need to keep pointers of the old buffers for memory reporting. + nsTArray<RefPtr<CacheFileChunkBuffer>> mOldBufs; + + // Read handle that is used during writing the chunk to the disk. + nsAutoPtr<CacheFileChunkReadHandle> mWritingStateHandle; + + // Buffer that is used to read the chunk from the disk. It is allowed to write + // a new data to chunk while we wait for the data from the disk. In this case + // this buffer is merged with mBuf in OnDataRead(). + RefPtr<CacheFileChunkBuffer> mReadingStateBuf; + CacheHash::Hash16_t mExpectedHash; + + RefPtr<CacheFile> mFile; // is null if chunk is cached to + // prevent reference cycles + nsCOMPtr<CacheFileChunkListener> mListener; + nsTArray<ChunkListenerItem *> mUpdateListeners; + CacheFileUtils::ValidityMap mValidityMap; +}; + + +} // namespace net +} // namespace mozilla + +#endif |