michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef CacheFile__h__ michael@0: #define CacheFile__h__ michael@0: michael@0: #include "CacheFileChunk.h" michael@0: #include "CacheFileIOManager.h" michael@0: #include "CacheFileMetadata.h" michael@0: #include "nsRefPtrHashtable.h" michael@0: #include "nsClassHashtable.h" michael@0: #include "mozilla/Mutex.h" michael@0: michael@0: class nsIInputStream; michael@0: class nsIOutputStream; michael@0: michael@0: namespace mozilla { michael@0: namespace net { michael@0: michael@0: class CacheFileInputStream; michael@0: class CacheFileOutputStream; michael@0: class CacheOutputCloseListener; michael@0: class MetadataWriteTimer; michael@0: michael@0: #define CACHEFILELISTENER_IID \ michael@0: { /* 95e7f284-84ba-48f9-b1fc-3a7336b4c33c */ \ michael@0: 0x95e7f284, \ michael@0: 0x84ba, \ michael@0: 0x48f9, \ michael@0: {0xb1, 0xfc, 0x3a, 0x73, 0x36, 0xb4, 0xc3, 0x3c} \ michael@0: } michael@0: michael@0: class CacheFileListener : public nsISupports michael@0: { michael@0: public: michael@0: NS_DECLARE_STATIC_IID_ACCESSOR(CACHEFILELISTENER_IID) michael@0: michael@0: NS_IMETHOD OnFileReady(nsresult aResult, bool aIsNew) = 0; michael@0: NS_IMETHOD OnFileDoomed(nsresult aResult) = 0; michael@0: }; michael@0: michael@0: NS_DEFINE_STATIC_IID_ACCESSOR(CacheFileListener, CACHEFILELISTENER_IID) michael@0: michael@0: michael@0: class CacheFile : public CacheFileChunkListener michael@0: , public CacheFileIOListener michael@0: , public CacheFileMetadataListener michael@0: { michael@0: public: michael@0: NS_DECL_THREADSAFE_ISUPPORTS michael@0: michael@0: CacheFile(); michael@0: michael@0: nsresult Init(const nsACString &aKey, michael@0: bool aCreateNew, michael@0: bool aMemoryOnly, michael@0: bool aPriority, michael@0: CacheFileListener *aCallback); michael@0: michael@0: NS_IMETHOD OnChunkRead(nsresult aResult, CacheFileChunk *aChunk); michael@0: NS_IMETHOD OnChunkWritten(nsresult aResult, CacheFileChunk *aChunk); michael@0: NS_IMETHOD OnChunkAvailable(nsresult aResult, uint32_t aChunkIdx, michael@0: CacheFileChunk *aChunk); michael@0: NS_IMETHOD OnChunkUpdated(CacheFileChunk *aChunk); michael@0: michael@0: NS_IMETHOD OnFileOpened(CacheFileHandle *aHandle, nsresult aResult); michael@0: NS_IMETHOD OnDataWritten(CacheFileHandle *aHandle, const char *aBuf, michael@0: nsresult aResult); michael@0: NS_IMETHOD OnDataRead(CacheFileHandle *aHandle, char *aBuf, nsresult aResult); michael@0: NS_IMETHOD OnFileDoomed(CacheFileHandle *aHandle, nsresult aResult); michael@0: NS_IMETHOD OnEOFSet(CacheFileHandle *aHandle, nsresult aResult); michael@0: NS_IMETHOD OnFileRenamed(CacheFileHandle *aHandle, nsresult aResult); michael@0: michael@0: NS_IMETHOD OnMetadataRead(nsresult aResult); michael@0: NS_IMETHOD OnMetadataWritten(nsresult aResult); michael@0: michael@0: NS_IMETHOD OpenInputStream(nsIInputStream **_retval); michael@0: NS_IMETHOD OpenOutputStream(CacheOutputCloseListener *aCloseListener, nsIOutputStream **_retval); michael@0: NS_IMETHOD SetMemoryOnly(); michael@0: NS_IMETHOD Doom(CacheFileListener *aCallback); michael@0: michael@0: nsresult ThrowMemoryCachedData(); michael@0: michael@0: // metadata forwarders michael@0: nsresult GetElement(const char *aKey, char **_retval); michael@0: nsresult SetElement(const char *aKey, const char *aValue); michael@0: nsresult ElementsSize(uint32_t *_retval); michael@0: nsresult SetExpirationTime(uint32_t aExpirationTime); michael@0: nsresult GetExpirationTime(uint32_t *_retval); michael@0: nsresult SetLastModified(uint32_t aLastModified); michael@0: nsresult GetLastModified(uint32_t *_retval); michael@0: nsresult SetFrecency(uint32_t aFrecency); michael@0: nsresult GetFrecency(uint32_t *_retval); michael@0: nsresult GetLastFetched(uint32_t *_retval); michael@0: nsresult GetFetchCount(uint32_t *_retval); michael@0: michael@0: bool DataSize(int64_t* aSize); michael@0: void Key(nsACString& aKey) { aKey = mKey; } michael@0: bool IsDoomed(); michael@0: bool IsWriteInProgress(); michael@0: michael@0: // Memory reporting michael@0: size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const; michael@0: size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const; michael@0: michael@0: private: michael@0: friend class CacheFileIOManager; michael@0: friend class CacheFileChunk; michael@0: friend class CacheFileInputStream; michael@0: friend class CacheFileOutputStream; michael@0: friend class CacheFileAutoLock; michael@0: friend class MetadataWriteTimer; michael@0: michael@0: virtual ~CacheFile(); michael@0: michael@0: void Lock(); michael@0: void Unlock(); michael@0: void AssertOwnsLock() const; michael@0: void ReleaseOutsideLock(nsISupports *aObject); michael@0: michael@0: nsresult GetChunk(uint32_t aIndex, bool aWriter, michael@0: CacheFileChunkListener *aCallback, michael@0: CacheFileChunk **_retval); michael@0: nsresult GetChunkLocked(uint32_t aIndex, bool aWriter, michael@0: CacheFileChunkListener *aCallback, michael@0: CacheFileChunk **_retval); michael@0: nsresult RemoveChunk(CacheFileChunk *aChunk); michael@0: void RemoveChunkInternal(CacheFileChunk *aChunk, bool aCacheChunk); michael@0: michael@0: nsresult RemoveInput(CacheFileInputStream *aInput); michael@0: nsresult RemoveOutput(CacheFileOutputStream *aOutput); michael@0: nsresult NotifyChunkListener(CacheFileChunkListener *aCallback, michael@0: nsIEventTarget *aTarget, michael@0: nsresult aResult, michael@0: uint32_t aChunkIdx, michael@0: CacheFileChunk *aChunk); michael@0: nsresult QueueChunkListener(uint32_t aIndex, michael@0: CacheFileChunkListener *aCallback); michael@0: nsresult NotifyChunkListeners(uint32_t aIndex, nsresult aResult, michael@0: CacheFileChunk *aChunk); michael@0: bool HaveChunkListeners(uint32_t aIndex); michael@0: void NotifyListenersAboutOutputRemoval(); michael@0: michael@0: bool IsDirty(); michael@0: void WriteMetadataIfNeeded(); michael@0: void WriteMetadataIfNeededLocked(bool aFireAndForget = false); michael@0: void PostWriteTimer(); michael@0: michael@0: static PLDHashOperator WriteAllCachedChunks(const uint32_t& aIdx, michael@0: nsRefPtr& aChunk, michael@0: void* aClosure); michael@0: michael@0: static PLDHashOperator FailListenersIfNonExistentChunk( michael@0: const uint32_t& aIdx, michael@0: nsAutoPtr& aListeners, michael@0: void* aClosure); michael@0: michael@0: static PLDHashOperator FailUpdateListeners(const uint32_t& aIdx, michael@0: nsRefPtr& aChunk, michael@0: void* aClosure); michael@0: michael@0: nsresult PadChunkWithZeroes(uint32_t aChunkIdx); michael@0: michael@0: void SetError(nsresult aStatus); michael@0: michael@0: nsresult InitIndexEntry(); michael@0: michael@0: mozilla::Mutex mLock; michael@0: bool mOpeningFile; michael@0: bool mReady; michael@0: bool mMemoryOnly; michael@0: bool mOpenAsMemoryOnly; michael@0: bool mDataAccessed; michael@0: bool mDataIsDirty; michael@0: bool mWritingMetadata; michael@0: nsresult mStatus; michael@0: int64_t mDataSize; michael@0: nsCString mKey; michael@0: michael@0: nsRefPtr mHandle; michael@0: nsRefPtr mMetadata; michael@0: nsCOMPtr mListener; michael@0: nsCOMPtr mDoomAfterOpenListener; michael@0: michael@0: nsRefPtrHashtable mChunks; michael@0: nsClassHashtable mChunkListeners; michael@0: nsRefPtrHashtable mCachedChunks; michael@0: michael@0: nsTArray mInputs; michael@0: CacheFileOutputStream *mOutput; michael@0: michael@0: nsTArray mObjsToRelease; michael@0: }; michael@0: michael@0: class CacheFileAutoLock { michael@0: public: michael@0: CacheFileAutoLock(CacheFile *aFile) michael@0: : mFile(aFile) michael@0: , mLocked(true) michael@0: { michael@0: mFile->Lock(); michael@0: } michael@0: ~CacheFileAutoLock() michael@0: { michael@0: if (mLocked) michael@0: mFile->Unlock(); michael@0: } michael@0: void Lock() michael@0: { michael@0: MOZ_ASSERT(!mLocked); michael@0: mFile->Lock(); michael@0: mLocked = true; michael@0: } michael@0: void Unlock() michael@0: { michael@0: MOZ_ASSERT(mLocked); michael@0: mFile->Unlock(); michael@0: mLocked = false; michael@0: } michael@0: michael@0: private: michael@0: nsRefPtr mFile; michael@0: bool mLocked; michael@0: }; michael@0: michael@0: } // net michael@0: } // mozilla michael@0: michael@0: #endif