tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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