summaryrefslogtreecommitdiffstats
path: root/netwerk/cache2/CacheFileChunk.h
diff options
context:
space:
mode:
Diffstat (limited to 'netwerk/cache2/CacheFileChunk.h')
-rw-r--r--netwerk/cache2/CacheFileChunk.h252
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