diff --git a/mozilla/netwerk/cache/src/Makefile.in b/mozilla/netwerk/cache/src/Makefile.in index 28dee11ffab..63eaa4f2dea 100644 --- a/mozilla/netwerk/cache/src/Makefile.in +++ b/mozilla/netwerk/cache/src/Makefile.in @@ -37,6 +37,7 @@ EXPORTS = \ $(NULL) CPPSRCS = \ + nsANSIFileStreams.cpp \ nsCache.cpp \ nsCacheEntry.cpp \ nsCacheEntryDescriptor.cpp \ @@ -46,6 +47,7 @@ CPPSRCS = \ nsCacheSession.cpp \ nsDiskCacheDevice.cpp \ nsDiskCacheEntry.cpp \ + nsDiskCacheMap.cpp \ nsMemoryCacheDevice.cpp \ $(NULL) diff --git a/mozilla/netwerk/cache/src/makefile.win b/mozilla/netwerk/cache/src/makefile.win index b27bb415b6e..503fba6f40c 100755 --- a/mozilla/netwerk/cache/src/makefile.win +++ b/mozilla/netwerk/cache/src/makefile.win @@ -45,6 +45,8 @@ CPP_OBJS = \ .\$(OBJDIR)\nsCacheSession.obj \ .\$(OBJDIR)\nsDiskCacheDevice.obj \ .\$(OBJDIR)\nsDiskCacheEntry.obj \ + .\$(OBJDIR)\nsDiskCacheMap.obj \ + .\$(OBJDIR)\nsANSIFileStreams.obj \ .\$(OBJDIR)\nsMemoryCacheDevice.obj \ $(NULL) diff --git a/mozilla/netwerk/cache/src/nsANSIFileStreams.cpp b/mozilla/netwerk/cache/src/nsANSIFileStreams.cpp index e5494a7465b..c68c1313c37 100644 --- a/mozilla/netwerk/cache/src/nsANSIFileStreams.cpp +++ b/mozilla/netwerk/cache/src/nsANSIFileStreams.cpp @@ -23,11 +23,16 @@ #include "nsANSIFileStreams.h" -NS_IMPL_ISUPPORTS1(nsANSIInputStream, nsIInputStream); +NS_IMPL_ISUPPORTS2(nsANSIInputStream, nsIInputStream, nsISeekableStream); -nsANSIInputStream::nsANSIInputStream(FILE* file) : mFile(file) +nsANSIInputStream::nsANSIInputStream(FILE* file) : mFile(file), mSize(0) { NS_INIT_ISUPPORTS(); + if (file) { + ::fseek(file, 0, SEEK_END); + mSize = ::ftell(file); + ::fseek(file, 0, SEEK_SET); + } } nsANSIInputStream::~nsANSIInputStream() @@ -35,7 +40,6 @@ nsANSIInputStream::~nsANSIInputStream() Close(); } -/* void close (); */ NS_IMETHODIMP nsANSIInputStream::Close() { if (mFile) { @@ -46,13 +50,15 @@ NS_IMETHODIMP nsANSIInputStream::Close() return NS_BASE_STREAM_CLOSED; } -/* unsigned long available (); */ -NS_IMETHODIMP nsANSIInputStream::Available(PRUint32 *_retval) +NS_IMETHODIMP nsANSIInputStream::Available(PRUint32 * result) { - return NS_ERROR_NOT_IMPLEMENTED; + if (mFile) { + *result = (mSize - ::ftell(mFile)); + return NS_OK; + } + return NS_BASE_STREAM_CLOSED; } -/* [noscript] unsigned long read (in charPtr buf, in unsigned long count); */ NS_IMETHODIMP nsANSIInputStream::Read(char * buf, PRUint32 count, PRUint32 *result) { if (mFile) { @@ -62,30 +68,46 @@ NS_IMETHODIMP nsANSIInputStream::Read(char * buf, PRUint32 count, PRUint32 *resu return NS_BASE_STREAM_CLOSED; } -/* [noscript] unsigned long readSegments (in nsWriteSegmentFun writer, in voidPtr closure, in unsigned long count); */ NS_IMETHODIMP nsANSIInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval) { return NS_ERROR_NOT_IMPLEMENTED; } -/* readonly attribute boolean nonBlocking; */ NS_IMETHODIMP nsANSIInputStream::GetNonBlocking(PRBool *aNonBlocking) { *aNonBlocking = PR_FALSE; return NS_OK; } -/* attribute nsIInputStreamObserver observer; */ NS_IMETHODIMP nsANSIInputStream::GetObserver(nsIInputStreamObserver * *aObserver) { return NS_ERROR_NOT_IMPLEMENTED; } + NS_IMETHODIMP nsANSIInputStream::SetObserver(nsIInputStreamObserver * aObserver) { return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMPL_ISUPPORTS1(nsANSIOutputStream, nsIOutputStream); +NS_IMETHODIMP nsANSIInputStream::Seek(PRInt32 whence, PRInt32 offset) +{ + if (mFile) { + ::fseek(mFile, offset, whence); + return NS_OK; + } + return NS_BASE_STREAM_CLOSED; +} + +NS_IMETHODIMP nsANSIInputStream::Tell(PRUint32 * result) +{ + if (mFile) { + *result = ::ftell(mFile); + return NS_OK; + } + return NS_BASE_STREAM_CLOSED; +} + +NS_IMPL_ISUPPORTS2(nsANSIOutputStream, nsIOutputStream, nsISeekableStream); nsANSIOutputStream::nsANSIOutputStream(FILE* file) : mFile(file) { @@ -97,7 +119,6 @@ nsANSIOutputStream::~nsANSIOutputStream() Close(); } -/* void close (); */ NS_IMETHODIMP nsANSIOutputStream::Close() { if (mFile) { @@ -108,7 +129,6 @@ NS_IMETHODIMP nsANSIOutputStream::Close() return NS_BASE_STREAM_CLOSED; } -/* void flush (); */ NS_IMETHODIMP nsANSIOutputStream::Flush() { if (mFile) { @@ -118,7 +138,6 @@ NS_IMETHODIMP nsANSIOutputStream::Flush() return NS_BASE_STREAM_CLOSED; } -/* unsigned long write (in string buf, in unsigned long count); */ NS_IMETHODIMP nsANSIOutputStream::Write(const char *buffer, PRUint32 count, PRUint32 *result) { if (mFile) { @@ -128,7 +147,6 @@ NS_IMETHODIMP nsANSIOutputStream::Write(const char *buffer, PRUint32 count, PRUi return NS_BASE_STREAM_CLOSED; } -/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */ NS_IMETHODIMP nsANSIOutputStream::WriteFrom(nsIInputStream *input, PRUint32 count, PRUint32 *actualCount) { char buffer[BUFSIZ]; @@ -145,13 +163,11 @@ NS_IMETHODIMP nsANSIOutputStream::WriteFrom(nsIInputStream *input, PRUint32 coun return NS_OK; } -/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */ NS_IMETHODIMP nsANSIOutputStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval) { return NS_ERROR_NOT_IMPLEMENTED; } -/* attribute boolean nonBlocking; */ NS_IMETHODIMP nsANSIOutputStream::GetNonBlocking(PRBool *aNonBlocking) { *aNonBlocking = PR_FALSE; @@ -162,7 +178,6 @@ NS_IMETHODIMP nsANSIOutputStream::SetNonBlocking(PRBool aNonBlocking) return NS_ERROR_NOT_IMPLEMENTED; } -/* attribute nsIOutputStreamObserver observer; */ NS_IMETHODIMP nsANSIOutputStream::GetObserver(nsIOutputStreamObserver * *aObserver) { return NS_ERROR_NOT_IMPLEMENTED; @@ -171,3 +186,21 @@ NS_IMETHODIMP nsANSIOutputStream::SetObserver(nsIOutputStreamObserver * aObserve { return NS_ERROR_NOT_IMPLEMENTED; } + +NS_IMETHODIMP nsANSIOutputStream::Seek(PRInt32 whence, PRInt32 offset) +{ + if (mFile) { + ::fseek(mFile, offset, whence); + return NS_OK; + } + return NS_BASE_STREAM_CLOSED; +} + +NS_IMETHODIMP nsANSIOutputStream::Tell(PRUint32 * result) +{ + if (mFile) { + *result = ::ftell(mFile); + return NS_OK; + } + return NS_BASE_STREAM_CLOSED; +} diff --git a/mozilla/netwerk/cache/src/nsANSIFileStreams.h b/mozilla/netwerk/cache/src/nsANSIFileStreams.h index 9c6721cdc93..27069011df1 100644 --- a/mozilla/netwerk/cache/src/nsANSIFileStreams.h +++ b/mozilla/netwerk/cache/src/nsANSIFileStreams.h @@ -26,24 +26,26 @@ #include -#include "nsIInputStream.h" -#include "nsIOutputStream.h" +#include "nsIFileStreams.h" -class nsANSIInputStream : public nsIInputStream { - FILE* mFile; +class nsANSIInputStream : public nsIInputStream, public nsISeekableStream { + FILE* mFile; + PRUint32 mSize; public: NS_DECL_ISUPPORTS NS_DECL_NSIINPUTSTREAM + NS_DECL_NSISEEKABLESTREAM nsANSIInputStream(FILE* file); virtual ~nsANSIInputStream(); }; -class nsANSIOutputStream : public nsIOutputStream { +class nsANSIOutputStream : public nsIOutputStream, public nsISeekableStream { FILE* mFile; public: NS_DECL_ISUPPORTS NS_DECL_NSIOUTPUTSTREAM + NS_DECL_NSISEEKABLESTREAM nsANSIOutputStream(FILE* file); virtual ~nsANSIOutputStream(); diff --git a/mozilla/netwerk/cache/src/nsCacheDevice.h b/mozilla/netwerk/cache/src/nsCacheDevice.h index a54ce558f45..ab6ea981663 100644 --- a/mozilla/netwerk/cache/src/nsCacheDevice.h +++ b/mozilla/netwerk/cache/src/nsCacheDevice.h @@ -42,6 +42,7 @@ public: virtual ~nsCacheDevice() {} virtual nsresult Init() = 0; + virtual nsresult Shutdown() = 0; virtual const char * GetDeviceID(void) = 0; virtual nsCacheEntry * FindEntry( nsCString * key ) = 0; @@ -59,9 +60,13 @@ public: virtual nsresult OnDataSizeChange( nsCacheEntry * entry, PRInt32 deltaSize ) = 0; - // XXX need to define methods for enumerating entries - virtual nsresult Visit(nsICacheVisitor * visitor) = 0; + + /** + * Device must evict entries associated with clientID. If clientID == nsnull, all + * entries must be evicted. Active entries must be doomed, rather than evicted. + */ + virtual nsresult EvictEntries(const char * clientID) = 0; }; #endif // _nsCacheDevice_h_ diff --git a/mozilla/netwerk/cache/src/nsCacheEntry.cpp b/mozilla/netwerk/cache/src/nsCacheEntry.cpp index 961bd89654e..1010e0d2929 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntry.cpp +++ b/mozilla/netwerk/cache/src/nsCacheEntry.cpp @@ -36,8 +36,8 @@ nsCacheEntry::nsCacheEntry(nsCString * key, PRBool streamBased, nsCacheStoragePolicy storagePolicy) : mKey(key), - mFetchCount(1), - mLastValidated(0), + mFetchCount(0), + mLastFetched(0), mExpirationTime(0), mFlags(0), mDataSize(0), @@ -50,8 +50,6 @@ nsCacheEntry::nsCacheEntry(nsCString * key, PR_INIT_CLIST(&mRequestQ); PR_INIT_CLIST(&mDescriptorQ); - mLastFetched = SecondsFromPRTime(PR_Now()); - if (streamBased) MarkStreamBased(); SetStoragePolicy(storagePolicy); } @@ -65,51 +63,30 @@ nsCacheEntry::~nsCacheEntry() void -nsCacheEntry::SetDataSize( PRUint32 size) +nsCacheEntry::Fetched() { - mDataSize = size; - mLastModified = SecondsFromPRTime(PR_Now()); - MarkEntryDirty(); -} - - -nsresult -nsCacheEntry::GetSecurityInfo( nsISupports ** result) -{ - NS_ENSURE_ARG_POINTER(result); - NS_IF_ADDREF(*result = mSecurityInfo); - return NS_OK; -} - - -nsresult -nsCacheEntry::SetSecurityInfo( nsISupports * info) -{ - mSecurityInfo = info; - return NS_OK; + mLastFetched = SecondsFromPRTime(PR_Now()); + ++mFetchCount; } nsresult nsCacheEntry::GetData(nsISupports **result) { - if (!result) - return NS_ERROR_NULL_POINTER; - + NS_ENSURE_ARG_POINTER(result); NS_IF_ADDREF(*result = mData); return NS_OK; } - -nsresult -nsCacheEntry::SetData(nsISupports * data) +void +nsCacheEntry::TouchData() { mLastModified = SecondsFromPRTime(PR_Now()); - mData = data; - return NS_OK; + MarkDataDirty(); } + nsresult nsCacheEntry::GetMetaDataElement( const nsAReadableCString& key, nsAReadableCString ** value) @@ -133,28 +110,10 @@ nsCacheEntry::SetMetaDataElement( const nsAReadableCString& key, return rv; mMetaSize = mMetaData->Size(); // calc new meta data size - mLastModified = SecondsFromPRTime(PR_Now()); // time stamp the entry - MarkMetaDataDirty(); // mark it dirty return rv; } -#if 0 -nsresult -nsCacheEntry::GetKeyValueArray(nsCacheMetaDataKeyValuePair ** array, - PRUint32 * count) -{ - if (!array || !count) return NS_ERROR_NULL_POINTER; - - if (!mMetaData) { - *array = nsnull; - *count = 0; - return NS_OK; - } - return mMetaData->GetKeyValueArray(array, count); -} -#endif - nsresult nsCacheEntry::FlattenMetaData(char ** data, PRUint32 * size) { @@ -176,9 +135,46 @@ nsCacheEntry::UnflattenMetaData(char * data, PRUint32 size) mMetaData = nsCacheMetaData::Create(); if (!mMetaData) return NS_ERROR_OUT_OF_MEMORY; - return mMetaData->UnflattenMetaData(data, size); + nsresult rv = mMetaData->UnflattenMetaData(data, size); + if (NS_SUCCEEDED(rv)) + mMetaSize = mMetaData->Size(); + return rv; } + +void +nsCacheEntry::TouchMetaData() +{ + mLastModified = SecondsFromPRTime(PR_Now()); + MarkMetaDataDirty(); +} + +#if 0 +nsresult +nsCacheEntry::GetKeyValueArray(nsCacheMetaDataKeyValuePair ** array, + PRUint32 * count) +{ + if (!array || !count) return NS_ERROR_NULL_POINTER; + + if (!mMetaData) { + *array = nsnull; + *count = 0; + return NS_OK; + } + return mMetaData->GetKeyValueArray(array, count); +} +#endif + + +nsresult +nsCacheEntry::GetSecurityInfo( nsISupports ** result) +{ + NS_ENSURE_ARG_POINTER(result); + NS_IF_ADDREF(*result = mSecurityInfo); + return NS_OK; +} + + /** * cache entry states * 0 descriptors (new entry) @@ -360,17 +356,6 @@ nsCacheEntryInfo::GetLastModified(PRUint32 * lastModified) } -NS_IMETHODIMP -nsCacheEntryInfo::GetLastValidated(PRUint32 * lastValidated) -{ - NS_ENSURE_ARG_POINTER(lastValidated); - if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE; - - *lastValidated = mCacheEntry->LastValidated(); - return NS_OK; -} - - NS_IMETHODIMP nsCacheEntryInfo::GetExpirationTime(PRUint32 * expirationTime) { @@ -423,14 +408,15 @@ nsCacheEntryHashTable::ops = nsCacheEntryHashTable::nsCacheEntryHashTable() - : initialized(0) + : initialized(PR_FALSE) { } nsCacheEntryHashTable::~nsCacheEntryHashTable() { - PL_DHashTableFinish(&table); + if (initialized) + PL_DHashTableFinish(&table); } diff --git a/mozilla/netwerk/cache/src/nsCacheEntry.h b/mozilla/netwerk/cache/src/nsCacheEntry.h index 23fd703432d..831538ffc59 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntry.h +++ b/mozilla/netwerk/cache/src/nsCacheEntry.h @@ -53,46 +53,43 @@ public: nsCacheStoragePolicy storagePolicy); ~nsCacheEntry(); - nsCacheEntry * - Create(nsCString * key, - PRBool streamBased, - nsCacheStoragePolicy storagePolicy, - nsCacheDevice * cacheDevice); - nsCString * Key(void) { return mKey; } + nsCString * Key() { return mKey; } - PRInt32 FetchCount(void) { return mFetchCount;} + PRInt32 FetchCount() { return mFetchCount;} void SetFetchCount( PRInt32 count) { mFetchCount = count;} - void IncrementFetchCount(void) { ++mFetchCount; } + void Fetched(); - PRUint32 LastFetched(void) { return mLastFetched;} + PRUint32 LastFetched() { return mLastFetched;} void SetLastFetched( PRUint32 lastFetched) { mLastFetched = lastFetched;} - PRUint32 LastModified(void) { return mLastModified;} + PRUint32 LastModified() { return mLastModified;} void SetLastModified( PRUint32 lastModified) { mLastModified = lastModified;} - PRUint32 LastValidated(void) { return mLastValidated;} - void SetLastValidated( PRUint32 lastValidated) { mLastValidated = lastValidated;} - - PRUint32 ExpirationTime(void) { return mExpirationTime;} + PRUint32 ExpirationTime() { return mExpirationTime;} void SetExpirationTime( PRUint32 expires) { mExpirationTime = expires;} - PRUint32 DataSize(void) { return mDataSize;} - void SetDataSize( PRUint32 size); + PRUint32 Size() { return mDataSize + mMetaSize; } - PRUint32 MetaDataSize(void) { return mMetaSize;} - - PRUint32 Size(void) { return mDataSize + mMetaSize; } - - nsCacheDevice * CacheDevice(void) { return mCacheDevice;} + nsCacheDevice * CacheDevice() { return mCacheDevice;} void SetCacheDevice( nsCacheDevice * device) { mCacheDevice = device;} - nsresult GetSecurityInfo( nsISupports ** result); - nsresult SetSecurityInfo( nsISupports * info); + /** + * Data accessors + */ nsresult GetData( nsISupports ** result); - nsresult SetData( nsISupports * data); + void SetData( nsISupports * data) { mData = data; } + PRUint32 DataSize() { return mDataSize;} + void SetDataSize( PRUint32 size) { mDataSize = size;} + + void TouchData(); + + + /** + * Meta data accessors + */ nsresult GetMetaDataElement( const nsAReadableCString& key, nsAReadableCString ** value); nsresult SetMetaDataElement( const nsAReadableCString& key, @@ -101,6 +98,18 @@ public: nsresult FlattenMetaData(char ** data, PRUint32 * size); nsresult UnflattenMetaData(char * data, PRUint32 size); + PRUint32 MetaDataSize() { return mMetaSize;} + + void TouchMetaData(); + + + /** + * Security Info accessors + */ + nsresult GetSecurityInfo( nsISupports ** result); + void SetSecurityInfo( nsISupports * info) { mSecurityInfo = info; } + + // XXX enumerate MetaData method @@ -187,7 +196,6 @@ private: void DetachDescriptors(void); // internal methods - nsresult CommonOpen(nsCacheRequest * request, nsCacheAccessMode *accessGranted); void MarkDoomed() { mFlags |= eDoomedMask; } void MarkStreamBased() { mFlags |= eStreamDataMask; } void MarkInitialized() { mFlags |= eInitializedMask; } @@ -227,7 +235,7 @@ public: } virtual ~nsCacheEntryInfo() {} - void DetachEntry(void) { mCacheEntry = nsnull; } + void DetachEntry() { mCacheEntry = nsnull; } private: nsCacheEntry * mCacheEntry; diff --git a/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp b/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp index 3e45dbc0ad0..74d15e919fd 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp +++ b/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.cpp @@ -146,17 +146,6 @@ nsCacheEntryDescriptor::GetLastModified(PRUint32 *result) } -NS_IMETHODIMP -nsCacheEntryDescriptor::GetLastValidated(PRUint32 *result) -{ - NS_ENSURE_ARG_POINTER(result); - if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE; - - *result = mCacheEntry->LastValidated(); - return NS_OK; -} - - NS_IMETHODIMP nsCacheEntryDescriptor::GetExpirationTime(PRUint32 *result) { @@ -174,6 +163,7 @@ nsCacheEntryDescriptor::SetExpirationTime(PRUint32 expirationTime) if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE; mCacheEntry->SetExpirationTime(expirationTime); + mCacheEntry->MarkEntryDirty(); return NS_OK; } @@ -207,6 +197,7 @@ nsCacheEntryDescriptor::RequestDataSizeChange(PRInt32 deltaSize) // XXX review for signed/unsigned math errors PRUint32 newDataSize = mCacheEntry->DataSize() + deltaSize; mCacheEntry->SetDataSize(newDataSize); + mCacheEntry->TouchData(); } return rv; } @@ -256,7 +247,9 @@ nsCacheEntryDescriptor::SetCacheElement(nsISupports * cacheElement) if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE; if (mCacheEntry->IsStreamData()) return NS_ERROR_CACHE_DATA_IS_STREAM; - return mCacheEntry->SetData(cacheElement); + mCacheEntry->SetData(cacheElement); + mCacheEntry->TouchData(); + return NS_OK; } @@ -285,7 +278,7 @@ nsCacheEntryDescriptor::SetStoragePolicy(nsCacheStoragePolicy policy) if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE; // XXX validate policy against session? mCacheEntry->SetStoragePolicy(policy); - + mCacheEntry->MarkEntryDirty(); return NS_OK; } @@ -316,6 +309,7 @@ nsCacheEntryDescriptor::SetSecurityInfo(nsISupports * securityInfo) if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE; mCacheEntry->SetSecurityInfo(securityInfo); + mCacheEntry->MarkEntryDirty(); return NS_OK; } @@ -394,6 +388,8 @@ nsCacheEntryDescriptor::SetMetaDataElement(const char *key, const char *value) // XXX allow null value, for clearing key? nsresult rv = mCacheEntry->SetMetaDataElement(nsLiteralCString(key), nsLiteralCString(value)); + if (NS_SUCCEEDED(rv)) + mCacheEntry->TouchMetaData(); return rv; } diff --git a/mozilla/netwerk/cache/src/nsCacheMetaData.cpp b/mozilla/netwerk/cache/src/nsCacheMetaData.cpp index 0ef00e499ec..a11cd183c88 100644 --- a/mozilla/netwerk/cache/src/nsCacheMetaData.cpp +++ b/mozilla/netwerk/cache/src/nsCacheMetaData.cpp @@ -44,13 +44,14 @@ nsCacheMetaData::ops = nsCacheMetaData::nsCacheMetaData() - : initialized(0) + : initialized(PR_FALSE) { } nsCacheMetaData::~nsCacheMetaData() { - PL_DHashTableFinish(&table); + if (initialized) + PL_DHashTableFinish(&table); } diff --git a/mozilla/netwerk/cache/src/nsCacheService.cpp b/mozilla/netwerk/cache/src/nsCacheService.cpp index 8e0b9362d20..a1ed7c02ae0 100644 --- a/mozilla/netwerk/cache/src/nsCacheService.cpp +++ b/mozilla/netwerk/cache/src/nsCacheService.cpp @@ -37,16 +37,129 @@ #include "nsIEventQueue.h" #include "nsProxiedService.h" #include "nsIObserverService.h" +#include "nsIPref.h" static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); + + + +/****************************************************************************** + * nsCachePrefObserver + *****************************************************************************/ + +#define ENABLE_MEMORY_CACHE_PREF "browser.cache.enable" +#define ENABLE_DISK_CACHE_PREF "browser.cache.disk.enable" + +class nsCachePrefObserver : public nsIObserver +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIOBSERVER + + nsCachePrefObserver() : + mDiskCacheEnabled(PR_TRUE), + mMemoryCacheEnabled(PR_TRUE) + { + NS_INIT_ISUPPORTS(); + } + + virtual ~nsCachePrefObserver() {} + + nsresult Install(); + nsresult Remove(); + +private: + PRBool mDiskCacheEnabled; + PRBool mMemoryCacheEnabled; +}; + +NS_IMPL_ISUPPORTS1(nsCachePrefObserver, nsIObserver); + + +nsresult +nsCachePrefObserver::Install() +{ + nsresult rv, rv2; + nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = prefs->AddObserver(ENABLE_MEMORY_CACHE_PREF, this); + if (NS_FAILED(rv)) rv2 = rv; + + rv = prefs->AddObserver(ENABLE_DISK_CACHE_PREF, this); + if (NS_FAILED(rv)) rv2 = rv; + + rv = prefs->GetBoolPref(ENABLE_DISK_CACHE_PREF, &mDiskCacheEnabled); + if (NS_FAILED(rv)) rv2 = rv; + + rv = prefs->GetBoolPref(ENABLE_MEMORY_CACHE_PREF, &mMemoryCacheEnabled); + // if (NS_FAILED(rv)) rv2 = rv; + + if (NS_SUCCEEDED(rv)) rv = rv2; + return rv; +} + + +nsresult +nsCachePrefObserver::Remove() +{ + nsresult rv, rv2; + + nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = prefs->RemoveObserver(ENABLE_DISK_CACHE_PREF, this); + rv2 = prefs->RemoveObserver(ENABLE_MEMORY_CACHE_PREF, this); + + if (NS_SUCCEEDED(rv)) rv = rv2; + return rv; +} + + +NS_IMETHODIMP +nsCachePrefObserver::Observe(nsISupports * subject, + const PRUnichar * topic, + const PRUnichar * data) +{ + nsresult rv; + + if (NS_LITERAL_STRING("nsPref:changed").Equals(topic)) { + nsCOMPtr prefs = do_QueryInterface(subject, &rv); + if (NS_FAILED(rv)) return rv; + + // which preference changed? + if (NS_LITERAL_STRING(ENABLE_DISK_CACHE_PREF).Equals(data)) { + + rv = prefs->GetBoolPref(ENABLE_DISK_CACHE_PREF, &mDiskCacheEnabled); + + } else if (NS_LITERAL_STRING(ENABLE_MEMORY_CACHE_PREF).Equals(data)) { + + rv = prefs->GetBoolPref(ENABLE_MEMORY_CACHE_PREF, &mMemoryCacheEnabled); + } + + if (NS_FAILED(rv)) return rv; + nsCacheService::GlobalInstance()->SetCacheDevicesEnabled(mDiskCacheEnabled, + mMemoryCacheEnabled); + } + + return NS_OK; +} + + +/****************************************************************************** + * nsCacheService + *****************************************************************************/ + nsCacheService * nsCacheService::gService = nsnull; NS_IMPL_THREADSAFE_ISUPPORTS2(nsCacheService, nsICacheService, nsIObserver) nsCacheService::nsCacheService() : mCacheServiceLock(nsnull), + mEnableMemoryDevice(PR_TRUE), + mEnableDiskDevice(PR_TRUE), mMemoryDevice(nsnull), mDiskDevice(nsnull), mTotalEntries(0), @@ -95,25 +208,40 @@ nsCacheService::Init() // initialize hashtable for active cache entries rv = mActiveEntries.Init(); if (NS_FAILED(rv)) goto error; - - // create memory cache - mMemoryDevice = new nsMemoryCacheDevice; - if (!mMemoryDevice) { - rv = NS_ERROR_OUT_OF_MEMORY; - goto error; + + { // scope nsCOMPtr + nsCOMPtr prefs = do_GetService(NS_PREF_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) { + rv = prefs->GetBoolPref(ENABLE_DISK_CACHE_PREF, &mEnableDiskDevice); + rv = prefs->GetBoolPref(ENABLE_MEMORY_CACHE_PREF, &mEnableMemoryDevice); + // ignore errors + } + } + + if (mEnableMemoryDevice) { // create memory cache + mMemoryDevice = new nsMemoryCacheDevice; + if (!mMemoryDevice) { + rv = NS_ERROR_OUT_OF_MEMORY; + goto error; + } + rv = mMemoryDevice->Init(); + if (NS_FAILED(rv)) { + // XXX log error + delete mMemoryDevice; + mMemoryDevice = nsnull; + } } - rv = mMemoryDevice->Init(); - if (NS_FAILED(rv)) goto error; #if EAGER_DISK_INIT - // create disk cache - mDiskDevice = new nsDiskCacheDevice; - if (!mDiskDevice) { - rv = NS_ERROR_OUT_OF_MEMORY; - goto error; + if (mEnableDiskCache) { // create disk cache + mDiskDevice = new nsDiskCacheDevice; + if (!mDiskDevice) { + rv = NS_ERROR_OUT_OF_MEMORY; + goto error; + } + rv = mDiskDevice->Init(); + if (NS_FAILED(rv)) goto error; } - rv = mDiskDevice->Init(); - if (NS_FAILED(rv)) goto error; #endif // observer XPCOM shutdown. @@ -194,6 +322,9 @@ nsCacheService::CreateSession(const char * clientID, { *result = nsnull; + if (!(mEnableDiskDevice || mEnableMemoryDevice)) + return NS_ERROR_NOT_AVAILABLE; + nsCacheSession * session = new nsCacheSession(clientID, storagePolicy, streamBased); if (!session) return NS_ERROR_OUT_OF_MEMORY; @@ -207,44 +338,89 @@ nsCacheService::CreateSession(const char * clientID, NS_IMETHODIMP nsCacheService::VisitEntries(nsICacheVisitor *visitor) { nsAutoLock lock(mCacheServiceLock); - + + if (!(mEnableDiskDevice || mEnableMemoryDevice)) + return NS_ERROR_NOT_AVAILABLE; + // XXX record the fact that a visitation is in progress, i.e. keep // list of visitors in progress. - nsresult rv = mMemoryDevice->Visit(visitor); - if (NS_FAILED(rv)) return rv; - - - if (!mDiskDevice) { - rv = CreateDiskDevice(); + nsresult rv = NS_OK; + if (mEnableMemoryDevice) { + rv = mMemoryDevice->Visit(visitor); + if (NS_FAILED(rv)) return rv; + } + + if (mEnableDiskDevice) { + if (!mDiskDevice) { + rv = CreateDiskDevice(); + if (NS_FAILED(rv)) return rv; + } + rv = mDiskDevice->Visit(visitor); if (NS_FAILED(rv)) return rv; } - rv = mDiskDevice->Visit(visitor); - if (NS_FAILED(rv)) return rv; - // XXX notify any shutdown process that visitation is complete for THIS visitor. + // XXX keep queue of visitors return NS_OK; } +NS_IMETHODIMP nsCacheService::EvictEntries(nsCacheStoragePolicy storagePolicy) +{ + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + + if (storagePolicy == nsICache::STORE_ON_DISK) { + if (mEnableDiskDevice) { + if (!mDiskDevice) { + rv = CreateDiskDevice(); + if (NS_FAILED(rv)) return rv; + } + rv = mDiskDevice->EvictEntries(nsnull); + } + } + + return rv; +} + + +/** + * Internal Methods + */ nsresult nsCacheService::CreateDiskDevice() { - nsresult rv = NS_OK; - if (!mDiskDevice) { - // create disk cache lazily - mDiskDevice = new nsDiskCacheDevice; - if (mDiskDevice) { - rv = mDiskDevice->Init(); - if (NS_FAILED(rv)) { - delete mDiskDevice; - mDiskDevice = nsnull; - } - } else { - rv = NS_ERROR_OUT_OF_MEMORY; - } + if (!mEnableDiskDevice) return NS_ERROR_NOT_AVAILABLE; + if (mDiskDevice) return NS_OK; + + mDiskDevice = new nsDiskCacheDevice; + if (!mDiskDevice) return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = mDiskDevice->Init(); + if (NS_FAILED(rv)) { + // XXX log error + delete mDiskDevice; + mDiskDevice = nsnull; + } + return rv; +} + + +nsresult +nsCacheService::CreateMemoryDevice() +{ + if (!mEnableMemoryDevice) return NS_ERROR_NOT_AVAILABLE; + if (mMemoryDevice) return NS_OK; + + mMemoryDevice = new nsMemoryCacheDevice; + if (!mMemoryDevice) return NS_ERROR_OUT_OF_MEMORY; + + nsresult rv = mMemoryDevice->Init(); + if (NS_FAILED(rv)) { + // XXX log error + delete mMemoryDevice; + mMemoryDevice = nsnull; } return rv; } @@ -434,7 +610,7 @@ nsCacheService::ActivateEntry(nsCacheRequest * request, if (entry) { ++mCacheHits; - entry->IncrementFetchCount(); + entry->Fetched(); } else { ++mCacheMisses; } @@ -465,6 +641,7 @@ nsCacheService::ActivateEntry(nsCacheRequest * request, if (!entry) return NS_ERROR_OUT_OF_MEMORY; + entry->Fetched(); ++mTotalEntries; // XXX we could perform an early bind in some cases based on storage policy @@ -494,19 +671,22 @@ nsCacheService::SearchCacheDevices(nsCString * key, nsCacheStoragePolicy policy) nsCacheEntry * entry = nsnull; if ((policy == nsICache::STORE_ANYWHERE) || (policy == nsICache::STORE_IN_MEMORY)) { - entry = mMemoryDevice->FindEntry(key); + if (mEnableMemoryDevice) + entry = mMemoryDevice->FindEntry(key); } if (!entry && ((policy == nsICache::STORE_ANYWHERE) || (policy == nsICache::STORE_ON_DISK))) { - if (!mDiskDevice) { - nsresult rv = CreateDiskDevice(); - if (NS_FAILED(rv)) - return nsnull; + if (mEnableDiskDevice) { + if (!mDiskDevice) { + nsresult rv = CreateDiskDevice(); + if (NS_FAILED(rv)) + return nsnull; + } + + entry = mDiskDevice->FindEntry(key); } - - entry = mDiskDevice->FindEntry(key); } return entry; @@ -519,7 +699,7 @@ nsCacheService::EnsureEntryHasDevice(nsCacheEntry * entry) nsCacheDevice * device = entry->CacheDevice(); if (device) return device; - if (entry->IsStreamData() && entry->IsAllowedOnDisk()) { + if (entry->IsStreamData() && entry->IsAllowedOnDisk() && mEnableDiskDevice) { // this is the default if (!mDiskDevice) { nsresult rv = CreateDiskDevice(); @@ -528,11 +708,13 @@ nsCacheService::EnsureEntryHasDevice(nsCacheEntry * entry) } device = mDiskDevice; - } else { + } else if (mEnableMemoryDevice) { NS_ASSERTION(entry->IsAllowedInMemory(), "oops.. bad flags"); device = mMemoryDevice; } + if (device == nsnull) return nsnull; + nsresult rv = device->BindEntry(entry); if (NS_FAILED(rv)) return nsnull; @@ -601,6 +783,24 @@ nsCacheService::DoomEntry_Locked(nsCacheEntry * entry) } +void +nsCacheService::SetCacheDevicesEnabled(PRBool enableDisk, PRBool enableMemory) +{ + if (this == nsnull) return; // NS_ERROR_NOT_AVAILABLE; + nsAutoLock lock(mCacheServiceLock); + + if (enableDisk && !mDiskDevice) { + // disk device requires lazy activation + } else if (!enableDisk && mDiskDevice) { + // XXX deactivate disk + } + + if (enableMemory && !mMemoryDevice) { + // XXX enable memory cache device + } else if (!enableMemory && mMemoryDevice) { + // XXX disable memory cache device + } +} nsresult diff --git a/mozilla/netwerk/cache/src/nsCacheService.h b/mozilla/netwerk/cache/src/nsCacheService.h index 7917bcf03fa..98d736632b2 100644 --- a/mozilla/netwerk/cache/src/nsCacheService.h +++ b/mozilla/netwerk/cache/src/nsCacheService.h @@ -95,10 +95,9 @@ public: nsresult DoomEntry_Locked(nsCacheEntry * entry); /** - * static utility methods + * Methods called by nsCachePrefObserver */ - static nsresult ClientID(const nsAReadableCString& clientID, char ** result); - static nsresult ClientKey(const nsAReadableCString& clientKey, char ** result); + void SetCacheDevicesEnabled(PRBool disk, PRBool memory); private: @@ -107,6 +106,7 @@ private: */ nsresult CreateDiskDevice(); + nsresult CreateMemoryDevice(); nsresult CreateRequest(nsCacheSession * session, const char * clientKey, @@ -137,7 +137,7 @@ private: void ClearActiveEntries(void); static - PLDHashOperator PR_CALLBACK DeactivateAndClearEntry(PLDHashTable * table, + PLDHashOperator PR_CALLBACK DeactivateAndClearEntry(PLDHashTable * table, PLDHashEntryHdr * hdr, PRUint32 number, void * arg); @@ -154,6 +154,9 @@ private: PRLock* mCacheServiceLock; + PRBool mEnableMemoryDevice; + PRBool mEnableDiskDevice; + nsCacheDevice * mMemoryDevice; nsCacheDevice * mDiskDevice; diff --git a/mozilla/netwerk/cache/src/nsCacheSession.cpp b/mozilla/netwerk/cache/src/nsCacheSession.cpp index 599d16ae05b..4c1f8507fcb 100644 --- a/mozilla/netwerk/cache/src/nsCacheSession.cpp +++ b/mozilla/netwerk/cache/src/nsCacheSession.cpp @@ -94,3 +94,8 @@ NS_IMETHODIMP nsCacheSession::AsyncOpenCacheEntry(const char *key, if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) rv = NS_OK; return rv; } + +NS_IMETHODIMP nsCacheSession::EvictEntries() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/mozilla/netwerk/cache/src/nsDiskCache.h b/mozilla/netwerk/cache/src/nsDiskCache.h index 072c848a358..0b4f7a0c2f0 100644 --- a/mozilla/netwerk/cache/src/nsDiskCache.h +++ b/mozilla/netwerk/cache/src/nsDiskCache.h @@ -26,83 +26,115 @@ #ifndef _nsDiskCache_h_ #define _nsDiskCache_h_ -enum { - eEvictionRankMask = 0xFF000000; - eLocationSelectorMask = 0x00C00000; +#include "prtypes.h" +#include "prnetdb.h" +#include "nsDebug.h" - eExtraBlocksMask = 0x00300000; - eBlockNumberMask = 0x000FFFFF; +class nsDiskCacheRecord { + enum { + eEvictionRankMask = 0xFF000000, + eLocationSelectorMask = 0x00C00000, - eFileReservedMask = 0x003F0000; - eFileGenerationMask = 0x0000FFFF; -}; + eExtraBlocksMask = 0x00300000, + eBlockNumberMask = 0x000FFFFF, + + eFileReservedMask = 0x003F0000, + eFileGenerationMask = 0x0000FFFF + }; -class DiskCacheRecord { public: - PRUint32 HashNumber(void) { return mHashNumber; } - void SetHashNumber(PRUint32 hashNumber) { mHashNumber = hashNumber; } - - PRUint8 EvictionRank(void) + nsDiskCacheRecord() + : mHashNumber(0), mEvictionRank(0), mLocation(0), mUnused(0) { - return (PRUint8)(mInfo & eEvictionRankMask) >> 24; + } + + PRUint32 HashNumber() + { + return mHashNumber; + } + + void SetHashNumber(PRUint32 hashNumber) + { + mHashNumber = hashNumber; } - void SetEvictionRank(PRUint8 rank) + PRUint32 EvictionRank() { - mInfo &= ~eEvictionRankMask; // clear eviction rank bits - mInfo |= rank << 24; + return mEvictionRank; } - PRUint32 LocationSelector(void) + void SetEvictionRank(PRUint32 rank) { - return (PRUint32)(mInfo & eLocationSelectorMask) >> 22; + mEvictionRank = rank; } - void SetLocationSelector(PRUint32 selector) + PRUint32 LocationSelector() { - mInfo &= ~eLocationSelectorMask; // clear location selector bits - mInfo |= (selector & eLocationSelectorMask) << 22; + return (PRUint32)(mLocation & eLocationSelectorMask) >> 22; } - PRUint32 BlockCount(void) + void SetLocationSelector(PRUint32 selector) { - return (PRUint32)((mInfo & eExtraBlocksMask) >> 20) + 1; + mLocation &= ~eLocationSelectorMask; // clear location selector bits + mLocation |= (selector & eLocationSelectorMask) << 22; } - void SetBlockCount(PRUint32 count) + PRUint32 BlockCount() + { + return (PRUint32)((mLocation & eExtraBlocksMask) >> 20) + 1; + } + + void SetBlockCount(PRUint32 count) { NS_ASSERTION( (count>=1) && (count<=4),"invalid block count"); count = --count; - mInfo &= ~eExtraBlocksMask; // clear extra blocks bits - mInfo |= (count & eExtraBlocksMask) << 20; + mLocation &= ~eExtraBlocksMask; // clear extra blocks bits + mLocation |= (count & eExtraBlocksMask) << 20; } - PRUint32 BlockNumber(void) + PRUint32 BlockNumber() { - return mInfo & eBlockNumberMask; + return (mLocation & eBlockNumberMask); } void SetBlockNumber(PRUint32 blockNumber) { - mInfo &= ~eBlockNumberMask; // clear block number bits - mInfo |= blockNumber & eBlockNumberMask; + mLocation &= ~eBlockNumberMask; // clear block number bits + mLocation |= blockNumber & eBlockNumberMask; } - PRUint16 FileGeneration(void) + PRUint16 FileGeneration() { - return mInfo & eFileGenerationMask; + return (mLocation & eFileGenerationMask); } void SetFileGeneration(PRUint16 generation) { - mInfo &= ~eFileGenerationMask; // clear file generation bits - mInfo |= generation & eFileGenerationMask; + mLocation &= ~eFileGenerationMask; // clear file generation bits + mLocation |= generation & eFileGenerationMask; } + void Swap() + { + mHashNumber = ::PR_htonl(mHashNumber); + mEvictionRank = ::PR_htonl(mEvictionRank); + mLocation = ::PR_htonl(mLocation); + mUnused = ::PR_htonl(mUnused); + } + + void Unswap() + { + mHashNumber = ::PR_ntohl(mHashNumber); + mEvictionRank = ::PR_ntohl(mEvictionRank); + mLocation = ::PR_ntohl(mLocation); + mUnused = ::PR_ntohl(mUnused); + } private: - PRUint32 mHashNumber; - PRUint32 mInfo; + PRUint32 mHashNumber; + PRUint32 mEvictionRank; + PRUint32 mLocation; + PRUint32 mUnused; }; diff --git a/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp b/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp index 076c5630bf2..28f6905761c 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp @@ -10,7 +10,7 @@ * implied. See the License for the specific language governing * rights and limitations under the License. * - * The Original Code is nsMemoryCacheDevice.cpp, released February 22, 2001. + * The Original Code is nsDiskCacheDevice.cpp, released February 22, 2001. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are @@ -24,8 +24,10 @@ #include +#include "nsANSIFileStreams.h" #include "nsDiskCacheDevice.h" #include "nsDiskCacheEntry.h" +#include "nsDiskCacheMap.h" #include "nsCacheService.h" #include "nsCache.h" @@ -43,8 +45,6 @@ static const char DISK_CACHE_DEVICE_ID[] = { "disk" }; -static FILE* openFileStream(nsIFile* file, const char* mode); - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Using nsIPref will be subsumed with nsIDirectoryService when a selector @@ -75,9 +75,7 @@ NS_IMETHODIMP nsDiskCacheObserver::Observe(nsISupports *aSubject, const PRUnicha nsresult rv; // did a preference change? - nsLiteralString aTopicString(aTopic); - if (aTopicString.Equals(NS_LITERAL_STRING("nsPref:changed"))) { - // when bug #71879 gets fixed, this QueryInterface will succeed! + if (NS_LITERAL_STRING("nsPref:changed").Equals(aTopic)) { nsCOMPtr prefs = do_QueryInterface(aSubject, &rv); if (!prefs) { prefs = do_GetService(NS_PREF_CONTRACTID, &rv); @@ -98,7 +96,7 @@ NS_IMETHODIMP nsDiskCacheObserver::Observe(nsISupports *aSubject, const PRUnicha if (NS_SUCCEEDED(rv)) mDevice->setCacheCapacity(cacheCapacity); } - } else if (aTopicString.Equals(NS_LITERAL_STRING("profile-do-change"))) { + } else if (NS_LITERAL_STRING("profile-do-change").Equals(aTopic)) { // XXX need to regenerate the cache directory. hopefully the // cache service has already been informed of this change. nsCOMPtr profileDir; @@ -283,6 +281,7 @@ NS_IMPL_ISUPPORTS1(nsDiskCacheDeviceInfo, nsICacheDeviceInfo); /* readonly attribute string description; */ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetDescription(char ** aDescription) { + NS_ENSURE_ARG_POINTER(aDescription); char* result = nsCRT::strdup("disk cache device"); if (!result) return NS_ERROR_OUT_OF_MEMORY; *aDescription = result; @@ -292,6 +291,7 @@ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetDescription(char ** aDescription) /* readonly attribute string usageReport; */ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetUsageReport(char ** aUsageReport) { + NS_ENSURE_ARG_POINTER(aUsageReport); char* result = nsCRT::strdup("disk cache usage report"); if (!result) return NS_ERROR_OUT_OF_MEMORY; *aUsageReport = result; @@ -301,12 +301,15 @@ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetUsageReport(char ** aUsageReport) /* readonly attribute unsigned long entryCount; */ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetEntryCount(PRUint32 *aEntryCount) { - return NS_ERROR_NOT_IMPLEMENTED; + NS_ENSURE_ARG_POINTER(aEntryCount); + *aEntryCount = mDevice->getEntryCount(); + return NS_OK; } /* readonly attribute unsigned long totalSize; */ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetTotalSize(PRUint32 *aTotalSize) { + NS_ENSURE_ARG_POINTER(aTotalSize); *aTotalSize = mDevice->getCacheSize(); return NS_OK; } @@ -314,6 +317,7 @@ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetTotalSize(PRUint32 *aTotalSize) /* readonly attribute unsigned long maximumSize; */ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetMaximumSize(PRUint32 *aMaximumSize) { + NS_ENSURE_ARG_POINTER(aMaximumSize); *aMaximumSize = mDevice->getCacheCapacity(); return NS_OK; } @@ -354,6 +358,30 @@ struct MetaDataHeader { mMetaDataSize(0) { } + + void Swap() + { + mHeaderSize = ::PR_htonl(mHeaderSize); + mFetchCount = ::PR_htonl(mFetchCount); + mLastFetched = ::PR_htonl(mLastFetched); + mLastModified = ::PR_htonl(mLastModified); + mExpirationTime = ::PR_htonl(mExpirationTime); + mDataSize = ::PR_htonl(mDataSize); + mKeySize = ::PR_htonl(mKeySize); + mMetaDataSize = ::PR_htonl(mMetaDataSize); + } + + void Unswap() + { + mHeaderSize = ::PR_ntohl(mHeaderSize); + mFetchCount = ::PR_ntohl(mFetchCount); + mLastFetched = ::PR_ntohl(mLastFetched); + mLastModified = ::PR_ntohl(mLastModified); + mExpirationTime = ::PR_ntohl(mExpirationTime); + mDataSize = ::PR_ntohl(mDataSize); + mKeySize = ::PR_ntohl(mKeySize); + mMetaDataSize = ::PR_ntohl(mMetaDataSize); + } }; struct MetaDataFile : MetaDataHeader { @@ -386,69 +414,25 @@ struct MetaDataFile : MetaDataHeader { return entry->FlattenMetaData(&mMetaData, &mMetaDataSize); } - nsresult Write(nsIOutputStream* output); nsresult Read(nsIInputStream* input); + nsresult Write(nsIOutputStream* output); }; -#define WRITE_LONG_(item) \ - PR_BEGIN_MACRO \ - n = PR_htonl(item); \ - rv = output->Write((char*)&n, sizeof(n), &count); \ - if (NS_FAILED(rv)) return rv; \ - PR_END_MACRO - -#define READ_LONG_(item) \ - PR_BEGIN_MACRO \ - rv = input->Read((char*)&n, sizeof(n), &count); \ - if (NS_FAILED(rv)) return rv; \ - item = PR_ntohl(n); \ - PR_END_MACRO - -nsresult MetaDataFile::Write(nsIOutputStream* output) -{ - nsresult rv; - PRUint32 n, count; - - WRITE_LONG_(mHeaderSize); - WRITE_LONG_(mFetchCount); - WRITE_LONG_(mLastFetched); - WRITE_LONG_(mLastModified); - WRITE_LONG_(mExpirationTime); - WRITE_LONG_(mDataSize); - WRITE_LONG_(mKeySize); - WRITE_LONG_(mMetaDataSize); - - // write the key to the file. - rv = output->Write(mKey, mKeySize, &count); - if (NS_FAILED(rv)) return rv; - - // write the flattened metadata to the file. - if (mMetaDataSize) { - rv = output->Write(mMetaData, mMetaDataSize, &count); - if (NS_FAILED(rv)) return rv; - } - - return NS_OK; -} - nsresult MetaDataFile::Read(nsIInputStream* input) { nsresult rv; - PRUint32 n, count; + PRUint32 count; - // read the header size used by this file. - READ_LONG_(mHeaderSize); + // read in the file header. + rv = input->Read((char*)&mHeaderSize, sizeof(MetaDataHeader), &count); + if (NS_FAILED(rv)) return rv; + Unswap(); + + // make sure it is self-consistent. if (mHeaderSize != sizeof(MetaDataHeader)) { - NS_ERROR("### CACHE FORMAT CHANGED!!! PLEASE DELETE YOUR CACHE DIRECTORY!!! ###"); + NS_ERROR("### CACHE FORMAT CHANGED!!! PLEASE DELETE YOUR NewCache DIRECTORY!!! ###"); return NS_ERROR_ILLEGAL_VALUE; } - READ_LONG_(mFetchCount); - READ_LONG_(mLastFetched); - READ_LONG_(mLastModified); - READ_LONG_(mExpirationTime); - READ_LONG_(mDataSize); - READ_LONG_(mKeySize); - READ_LONG_(mMetaDataSize); // read in the key. delete[] mKey; @@ -470,6 +454,30 @@ nsresult MetaDataFile::Read(nsIInputStream* input) return NS_OK; } +nsresult MetaDataFile::Write(nsIOutputStream* output) +{ + nsresult rv; + PRUint32 count; + + // write the header to the file. + Swap(); + rv = output->Write((char*)&mHeaderSize, sizeof(MetaDataHeader), &count); + Unswap(); + if (NS_FAILED(rv)) return rv; + + // write the key to the file. + rv = output->Write(mKey, mKeySize, &count); + if (NS_FAILED(rv)) return rv; + + // write the flattened metadata to the file. + if (mMetaDataSize) { + rv = output->Write(mMetaData, mMetaDataSize, &count); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; +} + // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX class nsDiskCacheEntryInfo : public nsICacheEntryInfo { @@ -526,11 +534,6 @@ NS_IMETHODIMP nsDiskCacheEntryInfo::GetLastModified(PRUint32 *aLastModified) return NS_OK; } -NS_IMETHODIMP nsDiskCacheEntryInfo::GetLastValidated(PRUint32 *aLastValidated) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - NS_IMETHODIMP nsDiskCacheEntryInfo::GetExpirationTime(PRUint32 *aExpirationTime) { *aExpirationTime = mMetaDataFile.mExpirationTime; @@ -551,30 +554,60 @@ NS_IMETHODIMP nsDiskCacheEntryInfo::GetDataSize(PRUint32 *aDataSize) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +/** + * Helper class for implementing do_QueryElementAt() pattern. Thanks scc! + * Eventually this should become part of nsICollection.idl. + */ +class do_QueryElementAt : public nsCOMPtr_helper { +public: + do_QueryElementAt(nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr = 0) + : mCollection(aCollection), + mIndex(aIndex), + mErrorPtr(aErrorPtr) + { + // nothing else to do here + } + + virtual nsresult operator()( const nsIID& aIID, void** aResult) const + { + nsresult status; + if ( mCollection ) { + if ( !NS_SUCCEEDED(status = mCollection->QueryElementAt(mIndex, aIID, aResult)) ) + *aResult = 0; + } else + status = NS_ERROR_NULL_POINTER; + if ( mErrorPtr ) + *mErrorPtr = status; + return status; + } + +private: + nsICollection* mCollection; + PRUint32 mIndex; + nsresult* mErrorPtr; +}; + +#if 0 +inline const nsQueryElementAt +do_QueryElementAt( nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr = 0 ) +{ + return nsQueryElementAt(aCollection, aIndex, aErrorPtr); +} +#endif + +// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + static nsCOMPtr gFileTransportService; nsDiskCacheDevice::nsDiskCacheDevice() - : mCacheCapacity(0), mCacheSize(0), mInitialized(PR_FALSE) + : mInitialized(PR_FALSE), mCacheCapacity(0), mCacheMap(nsnull) { } nsDiskCacheDevice::~nsDiskCacheDevice() { - removeObservers(this); - - if (mInitialized) { -#if 1 - // XXX implement poor man's eviction strategy right here, - // keep deleting cache entries from oldest to newest, until - // cache usage is brought below limits. - evictDiskCacheEntries(); -#endif - - // XXX write out persistent information about the cache. - writeCacheInfo(); - } - // XXX release the reference to the cached file transport service. - gFileTransportService = nsnull; + Shutdown(); + delete mCacheMap; } nsresult @@ -593,16 +626,46 @@ nsDiskCacheDevice::Init() // XXX read in persistent information about the cache. this can fail, if // no cache directory has ever existed before. - rv = readCacheInfo(); + mCacheMap = new nsDiskCacheMap; + if (!mCacheMap) return NS_ERROR_OUT_OF_MEMORY; + + rv = readCacheMap(); if (NS_FAILED(rv)) { nsCOMPtr entries; scanDiskCacheEntries(getter_AddRefs(entries)); } + // XXX record that initialization succeeded. mInitialized = PR_TRUE; return NS_OK; } +nsresult +nsDiskCacheDevice::Shutdown() +{ + if (mInitialized) { + // XXX implement poor man's eviction strategy right here, + // keep deleting cache entries from oldest to newest, until + // cache usage is brought below limits. + evictDiskCacheEntries(); + + // XXX write out persistent information about the cache. + writeCacheMap(); + + // XXX no longer initialized. + mInitialized = PR_FALSE; + } + + // XXX disconnect observers. + removeObservers(this); + + // XXX release the reference to the cached file transport service. + gFileTransportService = nsnull; + + return NS_OK; +} + + nsresult nsDiskCacheDevice::Create(nsCacheDevice **result) { @@ -634,13 +697,17 @@ nsDiskCacheDevice::FindEntry(nsCString * key) nsCacheEntry * entry = nsnull; nsDiskCacheEntry * diskEntry = mBoundEntries.GetEntry(key->get()); if (!diskEntry) { - nsresult rv = readDiskCacheEntry(key->get(), &diskEntry); - if (NS_FAILED(rv)) return nsnull; - entry = diskEntry->getCacheEntry(); - rv = mBoundEntries.AddEntry(diskEntry); - if (NS_FAILED(rv)) { - delete entry; - return nsnull; + PLDHashNumber hashNumber = nsDiskCacheEntry::Hash(key->get()); + nsDiskCacheRecord* record = mCacheMap->GetRecord(hashNumber); + if (record->HashNumber() == hashNumber) { + nsresult rv = readDiskCacheEntry(key->get(), &diskEntry); + if (NS_FAILED(rv)) return nsnull; + entry = diskEntry->getCacheEntry(); + rv = mBoundEntries.AddEntry(diskEntry); + if (NS_FAILED(rv)) { + delete entry; + return nsnull; + } } } else { // XXX need to make sure this is an exact match, not just @@ -707,6 +774,7 @@ nsDiskCacheDevice::BindEntry(nsCacheEntry * newEntry) // Make sure this entry has its associated nsDiskCacheEntry data attached. nsDiskCacheEntry* newDiskEntry = ensureDiskCacheEntry(newEntry); NS_ASSERTION(newDiskEntry, "nsDiskCacheDevice::BindEntry"); + if (!newDiskEntry) return NS_ERROR_OUT_OF_MEMORY; // XXX check for cache collision. if an entry exists on disk that has the same // hash code as this newly bound entry, AND there is already a bound entry for @@ -736,6 +804,9 @@ nsDiskCacheDevice::BindEntry(nsCacheEntry * newEntry) OnDataSizeChange(newEntry, dataSize); // XXX Need to make this entry known to other entries? + // this probably isn't needed while the entry is bound, + // only when the entry is deactivated. this could be + // the reason disk cache performance suffers. return updateDiskCacheEntry(newDiskEntry); } @@ -746,9 +817,11 @@ nsDiskCacheDevice::DoomEntry(nsCacheEntry * entry) // so it can't be seen by FindEntry() ever again. nsDiskCacheEntry* diskEntry = ensureDiskCacheEntry(entry); mBoundEntries.RemoveEntry(diskEntry); + + // XXX clear this entry out of the cache map. // keep track of the cache total size. - mCacheSize -= entry->DataSize(); + mCacheMap->DataSize() -= entry->DataSize(); } @@ -791,20 +864,20 @@ nsDiskCacheDevice::GetFileForEntry(nsCacheEntry * entry, nsIFile ** result) { nsDiskCacheEntry* diskEntry = ensureDiskCacheEntry(entry); - return getFileForKey(entry->Key()->get(), PR_FALSE, - diskEntry->getGeneration(), result); + if (!diskEntry) return NS_ERROR_OUT_OF_MEMORY; + return getFileForDiskCacheEntry(diskEntry, PR_FALSE, result); } /** - * This routine will get called every time an open descriptor. + * This routine will get called every time an open descriptor is written to. */ nsresult nsDiskCacheDevice::OnDataSizeChange(nsCacheEntry * entry, PRInt32 deltaSize) { - mCacheSize += deltaSize; + PRUint32 newCacheSize = (mCacheMap->DataSize() += deltaSize); #if 0 - if (mCacheSize > mCacheCapacity) { + if (newCacheSize > mCacheCapacity) { // XXX go toss out some disk cache entries. evictDiskCacheEntries(); } @@ -816,7 +889,6 @@ nsDiskCacheDevice::OnDataSizeChange(nsCacheEntry * entry, PRInt32 deltaSize) nsresult nsDiskCacheDevice::Visit(nsICacheVisitor * visitor) { - // XXX nsDiskCacheDeviceInfo* deviceInfo = new nsDiskCacheDeviceInfo(this); nsCOMPtr ref(deviceInfo); @@ -830,6 +902,61 @@ nsDiskCacheDevice::Visit(nsICacheVisitor * visitor) return NS_OK; } +nsresult +nsDiskCacheDevice::EvictEntries(const char * clientID) +{ + nsCOMPtr entries; + nsresult rv = scanDiskCacheEntries(getter_AddRefs(entries)); + if (NS_FAILED(rv)) return rv; + + PRUint32 prefixLength = (clientID ? nsCRT::strlen(clientID) : 0); + PRUint32 newDataSize = mCacheMap->DataSize(); + + PRUint32 count; + entries->Count(&count); + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr info = do_QueryElementAt(entries, i, &rv); + if (NS_SUCCEEDED(rv)) { + nsDiskCacheEntryInfo* entryInfo = (nsDiskCacheEntryInfo*) info.get(); + const char* key = entryInfo->Key(); + + // if filtering by clientID, make sure key prefix and clientID match. + if (clientID && nsCRT::strncmp(clientID, key, prefixLength) != 0) + continue; + + // if the entry is currently in use, then doom it rather than evicting right here. + nsDiskCacheEntry* diskEntry = mBoundEntries.GetEntry(key); + if (diskEntry) { + nsCacheService::GlobalInstance()->DoomEntry_Locked(diskEntry->getCacheEntry()); + continue; + } + + // delete the metadata file. + nsCOMPtr metaFile; + rv = getFileForKey(key, PR_TRUE, 0, getter_AddRefs(metaFile)); + if (NS_SUCCEEDED(rv)) { + rv = metaFile->Delete(PR_FALSE); + } + + // delete the data file + nsCOMPtr dataFile; + rv = getFileForKey(key, PR_FALSE, 0, getter_AddRefs(dataFile)); + if (NS_SUCCEEDED(rv)) { + rv = dataFile->Delete(PR_FALSE); + } + + // update the cache size. + PRUint32 dataSize; + info->GetDataSize(&dataSize); + newDataSize -= dataSize; + } + } + + mCacheMap->DataSize() = newDataSize; + return NS_OK; +} + + void nsDiskCacheDevice::setPrefsObserver(nsIObserver* observer) { mPrefsObserver = observer; @@ -858,11 +985,15 @@ PRUint32 nsDiskCacheDevice::getCacheCapacity() PRUint32 nsDiskCacheDevice::getCacheSize() { - return mCacheSize; + return mCacheMap->DataSize(); } -nsresult nsDiskCacheDevice::getFileForKey(const char* key, PRBool meta, - PRUint32 generation, nsIFile ** result) +PRUint32 nsDiskCacheDevice::getEntryCount() +{ + return mCacheMap->EntryCount(); +} + +nsresult nsDiskCacheDevice::getFileForHashNumber(PLDHashNumber hashNumber, PRBool meta, PRUint32 generation, nsIFile ** result) { if (mCacheDirectory) { nsCOMPtr entryFile; @@ -871,32 +1002,24 @@ nsresult nsDiskCacheDevice::getFileForKey(const char* key, PRBool meta, return rv; // generate the hash code for this entry, and use that as a file name. char name[32]; - PLDHashNumber hash = ::PL_DHashStringKey(NULL, key); - ::sprintf(name, "%08X%c%02X", hash, (meta ? 'm' : 'd'), generation); + ::sprintf(name, "%08X%c%02X", hashNumber, (meta ? 'm' : 'd'), generation); entryFile->Append(name); NS_ADDREF(*result = entryFile); return NS_OK; } return NS_ERROR_NOT_AVAILABLE; } +nsresult nsDiskCacheDevice::getFileForKey(const char* key, PRBool meta, + PRUint32 generation, nsIFile ** result) +{ + PLDHashNumber hash = nsDiskCacheEntry::Hash(key); + return getFileForHashNumber(hash, meta, generation, result); +} nsresult nsDiskCacheDevice::getFileForDiskCacheEntry(nsDiskCacheEntry * diskEntry, PRBool meta, nsIFile ** result) { - if (mCacheDirectory) { - nsCOMPtr entryFile; - nsresult rv = mCacheDirectory->Clone(getter_AddRefs(entryFile)); - if (NS_FAILED(rv)) - return rv; - // generate the hash code for this entry, and use that as a file name. - char name[32]; - ::sprintf(name, "%08X%c%02X", diskEntry->getHashNumber(), - (meta ? 'm' : 'd'), diskEntry->getGeneration()); - entryFile->Append(name); - NS_ADDREF(*result = entryFile); - return NS_OK; - } - return NS_ERROR_NOT_AVAILABLE; + return getFileForHashNumber(diskEntry->getHashNumber(), meta, diskEntry->getGeneration(), result); } nsresult nsDiskCacheDevice::getTransportForFile(nsIFile* file, nsCacheAccessMode mode, nsITransport ** result) @@ -916,6 +1039,55 @@ nsresult nsDiskCacheDevice::getTransportForFile(nsIFile* file, nsCacheAccessMode return gFileTransportService->CreateTransport(file, ioFlags, PR_IRUSR | PR_IWUSR, result); } +static FILE* openFileStream(nsIFile* file, const char* mode) +{ + FILE* stream = nsnull; + nsCOMPtr localFile = do_QueryInterface(file); + if (localFile) { + nsresult rv = localFile->OpenANSIFileDesc(mode, &stream); + if (NS_FAILED(rv)) return nsnull; + } + return stream; +} + +nsresult nsDiskCacheDevice::openInputStream(nsIFile * file, nsIInputStream ** result) +{ + FILE* stream = openFileStream(file, "rb"); + if (stream) { + nsCOMPtr input(new nsANSIInputStream(stream)); + if (!input) { + ::fclose(stream); + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(*result = input); + return NS_OK; + } else { + nsCOMPtr transport; + nsresult rv = getTransportForFile(file, nsICache::ACCESS_READ, getter_AddRefs(transport)); + if (NS_FAILED(rv)) return rv; + return transport->OpenInputStream(0, ULONG_MAX, 0, result); + } +} + +nsresult nsDiskCacheDevice::openOutputStream(nsIFile * file, nsIOutputStream ** result) +{ + FILE* stream = openFileStream(file, "wb"); + if (stream) { + nsCOMPtr output(new nsANSIOutputStream(stream)); + if (!output) { + ::fclose(stream); + return NS_ERROR_OUT_OF_MEMORY; + } + NS_ADDREF(*result = output); + return NS_OK; + } else { + nsCOMPtr transport; + nsresult rv = getTransportForFile(file, nsICache::ACCESS_WRITE, getter_AddRefs(transport)); + if (NS_FAILED(rv)) return rv; + return transport->OpenOutputStream(0, ULONG_MAX, 0, result); + } +} + inline PRBool isMetaDataFile(const char* name) { return (name[8] == 'm'); @@ -945,11 +1117,8 @@ nsresult nsDiskCacheDevice::visitEntries(nsICacheVisitor * visitor) rv = file->GetLeafName(getter_Copies(name)); if (isMetaDataFile(name)) { // this must be a metadata file. - nsCOMPtr transport; - rv = getTransportForFile(file, nsICache::ACCESS_READ, getter_AddRefs(transport)); - if (NS_FAILED(rv)) continue; nsCOMPtr input; - rv = transport->OpenInputStream(0, ULONG_MAX, 0, getter_AddRefs(input)); + rv = openInputStream(file, getter_AddRefs(input)); if (NS_FAILED(rv)) continue; // read the metadata file. @@ -989,27 +1158,20 @@ nsresult nsDiskCacheDevice::updateDiskCacheEntries() nsresult nsDiskCacheDevice::updateDiskCacheEntry(nsDiskCacheEntry* diskEntry) { + nsresult rv; nsCacheEntry* entry = diskEntry->getCacheEntry(); if (entry->IsMetaDataDirty() || entry->IsEntryDirty()) { - nsresult rv; -#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS - nsCOMPtr& transport = diskEntry->getMetaTransport(nsICache::ACCESS_WRITE); -#else - nsCOMPtr transport; -#endif - if (!transport) { - nsCOMPtr file; - rv = getFileForDiskCacheEntry(diskEntry, PR_TRUE, - getter_AddRefs(file)); - if (NS_FAILED(rv)) return rv; - - rv = getTransportForFile(file, nsICache::ACCESS_WRITE, - getter_AddRefs(transport)); - if (NS_FAILED(rv)) return rv; - } + // make sure this disk entry is known to the cache map. + rv = updateCacheMap(diskEntry); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr file; + rv = getFileForDiskCacheEntry(diskEntry, PR_TRUE, + getter_AddRefs(file)); + if (NS_FAILED(rv)) return rv; nsCOMPtr output; - rv = transport->OpenOutputStream(0, ULONG_MAX, 0, getter_AddRefs(output)); + rv = openOutputStream(file, getter_AddRefs(output)); if (NS_FAILED(rv)) return rv; // write the metadata to the file. @@ -1017,8 +1179,8 @@ nsresult nsDiskCacheDevice::updateDiskCacheEntry(nsDiskCacheEntry* diskEntry) rv = metaDataFile.Init(entry); if (NS_FAILED(rv)) return rv; rv = metaDataFile.Write(output); - - rv = output->Close(); + output->Close(); + if (NS_FAILED(rv)) return rv; // mark the disk entry as being consistent with meta data file. entry->MarkMetaDataClean(); @@ -1058,26 +1220,10 @@ nsresult nsDiskCacheDevice::readDiskCacheEntry(const char * key, nsDiskCacheEntr rv = file->Exists(&exists); if (NS_FAILED(rv) || !exists) return NS_ERROR_NOT_AVAILABLE; - nsCacheEntry* entry; - rv = NS_NewCacheEntry(&entry, key, PR_TRUE, nsICache::STORE_ON_DISK, this); - if (NS_FAILED(rv)) return rv; - + nsCacheEntry* entry = nsnull; do { - nsDiskCacheEntry* diskEntry = ensureDiskCacheEntry(entry); - if (!diskEntry) break; - -#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS - nsCOMPtr& transport = diskEntry->getMetaTransport(nsICache::ACCESS_READ); -#else - nsCOMPtr transport; -#endif - if (!transport) { - rv = getTransportForFile(file, nsICache::ACCESS_READ, getter_AddRefs(transport)); - if (NS_FAILED(rv)) break; - } - nsCOMPtr input; - rv = transport->OpenInputStream(0, ULONG_MAX, 0, getter_AddRefs(input)); + rv = openInputStream(file, getter_AddRefs(input)); if (NS_FAILED(rv)) break; // read the metadata file. @@ -1089,6 +1235,9 @@ nsresult nsDiskCacheDevice::readDiskCacheEntry(const char * key, nsDiskCacheEntr // Ensure that the keys match. if (nsCRT::strcmp(key, metaDataFile.mKey) != 0) break; + rv = NS_NewCacheEntry(&entry, key, PR_TRUE, nsICache::STORE_ON_DISK, this); + if (NS_FAILED(rv)) return rv; + // initialize the entry. entry->SetFetchCount(metaDataFile.mFetchCount); entry->SetLastFetched(metaDataFile.mLastFetched); @@ -1103,7 +1252,8 @@ nsresult nsDiskCacheDevice::readDiskCacheEntry(const char * key, nsDiskCacheEntr } // celebrate! - *result = diskEntry; + *result = ensureDiskCacheEntry(entry); + if (!*result) break; return NS_OK; } while (0); @@ -1134,10 +1284,12 @@ nsresult nsDiskCacheDevice::deleteDiskCacheEntry(nsDiskCacheEntry * diskEntry) // NS_ASSERTION(NS_SUCCEEDED(rv), "nsDiskCacheDevice::deleteDiskCacheEntry"); } + // remove from cache map. + mCacheMap->DeleteRecord(diskEntry->getHashNumber()); + return NS_OK; } - nsresult nsDiskCacheDevice::scavengeDiskCacheEntries(nsDiskCacheEntry * diskEntry) { nsresult rv; @@ -1193,45 +1345,6 @@ nsresult nsDiskCacheDevice::scavengeDiskCacheEntries(nsDiskCacheEntry * diskEntr return NS_OK; } -/** - * Helper class for implementing do_QueryElementAt() pattern. Thanks scc! - * Eventually this should become part of nsICollection.idl. - */ -class nsQueryElementAt : public nsCOMPtr_helper { -public: - nsQueryElementAt( nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr ) - : mCollection(aCollection), - mIndex(aIndex), - mErrorPtr(aErrorPtr) - { - // nothing else to do here - } - - virtual nsresult operator()( const nsIID& aIID, void** aResult) const - { - nsresult status; - if ( mCollection ) { - if ( !NS_SUCCEEDED(status = mCollection->QueryElementAt(mIndex, aIID, aResult)) ) - *aResult = 0; - } else - status = NS_ERROR_NULL_POINTER; - if ( mErrorPtr ) - *mErrorPtr = status; - return status; - } - -private: - nsICollection* mCollection; - PRUint32 mIndex; - nsresult* mErrorPtr; -}; - -inline const nsQueryElementAt -do_QueryElementAt( nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr = 0 ) -{ - return nsQueryElementAt(aCollection, aIndex, aErrorPtr); -} - nsresult nsDiskCacheDevice::scanDiskCacheEntries(nsISupportsArray ** result) { nsresult rv; @@ -1259,11 +1372,8 @@ nsresult nsDiskCacheDevice::scanDiskCacheEntries(nsISupportsArray ** result) rv = file->GetLeafName(getter_Copies(name)); if (isMetaDataFile(name)) { // this must be a metadata file. - nsCOMPtr transport; - rv = getTransportForFile(file, nsICache::ACCESS_READ, getter_AddRefs(transport)); - if (NS_FAILED(rv)) continue; nsCOMPtr input; - rv = transport->OpenInputStream(0, ULONG_MAX, 0, getter_AddRefs(input)); + rv = openInputStream(file, getter_AddRefs(input)); if (NS_FAILED(rv)) continue; nsDiskCacheEntryInfo* entryInfo = new nsDiskCacheEntryInfo(); @@ -1320,7 +1430,8 @@ nsresult nsDiskCacheDevice::scanDiskCacheEntries(nsISupportsArray ** result) NS_ADDREF(*result = entries); // we've successfully totaled the cache size. - mCacheSize = newCacheSize; + mCacheMap->DataSize() = newCacheSize; + entries->Count(&mCacheMap->EntryCount()); return NS_OK; } @@ -1331,7 +1442,7 @@ nsresult nsDiskCacheDevice::evictDiskCacheEntries() nsresult rv = scanDiskCacheEntries(getter_AddRefs(entries)); if (NS_FAILED(rv)) return rv; - if (mCacheSize < mCacheCapacity) return NS_OK; + if (mCacheMap->DataSize() < mCacheCapacity) return NS_OK; // these are sorted in oldest to newest order. PRUint32 count; @@ -1364,8 +1475,7 @@ nsresult nsDiskCacheDevice::evictDiskCacheEntries() // update the cache size. PRUint32 dataSize; info->GetDataSize(&dataSize); - mCacheSize -= dataSize; - if (mCacheSize <= mCacheCapacity) + if ((mCacheMap->DataSize() -= dataSize) <= mCacheCapacity) break; } } @@ -1373,73 +1483,91 @@ nsresult nsDiskCacheDevice::evictDiskCacheEntries() return NS_OK; } -static FILE* openFileStream(nsIFile* file, const char* mode) +nsresult nsDiskCacheDevice::readCacheMap() { - FILE* stream = nsnull; - nsCOMPtr localFile = do_QueryInterface(file); - if (localFile) { - nsresult rv = localFile->OpenANSIFileDesc(mode, &stream); - if (NS_FAILED(rv)) return nsnull; - } - return stream; + nsCOMPtr file; + nsresult rv = mCacheDirectory->Clone(getter_AddRefs(file)); + if (NS_FAILED(rv)) return rv; + + rv = file->Append("_CACHE_MAP_"); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr input; + rv = openInputStream(file, getter_AddRefs(input)); + if (NS_FAILED(rv)) return rv; + + rv = mCacheMap->Read(input); + input->Close(); + + return rv; } -nsresult nsDiskCacheDevice::writeCacheInfo() +nsresult nsDiskCacheDevice::writeCacheMap() { - nsCOMPtr infoFile; - nsresult rv = mCacheDirectory->Clone(getter_AddRefs(infoFile)); + nsCOMPtr file; + nsresult rv = mCacheDirectory->Clone(getter_AddRefs(file)); if (NS_FAILED(rv)) return rv; - rv = infoFile->Append("CacheInfo"); + rv = file->Append("_CACHE_MAP_"); if (NS_FAILED(rv)) return rv; - PRUint32 cacheSize = PR_htonl(mCacheSize); + nsCOMPtr output; + rv = openOutputStream(file, getter_AddRefs(output)); + if (NS_FAILED(rv)) return rv; + + rv = mCacheMap->Write(output); + output->Close(); + + return rv; +} - FILE* stream = openFileStream(infoFile, "wb"); - if (stream) { - fwrite(&cacheSize, sizeof(cacheSize), 1, stream); - fclose(stream); +nsresult nsDiskCacheDevice::updateCacheMap(nsDiskCacheEntry * diskEntry) +{ + // get a record from the cache map, and use the fetch time for eviction ranking. + nsDiskCacheRecord* record = mCacheMap->GetRecord(diskEntry->getHashNumber()); + if (record->HashNumber() != diskEntry->getHashNumber()) { + if (record->HashNumber() != 0) { + // eviction of eldest entry in this bucket. + evictDiskCacheRecord(record); + } + // newly bound record. fill in the blanks. + record->SetHashNumber(diskEntry->getHashNumber()); + record->SetEvictionRank(0); + record->SetFileGeneration(diskEntry->getGeneration()); } else { - nsCOMPtr transport; - rv = getTransportForFile(infoFile, nsICache::ACCESS_WRITE, getter_AddRefs(transport)); - if (NS_FAILED(rv)) return rv; - nsCOMPtr output; - rv = transport->OpenOutputStream(0, ULONG_MAX, 0, getter_AddRefs(output)); - if (NS_FAILED(rv)) return rv; - PRUint32 count = sizeof(cacheSize); - rv = output->Write((char*)&cacheSize, count, &count); - rv = output->Close(); + record->SetEvictionRank(record->EvictionRank() + 1); } return NS_OK; } -nsresult nsDiskCacheDevice::readCacheInfo() +/** + * This evicts the disk cache entry that corresponds to the given record. + * If the entry happens to be bound, it must be doomed, otherwise, it can + * be eagerly removed from disk. + */ +nsresult nsDiskCacheDevice::evictDiskCacheRecord(nsDiskCacheRecord * record) { - nsCOMPtr infoFile; - nsresult rv = mCacheDirectory->Clone(getter_AddRefs(infoFile)); - if (NS_FAILED(rv)) return rv; + nsresult rv; - rv = infoFile->Append("CacheInfo"); - if (NS_FAILED(rv)) return rv; + // if the entry is currently in use, then doom it rather than evicting right here. + nsDiskCacheEntry* diskEntry = mBoundEntries.GetEntry(record->HashNumber()); + if (diskEntry) + return nsCacheService::GlobalInstance()->DoomEntry_Locked(diskEntry->getCacheEntry()); - PRUint32 cacheSize = 0; + // delete the metadata file. + nsCOMPtr metaFile; + rv = getFileForHashNumber(record->HashNumber(), PR_TRUE, + record->FileGeneration(), getter_AddRefs(metaFile)); + if (NS_SUCCEEDED(rv)) + rv = metaFile->Delete(PR_FALSE); - FILE* stream = openFileStream(infoFile, "rb"); - if (stream) { - fread(&cacheSize, sizeof(mCacheSize), 1, stream); - fclose(stream); - } else { - nsCOMPtr transport; - rv = getTransportForFile(infoFile, nsICache::ACCESS_READ, getter_AddRefs(transport)); - if (NS_FAILED(rv)) return rv; - nsCOMPtr input; - rv = transport->OpenInputStream(0, ULONG_MAX, 0, getter_AddRefs(input)); - if (NS_FAILED(rv)) return rv; - PRUint32 count = sizeof(cacheSize); - rv = input->Read((char*)&cacheSize, count, &count); - rv = input->Close(); - } - mCacheSize = PR_ntohl(cacheSize); - return NS_OK; + // delete the data file + nsCOMPtr dataFile; + rv = getFileForHashNumber(record->HashNumber(), PR_FALSE, + record->FileGeneration(), getter_AddRefs(dataFile)); + if (NS_SUCCEEDED(rv)) + rv = dataFile->Delete(PR_FALSE); + + return rv; } diff --git a/mozilla/netwerk/cache/src/nsDiskCacheDevice.h b/mozilla/netwerk/cache/src/nsDiskCacheDevice.h index 6bc76de6117..170d33f27ad 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheDevice.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheDevice.h @@ -10,7 +10,7 @@ * implied. See the License for the specific language governing * rights and limitations under the License. * - * The Original Code is nsMemoryCacheDevice.h, released February 20, 2001. + * The Original Code is nsDiskCacheDevice.h, released February 20, 2001. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are @@ -18,7 +18,8 @@ * Rights Reserved. * * Contributor(s): - * Gordon Sheridan, 20-February-2001 + * Gordon Sheridan + * Patrick C. Beard */ #ifndef _nsDiskCacheDevice_h_ @@ -31,16 +32,22 @@ #include "nsIObserver.h" class nsDiskCacheEntry; +class nsDiskCacheMap; +class nsDiskCacheRecord; + class nsISupportsArray; +class nsIInputStream; +class nsIOutputStream; class nsDiskCacheDevice : public nsCacheDevice { public: nsDiskCacheDevice(); virtual ~nsDiskCacheDevice(); - nsresult Init(); + static nsresult Create(nsCacheDevice **result); - static nsresult Create(nsCacheDevice **result); + virtual nsresult Init(); + virtual nsresult Shutdown(); virtual const char * GetDeviceID(void); virtual nsCacheEntry * FindEntry(nsCString * key); @@ -59,6 +66,8 @@ public: virtual nsresult Visit(nsICacheVisitor * visitor); + virtual nsresult EvictEntries(const char * clientID); + /* private: */ void setPrefsObserver(nsIObserver* observer); void getPrefsObserver(nsIObserver ** result); @@ -66,10 +75,15 @@ public: void setCacheCapacity(PRUint32 capacity); PRUint32 getCacheCapacity(); PRUint32 getCacheSize(); + PRUint32 getEntryCount(); + nsresult getFileForHashNumber(PLDHashNumber hashNumber, PRBool meta, PRUint32 generation, nsIFile ** result); nsresult getFileForKey(const char* key, PRBool meta, PRUint32 generation, nsIFile ** result); nsresult getFileForDiskCacheEntry(nsDiskCacheEntry * diskEntry, PRBool meta, nsIFile ** result); + static nsresult getTransportForFile(nsIFile* file, nsCacheAccessMode mode, nsITransport ** result); + static nsresult openInputStream(nsIFile* file, nsIInputStream ** result); + static nsresult openOutputStream(nsIFile* file, nsIOutputStream ** result); nsresult visitEntries(nsICacheVisitor * visitory); @@ -84,16 +98,19 @@ public: nsresult scanDiskCacheEntries(nsISupportsArray ** result); nsresult evictDiskCacheEntries(); - nsresult writeCacheInfo(); - nsresult readCacheInfo(); + nsresult readCacheMap(); + nsresult writeCacheMap(); + nsresult updateCacheMap(nsDiskCacheEntry * diskEntry); + nsresult evictDiskCacheRecord(nsDiskCacheRecord * record); + private: + PRBool mInitialized; nsCOMPtr mPrefsObserver; nsCOMPtr mCacheDirectory; nsDiskCacheEntryHashTable mBoundEntries; PRUint32 mCacheCapacity; - PRUint32 mCacheSize; - PRBool mInitialized; + nsDiskCacheMap* mCacheMap; }; #endif // _nsDiskCacheDevice_h_ diff --git a/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp b/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp index 22f92286154..0d2d56050c5 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp @@ -21,10 +21,21 @@ * Patrick C. Beard */ +#include + #include "nsDiskCacheEntry.h" NS_IMPL_ISUPPORTS0(nsDiskCacheEntry); +PLDHashNumber +nsDiskCacheEntry::Hash(const char* key) +{ + PLDHashNumber h = 0; + for (const PRUint8* s = (PRUint8*) key; *s != '\0'; ++s) + h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ *s; + return (h == 0 ? ULONG_MAX : h); +} + /****************************************************************************** * nsCacheEntryHashTable *****************************************************************************/ @@ -70,7 +81,7 @@ nsDiskCacheEntryHashTable::Init() nsDiskCacheEntry * nsDiskCacheEntryHashTable::GetEntry(const char * key) { - return GetEntry(::PL_DHashStringKey(NULL, key)); + return GetEntry(nsDiskCacheEntry::Hash(key)); } diff --git a/mozilla/netwerk/cache/src/nsDiskCacheEntry.h b/mozilla/netwerk/cache/src/nsDiskCacheEntry.h index 663e689c8c7..b9d98329430 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheEntry.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheEntry.h @@ -44,7 +44,7 @@ public: { NS_INIT_ISUPPORTS(); PR_INIT_CLIST(this); - mHashNumber = ::PL_DHashStringKey(NULL, entry->Key()->get()); + mHashNumber = Hash(entry->Key()->get()); } virtual ~nsDiskCacheEntry() @@ -89,6 +89,8 @@ public: return mHashNumber; } + static PLDHashNumber Hash(const char* key); + private: #ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS nsCOMPtr mTransports[3]; diff --git a/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp b/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp index 7b4c4eaea2b..49b8e91686a 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp @@ -22,8 +22,9 @@ */ #include "nsDiskCacheMap.h" -#include "nsIInputStream.h" -#include "nsIOutputStream.h" +#include "nsIFileStreams.h" + +#include nsDiskCacheMap::nsDiskCacheMap() { @@ -35,33 +36,74 @@ nsDiskCacheMap::~nsDiskCacheMap() nsDiskCacheRecord* nsDiskCacheMap::GetRecord(PRUint32 hashNumber) { - PRUint32 index = (hashNumber & (kBucketsPerTable - 1)); - nsDiskCacheBucket& bucket = mBuckets[index]; + nsDiskCacheBucket& bucket = mBuckets[(hashNumber & (kBucketsPerTable - 1))]; nsDiskCacheRecord* oldestRecord = &bucket.mRecords[0]; - for (int i = 0; i < kRecordsPerBucket; ++i) { - nsDiskCacheRecord* record = &bucket.mRecords[i]; + for (int r = 0; r < kRecordsPerBucket; ++r) { + nsDiskCacheRecord* record = &bucket.mRecords[r]; if (record->HashNumber() == 0 || record->HashNumber() == hashNumber) return record; - if (record->EvictionRank() > oldestRecord->EvictionRank()) + if (record->EvictionRank() < oldestRecord->EvictionRank()) oldestRecord = record; } - - // record not found, so must evict a record. - oldestRecord->SetHashNumber(0); - oldestRecord->SetEvictionRank(0); + // if we don't find an empty record, return the oldest record for eviction. return oldestRecord; } +void nsDiskCacheMap::DeleteRecord(PRUint32 hashNumber) +{ + nsDiskCacheBucket& bucket = mBuckets[(hashNumber & (kBucketsPerTable - 1))]; + for (int r = 0; r < kRecordsPerBucket; ++r) { + nsDiskCacheRecord* record = &bucket.mRecords[r]; + if (record->HashNumber() == hashNumber) { + nsDiskCacheRecord* deletedRecord = record; + nsDiskCacheRecord* lastRecord = nsnull; + // XXX use binary search to find the end, much quicker. + // find the last record, to fill in the deleted record. + for (int j = r + 1; j < kRecordsPerBucket; ++j) { + record = &bucket.mRecords[j]; + if (record->HashNumber() == 0) { + lastRecord = record - 1; + break; + } + } + // copy the last record, to the newly deleted record. + if (lastRecord && deletedRecord != lastRecord) { + *deletedRecord = *lastRecord; + deletedRecord = lastRecord; + } + // mark record as free. + deletedRecord->SetHashNumber(0); + break; + } + } +} + nsresult nsDiskCacheMap::Read(nsIInputStream* input) { - // XXX need a header, etc. + nsresult rv; PRUint32 count; - nsresult rv = input->Read((char*)&mBuckets, sizeof(mBuckets), &count); + + // read the header. + rv = input->Read((char*)&mHeader, sizeof(mHeader), &count); + if (NS_FAILED(rv)) return rv; + mHeader.Unswap(); + + // validate the version. + if (mHeader.mVersion != nsDiskCacheHeader::kCurrentVersion) return NS_ERROR_FAILURE; + + // seek to beginning of first bucket. + nsCOMPtr seekable = do_QueryInterface(input, &rv); + if (NS_FAILED(rv)) return rv; + rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, sizeof(nsDiskCacheBucket)); + if (NS_FAILED(rv)) return rv; + + // read the buckets. + rv = input->Read((char*)&mBuckets[1], sizeof(mBuckets) - sizeof(nsDiskCacheBucket), &count); if (NS_FAILED(rv)) return rv; // unswap all of the active records. - for (int b = 0; b < kBucketsPerTable; ++b) { + for (int b = 1; b < kBucketsPerTable; ++b) { nsDiskCacheBucket& bucket = mBuckets[b]; for (int r = 0; r < kRecordsPerBucket; ++r) { nsDiskCacheRecord* record = &bucket.mRecords[r]; @@ -76,8 +118,12 @@ nsresult nsDiskCacheMap::Read(nsIInputStream* input) nsresult nsDiskCacheMap::Write(nsIOutputStream* output) { + nsresult rv; + PRUint32 count; + int b; + // swap all of the active records. - for (int b = 0; b < kBucketsPerTable; ++b) { + for (b = 1; b < kBucketsPerTable; ++b) { nsDiskCacheBucket& bucket = mBuckets[b]; for (int r = 0; r < kRecordsPerBucket; ++r) { nsDiskCacheRecord* record = &bucket.mRecords[r]; @@ -87,12 +133,11 @@ nsresult nsDiskCacheMap::Write(nsIOutputStream* output) } } - // XXX need a header, etc. - PRUint32 count; - nsresult rv = output->Write((char*)&mBuckets, sizeof(mBuckets), &count); + // write the buckets. + rv = output->Write((char*)&mBuckets, sizeof(mBuckets), &count); // unswap all of the active records. - for (int b = 0; b < kBucketsPerTable; ++b) { + for (b = 1; b < kBucketsPerTable; ++b) { nsDiskCacheBucket& bucket = mBuckets[b]; for (int r = 0; r < kRecordsPerBucket; ++r) { nsDiskCacheRecord* record = &bucket.mRecords[r]; @@ -101,6 +146,18 @@ nsresult nsDiskCacheMap::Write(nsIOutputStream* output) record->Unswap(); } } + if (NS_FAILED(rv)) return rv; + + // seek back to beginning of file. + nsCOMPtr seekable = do_QueryInterface(output, &rv); + if (NS_FAILED(rv)) return rv; + rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); + if (NS_FAILED(rv)) return rv; + + // write the header. + mHeader.Swap(); + rv = output->Write((char*)&mHeader, sizeof(mHeader), &count); + mHeader.Unswap(); return rv; } diff --git a/mozilla/netwerk/cache/src/nsDiskCacheMap.h b/mozilla/netwerk/cache/src/nsDiskCacheMap.h index 74e36d336b9..60b6bdffe8e 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheMap.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheMap.h @@ -29,26 +29,62 @@ class nsIInputStream; class nsIOutputStream; +struct nsDiskCacheHeader { + enum { kCurrentVersion = 0x00010000 }; + + PRUint32 mVersion; // cache version. + PRUint32 mDataSize; // size of cache in bytes. + PRUint32 mEntryCount; // number of entries stored in cache. + // XXX need a bitmap? + + nsDiskCacheHeader() + : mVersion(kCurrentVersion), mDataSize(0), mEntryCount(0) + { + } + + void Swap() + { + mVersion = ::PR_htonl(mVersion); + mDataSize = ::PR_htonl(mDataSize); + mEntryCount = ::PR_htonl(mEntryCount); + } + + void Unswap() + { + mVersion = ::PR_ntohl(mVersion); + mDataSize = ::PR_ntohl(mDataSize); + mEntryCount = ::PR_ntohl(mEntryCount); + } +}; + // XXX initial capacity, enough for 8192 distint entries. -const PRUint32 kRecordsPerBucket = 256; -const PRUint32 kBucketsPerTable = (1 << 4); // must be a power of 2! - class nsDiskCacheMap { public: nsDiskCacheMap(); ~nsDiskCacheMap(); + + PRUint32& DataSize() { return mHeader.mDataSize; } + + PRUint32& EntryCount() { return mHeader.mEntryCount; } nsDiskCacheRecord* GetRecord(PRUint32 hashNumber); + void DeleteRecord(PRUint32 hashNumber); nsresult Read(nsIInputStream* input); nsresult Write(nsIOutputStream* output); -private: - // XXX need a bitmap? - struct nsDiskCacheBucket { - nsDiskCacheRecord mRecords[kRecordsPerBucket]; + enum { + kRecordsPerBucket = 256, + kBucketsPerTable = (1 << 5) // must be a power of 2! }; - nsDiskCacheBucket mBuckets[kBucketsPerTable]; + +private: + struct nsDiskCacheBucket { + nsDiskCacheRecord mRecords[kRecordsPerBucket]; + }; + + nsDiskCacheHeader mHeader; + nsDiskCacheBucket mBuckets[kBucketsPerTable]; }; #endif // _nsDiskCacheMap_h_ diff --git a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp index d7a8130adef..f3a1833bd8c 100644 --- a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp +++ b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp @@ -119,6 +119,11 @@ nsMemoryCacheDevice::Init() return rv; } +nsresult +nsMemoryCacheDevice::Shutdown() +{ + return NS_OK; +} const char * nsMemoryCacheDevice::GetDeviceID() @@ -232,7 +237,8 @@ nsMemoryCacheDevice::GetTransportForEntry( nsCacheEntry * entry, (void **) transport); if (NS_FAILED(rv)) return rv; - return entry->SetData(*transport); + entry->SetData(*transport); + return NS_OK; } } @@ -344,6 +350,13 @@ nsMemoryCacheDevice::Visit(nsICacheVisitor * visitor) } +nsresult +nsMemoryCacheDevice::EvictEntries(const char * clientID) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + /****************************************************************************** * nsMemoryCacheDeviceInfo - for implementing about:cache *****************************************************************************/ diff --git a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h index 15f496bc286..2aee1dd1751 100644 --- a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h +++ b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h @@ -40,14 +40,15 @@ public: nsMemoryCacheDevice(); virtual ~nsMemoryCacheDevice(); - virtual nsresult Init(); + virtual nsresult Init(); + virtual nsresult Shutdown(); - virtual const char * GetDeviceID(void); + virtual const char * GetDeviceID(void); - virtual nsresult BindEntry( nsCacheEntry * entry ); - virtual nsCacheEntry * FindEntry( nsCString * key ); - virtual void DoomEntry( nsCacheEntry * entry ); - virtual nsresult DeactivateEntry( nsCacheEntry * entry ); + virtual nsresult BindEntry( nsCacheEntry * entry ); + virtual nsCacheEntry * FindEntry( nsCString * key ); + virtual void DoomEntry( nsCacheEntry * entry ); + virtual nsresult DeactivateEntry( nsCacheEntry * entry ); virtual nsresult GetTransportForEntry( nsCacheEntry * entry, nsCacheAccessMode mode, @@ -59,6 +60,8 @@ public: virtual nsresult OnDataSizeChange( nsCacheEntry * entry, PRInt32 deltaSize ); virtual nsresult Visit( nsICacheVisitor * visitor ); + + virtual nsresult EvictEntries(const char * clientID); static int PR_CALLBACK MemoryCacheSizeChanged(const char * pref, void * closure);