michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * 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 _nsCacheEntry_h_ michael@0: #define _nsCacheEntry_h_ michael@0: michael@0: #include "nsICache.h" michael@0: #include "nsICacheEntryDescriptor.h" michael@0: #include "nsIThread.h" michael@0: #include "nsCacheMetaData.h" michael@0: michael@0: #include "nspr.h" michael@0: #include "pldhash.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nscore.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsString.h" michael@0: #include "nsAString.h" michael@0: michael@0: class nsCacheDevice; michael@0: class nsCacheMetaData; michael@0: class nsCacheRequest; michael@0: class nsCacheEntryDescriptor; michael@0: michael@0: /****************************************************************************** michael@0: * nsCacheEntry michael@0: *******************************************************************************/ michael@0: class nsCacheEntry : public PRCList michael@0: { michael@0: public: michael@0: michael@0: nsCacheEntry(const nsACString & key, michael@0: bool streamBased, michael@0: nsCacheStoragePolicy storagePolicy); michael@0: ~nsCacheEntry(); michael@0: michael@0: michael@0: static nsresult Create( const char * key, michael@0: bool streamBased, michael@0: nsCacheStoragePolicy storagePolicy, michael@0: nsCacheDevice * device, michael@0: nsCacheEntry ** result); michael@0: michael@0: nsCString * Key() { return &mKey; } michael@0: michael@0: int32_t FetchCount() { return mFetchCount; } michael@0: void SetFetchCount( int32_t count) { mFetchCount = count; } michael@0: void Fetched(); michael@0: michael@0: uint32_t LastFetched() { return mLastFetched; } michael@0: void SetLastFetched( uint32_t lastFetched) { mLastFetched = lastFetched; } michael@0: michael@0: uint32_t LastModified() { return mLastModified; } michael@0: void SetLastModified( uint32_t lastModified) { mLastModified = lastModified; } michael@0: michael@0: uint32_t ExpirationTime() { return mExpirationTime; } michael@0: void SetExpirationTime( uint32_t expires) { mExpirationTime = expires; } michael@0: michael@0: uint32_t Size() michael@0: { return mDataSize + mMetaData.Size() + mKey.Length() ; } michael@0: michael@0: nsCacheDevice * CacheDevice() { return mCacheDevice; } michael@0: void SetCacheDevice( nsCacheDevice * device) { mCacheDevice = device; } michael@0: void SetCustomCacheDevice( nsCacheDevice * device ) michael@0: { mCustomDevice = device; } michael@0: nsCacheDevice * CustomCacheDevice() { return mCustomDevice; } michael@0: const char * GetDeviceID(); michael@0: michael@0: /** michael@0: * Data accessors michael@0: */ michael@0: nsISupports *Data() { return mData; } michael@0: void SetData( nsISupports * data); michael@0: michael@0: int64_t PredictedDataSize() { return mPredictedDataSize; } michael@0: void SetPredictedDataSize(int64_t size) { mPredictedDataSize = size; } michael@0: michael@0: uint32_t DataSize() { return mDataSize; } michael@0: void SetDataSize( uint32_t size) { mDataSize = size; } michael@0: michael@0: void TouchData(); michael@0: michael@0: /** michael@0: * Meta data accessors michael@0: */ michael@0: const char * GetMetaDataElement( const char * key) { return mMetaData.GetElement(key); } michael@0: nsresult SetMetaDataElement( const char * key, michael@0: const char * value) { return mMetaData.SetElement(key, value); } michael@0: nsresult VisitMetaDataElements( nsICacheMetaDataVisitor * visitor) { return mMetaData.VisitElements(visitor); } michael@0: nsresult FlattenMetaData(char * buffer, uint32_t bufSize) { return mMetaData.FlattenMetaData(buffer, bufSize); } michael@0: nsresult UnflattenMetaData(const char * buffer, uint32_t bufSize) { return mMetaData.UnflattenMetaData(buffer, bufSize); } michael@0: uint32_t MetaDataSize() { return mMetaData.Size(); } michael@0: michael@0: void TouchMetaData(); michael@0: michael@0: michael@0: /** michael@0: * Security Info accessors michael@0: */ michael@0: nsISupports* SecurityInfo() { return mSecurityInfo; } michael@0: void SetSecurityInfo( nsISupports * info) { mSecurityInfo = info; } michael@0: michael@0: michael@0: // XXX enumerate MetaData method michael@0: michael@0: michael@0: enum CacheEntryFlags { michael@0: eStoragePolicyMask = 0x000000FF, michael@0: eDoomedMask = 0x00000100, michael@0: eEntryDirtyMask = 0x00000200, michael@0: eDataDirtyMask = 0x00000400, michael@0: eMetaDataDirtyMask = 0x00000800, michael@0: eStreamDataMask = 0x00001000, michael@0: eActiveMask = 0x00002000, michael@0: eInitializedMask = 0x00004000, michael@0: eValidMask = 0x00008000, michael@0: eBindingMask = 0x00010000, michael@0: ePrivateMask = 0x00020000 michael@0: }; michael@0: michael@0: void MarkBinding() { mFlags |= eBindingMask; } michael@0: void ClearBinding() { mFlags &= ~eBindingMask; } michael@0: bool IsBinding() { return (mFlags & eBindingMask) != 0; } michael@0: michael@0: void MarkEntryDirty() { mFlags |= eEntryDirtyMask; } michael@0: void MarkEntryClean() { mFlags &= ~eEntryDirtyMask; } michael@0: void MarkDataDirty() { mFlags |= eDataDirtyMask; } michael@0: void MarkDataClean() { mFlags &= ~eDataDirtyMask; } michael@0: void MarkMetaDataDirty() { mFlags |= eMetaDataDirtyMask; } michael@0: void MarkMetaDataClean() { mFlags &= ~eMetaDataDirtyMask; } michael@0: void MarkStreamData() { mFlags |= eStreamDataMask; } michael@0: void MarkValid() { mFlags |= eValidMask; } michael@0: void MarkInvalid() { mFlags &= ~eValidMask; } michael@0: void MarkPrivate() { mFlags |= ePrivateMask; } michael@0: void MarkPublic() { mFlags &= ~ePrivateMask; } michael@0: // void MarkAllowedInMemory() { mFlags |= eAllowedInMemoryMask; } michael@0: // void MarkAllowedOnDisk() { mFlags |= eAllowedOnDiskMask; } michael@0: michael@0: bool IsDoomed() { return (mFlags & eDoomedMask) != 0; } michael@0: bool IsEntryDirty() { return (mFlags & eEntryDirtyMask) != 0; } michael@0: bool IsDataDirty() { return (mFlags & eDataDirtyMask) != 0; } michael@0: bool IsMetaDataDirty() { return (mFlags & eMetaDataDirtyMask) != 0; } michael@0: bool IsStreamData() { return (mFlags & eStreamDataMask) != 0; } michael@0: bool IsActive() { return (mFlags & eActiveMask) != 0; } michael@0: bool IsInitialized() { return (mFlags & eInitializedMask) != 0; } michael@0: bool IsValid() { return (mFlags & eValidMask) != 0; } michael@0: bool IsInvalid() { return (mFlags & eValidMask) == 0; } michael@0: bool IsInUse() { return IsBinding() || michael@0: !(PR_CLIST_IS_EMPTY(&mRequestQ) && michael@0: PR_CLIST_IS_EMPTY(&mDescriptorQ)); } michael@0: bool IsNotInUse() { return !IsInUse(); } michael@0: bool IsPrivate() { return (mFlags & ePrivateMask) != 0; } michael@0: michael@0: michael@0: bool IsAllowedInMemory() michael@0: { michael@0: return (StoragePolicy() == nsICache::STORE_ANYWHERE) || michael@0: (StoragePolicy() == nsICache::STORE_IN_MEMORY); michael@0: } michael@0: michael@0: bool IsAllowedOnDisk() michael@0: { michael@0: return !IsPrivate() && ((StoragePolicy() == nsICache::STORE_ANYWHERE) || michael@0: (StoragePolicy() == nsICache::STORE_ON_DISK)); michael@0: } michael@0: michael@0: bool IsAllowedOffline() michael@0: { michael@0: return (StoragePolicy() == nsICache::STORE_OFFLINE); michael@0: } michael@0: michael@0: nsCacheStoragePolicy StoragePolicy() michael@0: { michael@0: return (nsCacheStoragePolicy)(mFlags & eStoragePolicyMask); michael@0: } michael@0: michael@0: void SetStoragePolicy(nsCacheStoragePolicy policy) michael@0: { michael@0: NS_ASSERTION(policy <= 0xFF, "too many bits in nsCacheStoragePolicy"); michael@0: mFlags &= ~eStoragePolicyMask; // clear storage policy bits michael@0: mFlags |= policy; michael@0: } michael@0: michael@0: michael@0: // methods for nsCacheService michael@0: nsresult RequestAccess( nsCacheRequest * request, nsCacheAccessMode *accessGranted); michael@0: nsresult CreateDescriptor( nsCacheRequest * request, michael@0: nsCacheAccessMode accessGranted, michael@0: nsICacheEntryDescriptor ** result); michael@0: michael@0: bool RemoveRequest( nsCacheRequest * request); michael@0: bool RemoveDescriptor( nsCacheEntryDescriptor * descriptor, michael@0: bool * doomEntry); michael@0: michael@0: void GetDescriptors(nsTArray > &outDescriptors); michael@0: michael@0: private: michael@0: friend class nsCacheEntryHashTable; michael@0: friend class nsCacheService; michael@0: michael@0: void DetachDescriptors(); michael@0: michael@0: // internal methods michael@0: void MarkDoomed() { mFlags |= eDoomedMask; } michael@0: void MarkStreamBased() { mFlags |= eStreamDataMask; } michael@0: void MarkInitialized() { mFlags |= eInitializedMask; } michael@0: void MarkActive() { mFlags |= eActiveMask; } michael@0: void MarkInactive() { mFlags &= ~eActiveMask; } michael@0: michael@0: nsCString mKey; michael@0: uint32_t mFetchCount; // 4 michael@0: uint32_t mLastFetched; // 4 michael@0: uint32_t mLastModified; // 4 michael@0: uint32_t mLastValidated; // 4 michael@0: uint32_t mExpirationTime; // 4 michael@0: uint32_t mFlags; // 4 michael@0: int64_t mPredictedDataSize; // Size given by ContentLength. michael@0: uint32_t mDataSize; // 4 michael@0: nsCacheDevice * mCacheDevice; // 4 michael@0: nsCacheDevice * mCustomDevice; // 4 michael@0: nsCOMPtr mSecurityInfo; // michael@0: nsISupports * mData; // strong ref michael@0: nsCOMPtr mThread; michael@0: nsCacheMetaData mMetaData; // 4 michael@0: PRCList mRequestQ; // 8 michael@0: PRCList mDescriptorQ; // 8 michael@0: }; michael@0: michael@0: michael@0: /****************************************************************************** michael@0: * nsCacheEntryInfo michael@0: *******************************************************************************/ michael@0: class nsCacheEntryInfo : public nsICacheEntryInfo { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: NS_DECL_NSICACHEENTRYINFO michael@0: michael@0: nsCacheEntryInfo(nsCacheEntry* entry) michael@0: : mCacheEntry(entry) michael@0: { michael@0: } michael@0: michael@0: virtual ~nsCacheEntryInfo() {} michael@0: void DetachEntry() { mCacheEntry = nullptr; } michael@0: michael@0: private: michael@0: nsCacheEntry * mCacheEntry; michael@0: }; michael@0: michael@0: michael@0: /****************************************************************************** michael@0: * nsCacheEntryHashTable michael@0: *******************************************************************************/ michael@0: typedef struct { michael@0: PLDHashNumber keyHash; michael@0: nsCacheEntry *cacheEntry; michael@0: } nsCacheEntryHashTableEntry; michael@0: michael@0: michael@0: class nsCacheEntryHashTable michael@0: { michael@0: public: michael@0: nsCacheEntryHashTable(); michael@0: ~nsCacheEntryHashTable(); michael@0: michael@0: nsresult Init(); michael@0: void Shutdown(); michael@0: michael@0: nsCacheEntry *GetEntry( const nsCString * key); michael@0: nsresult AddEntry( nsCacheEntry *entry); michael@0: void RemoveEntry( nsCacheEntry *entry); michael@0: michael@0: void VisitEntries( PLDHashEnumerator etor, void *arg); michael@0: michael@0: private: michael@0: // PLDHashTable operation callbacks michael@0: static PLDHashNumber HashKey( PLDHashTable *table, const void *key); michael@0: michael@0: static bool MatchEntry( PLDHashTable * table, michael@0: const PLDHashEntryHdr * entry, michael@0: const void * key); michael@0: michael@0: static void MoveEntry( PLDHashTable *table, michael@0: const PLDHashEntryHdr *from, michael@0: PLDHashEntryHdr *to); michael@0: michael@0: static void ClearEntry( PLDHashTable *table, PLDHashEntryHdr *entry); michael@0: michael@0: static void Finalize( PLDHashTable *table); michael@0: michael@0: static michael@0: PLDHashOperator FreeCacheEntries(PLDHashTable * table, michael@0: PLDHashEntryHdr * hdr, michael@0: uint32_t number, michael@0: void * arg); michael@0: static michael@0: PLDHashOperator VisitEntry(PLDHashTable * table, michael@0: PLDHashEntryHdr * hdr, michael@0: uint32_t number, michael@0: void * arg); michael@0: michael@0: // member variables michael@0: static const PLDHashTableOps ops; michael@0: PLDHashTable table; michael@0: bool initialized; michael@0: }; michael@0: michael@0: #endif // _nsCacheEntry_h_