From 8d57282cf07e5f463c673bba8f2261227b2af5fb Mon Sep 17 00:00:00 2001 From: "gordon%netscape.com" Date: Tue, 13 Mar 2001 15:43:17 +0000 Subject: [PATCH] [not part of build] Implement simple LRU eviction mechanism for nsMemoryCacheDevice. Add cleanup code to nsCacheService to fix intermittent crashes on shutdown. Calculate MetaData size, and update field in nsCacheEntry. Begin implmentation of nsICacheDeviceInfo in nsMemoryCacheDevice for about:cache. Added various statistics to nsCacheService and nsMemoryCacheDevice. git-svn-id: svn://10.0.0.236/trunk@89508 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/netwerk/cache/src/nsCacheEntry.cpp | 51 +++--- mozilla/netwerk/cache/src/nsCacheEntry.h | 6 +- .../cache/src/nsCacheEntryDescriptor.h | 9 +- mozilla/netwerk/cache/src/nsCacheMetaData.cpp | 31 +++- mozilla/netwerk/cache/src/nsCacheMetaData.h | 2 + mozilla/netwerk/cache/src/nsCacheService.cpp | 95 ++++++++++- mozilla/netwerk/cache/src/nsCacheService.h | 18 ++ .../netwerk/cache/src/nsMemoryCacheDevice.cpp | 155 +++++++++++++++--- .../netwerk/cache/src/nsMemoryCacheDevice.h | 13 +- 9 files changed, 314 insertions(+), 66 deletions(-) diff --git a/mozilla/netwerk/cache/src/nsCacheEntry.cpp b/mozilla/netwerk/cache/src/nsCacheEntry.cpp index 0e9dddc293f..7e99aec2450 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntry.cpp +++ b/mozilla/netwerk/cache/src/nsCacheEntry.cpp @@ -85,13 +85,6 @@ nsCacheEntry::SetDataSize( PRUint32 size) MarkEntryDirty(); } -void -nsCacheEntry::SetMetaDataSize( PRUint32 size) -{ - mMetaSize = size; - mLastModified = ConvertPRTimeToSeconds(PR_Now()); - MarkEntryDirty(); -} nsresult nsCacheEntry::GetSecurityInfo( nsISupports ** result) @@ -149,13 +142,12 @@ nsCacheEntry::SetMetaDataElement( const nsAReadableCString& key, return NS_ERROR_OUT_OF_MEMORY; } nsresult rv = mMetaData->SetElement(key, value); - if (NS_SUCCEEDED(rv)) - MarkMetaDataDirty(); - - // XXX calc meta data size - - mLastModified = ConvertPRTimeToSeconds(PR_Now()); + if (NS_FAILED(rv)) + return rv; + mMetaSize = mMetaData->Size(); // calc new meta data size + mLastModified = ConvertPRTimeToSeconds(PR_Now()); // time stamp the entry + MarkMetaDataDirty(); // mark it dirty return rv; } @@ -304,9 +296,26 @@ nsCacheEntry::RemoveDescriptor(nsCacheEntryDescriptor * descriptor) } -/* +void +nsCacheEntry::DetachDescriptors(void) +{ + nsCacheEntryDescriptor * descriptor = + (nsCacheEntryDescriptor *)PR_LIST_HEAD(&mDescriptorQ); + + while (descriptor != &mDescriptorQ) { + nsCacheEntryDescriptor * next = + (nsCacheEntryDescriptor *)PR_NEXT_LINK(descriptor); + + descriptor->ClearCacheEntry(); + PR_REMOVE_AND_INIT_LINK(descriptor); + descriptor = next; + } +} + + +/****************************************************************************** * nsCacheEntryHashTable - */ + *****************************************************************************/ PLDHashTableOps nsCacheEntryHashTable::ops = @@ -373,7 +382,7 @@ nsCacheEntryHashTable::AddEntry( nsCacheEntry *cacheEntry) hashEntry = PL_DHashTableOperate(&table, cacheEntry->mKey, PL_DHASH_ADD); #ifndef DEBUG_dougt NS_ASSERTION(((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry == 0, - "nsCacheEntryHashTable::AddEntry - entry already used"); + "### nsCacheEntryHashTable::AddEntry - entry already used"); #endif ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry = cacheEntry; @@ -385,10 +394,13 @@ void nsCacheEntryHashTable::RemoveEntry( nsCacheEntry *cacheEntry) { NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized"); - NS_ASSERTION(cacheEntry, "cacheEntry == nsnull"); + NS_ASSERTION(cacheEntry, "### cacheEntry == nsnull"); +#if DEBUG // XXX debug code to make sure we have the entry we're trying to remove - + nsCacheEntry *check = GetEntry(cacheEntry->mKey); + NS_ASSERTION(check == cacheEntry, "### Attempting to remove unknown cache entry!!!"); +#endif (void) PL_DHashTableOperate(&table, cacheEntry->mKey, PL_DHASH_REMOVE); } @@ -433,7 +445,7 @@ nsCacheEntryHashTable::MatchEntry(PLDHashTable * /* table */, const PLDHashEntryHdr * hashEntry, const void * key) { - NS_ASSERTION(key != nsnull, "nsCacheEntryHashTable::MatchEntry : null key"); + NS_ASSERTION(key != nsnull, "### nsCacheEntryHashTable::MatchEntry : null key"); nsCacheEntry *cacheEntry = ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry; return nsStr::StrCompare(*cacheEntry->mKey, *(nsCString *)key, -1, PR_FALSE) == 0; @@ -459,6 +471,7 @@ nsCacheEntryHashTable::ClearEntry(PLDHashTable * /* table */, ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry = 0; } + void nsCacheEntryHashTable::Finalize(PLDHashTable * table) { diff --git a/mozilla/netwerk/cache/src/nsCacheEntry.h b/mozilla/netwerk/cache/src/nsCacheEntry.h index c63f063c7a5..35af61aedc3 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntry.h +++ b/mozilla/netwerk/cache/src/nsCacheEntry.h @@ -78,7 +78,8 @@ public: void SetDataSize( PRUint32 size); PRUint32 MetaDataSize(void) { return mMetaSize;} - void SetMetaDataSize( PRUint32 size); + + PRUint32 Size(void) { return mDataSize + mMetaSize; } nsCacheDevice * CacheDevice(void) { return mCacheDevice;} void SetCacheDevice( nsCacheDevice * device) { mCacheDevice = device;} @@ -158,6 +159,8 @@ private: friend class nsCacheEntryHashTable; friend class nsCacheService; + void DetachDescriptors(void); + // internal methods nsresult CommonOpen(nsCacheRequest * request, nsCacheAccessMode *accessGranted); void MarkDoomed() { mFlags |= eDoomedMask; } @@ -211,6 +214,7 @@ public: void VisitEntries( Visitor *visitor); private: + friend class nsCacheService; // XXX redefine interface so this isn't necessary // PLDHashTable operation callbacks static const void * GetKey( PLDHashTable *table, PLDHashEntryHdr *entry); diff --git a/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.h b/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.h index 7014ba45ead..2bccc25151e 100644 --- a/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.h +++ b/mozilla/netwerk/cache/src/nsCacheEntryDescriptor.h @@ -32,14 +32,14 @@ class nsCacheEntryDescriptor : public PRCList, public nsICacheEntryDescriptor - { +{ public: NS_DECL_ISUPPORTS NS_DECL_NSICACHEENTRYDESCRIPTOR nsCacheEntryDescriptor(nsCacheEntry * entry, nsCacheAccessMode mode); virtual ~nsCacheEntryDescriptor(); - + static nsresult Create(nsCacheEntry * entry, nsCacheAccessMode accessGranted, nsICacheEntryDescriptor ** result); @@ -48,11 +48,12 @@ public: * utility method to attempt changing data size of associated entry */ nsresult RequestDataSizeChange(PRInt32 deltaSize); - + /** * methods callbacks for nsCacheService */ - nsCacheEntry * CacheEntry(void) { return mCacheEntry; } + nsCacheEntry * CacheEntry(void) { return mCacheEntry; } + void ClearCacheEntry(void) { mCacheEntry = nsnull; } private: diff --git a/mozilla/netwerk/cache/src/nsCacheMetaData.cpp b/mozilla/netwerk/cache/src/nsCacheMetaData.cpp index 7700a9b11c8..8065bf9c267 100644 --- a/mozilla/netwerk/cache/src/nsCacheMetaData.cpp +++ b/mozilla/netwerk/cache/src/nsCacheMetaData.cpp @@ -110,37 +110,50 @@ nsCacheMetaData::SetElement(const nsAReadableCString& key, const nsAReadableCString& value) { nsCacheMetaDataHashTableEntry * metaEntry; + nsresult rv = NS_ERROR_OUT_OF_MEMORY; // presume the worst NS_ASSERTION(initialized, "nsCacheMetaDataHashTable not initialized"); // XXX need to copy string until we have scc's new flat string abstract class // XXX see nsCacheMetaData::HashKey below (bug 70075) nsCString * tempKey = new nsCString(key); - if (!tempKey) return NS_ERROR_OUT_OF_MEMORY; + if (!tempKey) return rv; // XXX should empty value remove the key? metaEntry = (nsCacheMetaDataHashTableEntry *) PL_DHashTableOperate(&table, tempKey, PL_DHASH_ADD); + if (!metaEntry) goto error_exit; + + if (metaEntry->key == nsnull) { metaEntry->key = new nsCString(key); if (metaEntry->key == nsnull) { - delete tempKey; - return NS_ERROR_OUT_OF_MEMORY; + goto error_exit; } } if (metaEntry->value != nsnull) - delete metaEntry->value; + delete metaEntry->value; // clear the old value metaEntry->value = new nsCString(value); if (metaEntry->value == nsnull) { // XXX remove key? - delete tempKey; - return NS_ERROR_OUT_OF_MEMORY; + goto error_exit; } + rv = NS_OK; + error_exit: delete tempKey; - return NS_OK; + return rv; +} + + +PRUint32 +nsCacheMetaData::Size(void) +{ + PRUint32 size = 0; + (void) PL_DHashTableEnumerate(&table, CalculateSize, &size); + return size; } @@ -204,9 +217,9 @@ nsCacheMetaData::MatchEntry(PLDHashTable * /* table */, const PLDHashEntryHdr * hashEntry, const void * key) { - NS_ASSERTION(key != nsnull, "nsCacheMetaDataHashTable::MatchEntry : null key"); + NS_ASSERTION(key != nsnull, "### nsCacheMetaDataHashTable::MatchEntry : null key"); nsCString * entryKey = ((nsCacheMetaDataHashTableEntry *)hashEntry)->key; - NS_ASSERTION(entryKey, "hashEntry->key == nsnull"); + NS_ASSERTION(entryKey, "### hashEntry->key == nsnull"); return entryKey->Equals(*NS_STATIC_CAST(const nsAReadableCString*,key)); } diff --git a/mozilla/netwerk/cache/src/nsCacheMetaData.h b/mozilla/netwerk/cache/src/nsCacheMetaData.h index 070a44bcdcc..7dd892a1e64 100644 --- a/mozilla/netwerk/cache/src/nsCacheMetaData.h +++ b/mozilla/netwerk/cache/src/nsCacheMetaData.h @@ -59,6 +59,8 @@ public: nsresult SetElement(const nsAReadableCString& key, const nsAReadableCString& value); + PRUint32 Size(void); + nsresult FlattenMetaData(char ** data, PRUint32 * size); nsresult UnflattenMetaData(char * data, PRUint32 size); diff --git a/mozilla/netwerk/cache/src/nsCacheService.cpp b/mozilla/netwerk/cache/src/nsCacheService.cpp index 7fe517d70c4..d64f9f87e08 100644 --- a/mozilla/netwerk/cache/src/nsCacheService.cpp +++ b/mozilla/netwerk/cache/src/nsCacheService.cpp @@ -48,6 +48,12 @@ nsCacheService::nsCacheService() : mCacheServiceLock(nsnull), mMemoryDevice(nsnull), mDiskDevice(nsnull), + mTotalEntries(0), + mCacheHits(0), + mCacheMisses(0), + mMaxKeyLength(0), + mMaxDataSize(0), + mMaxMetaSize(0), mDeactivateFailures(0), mDeactivatedUnboundEntries(0) { @@ -66,6 +72,9 @@ nsCacheService::~nsCacheService() (void) Shutdown(); gService = nsnull; +#if DEBUG + printf("### nsCacheService is now destroyed.\n"); +#endif } @@ -128,9 +137,16 @@ nsCacheService::Shutdown() "can't shutdown nsCacheService unless it has been initialized."); if (mCacheServiceLock) { - // XXX check for pending requests... + // XXX this is not sufficient + PRLock * tempLock = mCacheServiceLock; + mCacheServiceLock = nsnull; +#if DEBUG + printf("### beging nsCacheService::Shutdown()\n"); +#endif - // XXX finalize active entries + // Clear entries + ClearDoomList(); + ClearActiveEntries(); // deallocate memory and disk caches delete mMemoryDevice; @@ -139,8 +155,7 @@ nsCacheService::Shutdown() delete mDiskDevice; mDiskDevice = nsnull; - PR_DestroyLock(mCacheServiceLock); - mCacheServiceLock = nsnull; + PR_DestroyLock(tempLock); } return NS_OK; } @@ -219,7 +234,9 @@ nsCacheService::CreateRequest(nsCacheSession * session, nsLiteralCString(clientKey)); if (!key) return NS_ERROR_OUT_OF_MEMORY; - + + if (mMaxKeyLength < key->Length()) mMaxKeyLength = key->Length(); + // create request *request = new nsCacheRequest(key, listener, accessRequested, session); if (!*request) { @@ -384,6 +401,9 @@ nsCacheService::ActivateEntry(nsCacheRequest * request, if (entry) entry->MarkInitialized(); } + if (entry) ++mCacheHits; + else ++mCacheMisses; + if (!entry && !(request->AccessRequested() & nsICache::ACCESS_WRITE)) { // this is a READ-ONLY request rv = NS_ERROR_CACHE_KEY_NOT_FOUND; @@ -411,6 +431,8 @@ nsCacheService::ActivateEntry(nsCacheRequest * request, if (!entry) return NS_ERROR_OUT_OF_MEMORY; + ++mTotalEntries; + // XXX we could perform an early bind in some cases based on storage policy } @@ -590,7 +612,10 @@ void nsCacheService::DeactivateEntry(nsCacheEntry * entry) { nsresult rv = NS_OK; - NS_ASSERTION(entry->IsNotInUse(), "deactivating an entry while in use!"); + NS_ASSERTION(entry->IsNotInUse(), "### deactivating an entry while in use!"); + + if (mMaxDataSize < entry->DataSize() ) mMaxDataSize = entry->DataSize(); + if (mMaxMetaSize < entry->MetaDataSize() ) mMaxMetaSize = entry->MetaDataSize(); if (entry->IsDoomed()) { // remove from Doomed list @@ -689,6 +714,64 @@ nsCacheService::ProcessPendingRequests(nsCacheEntry * entry) return NS_OK; } + +void +nsCacheService::ClearPendingRequests(nsCacheEntry * entry) +{ + nsCacheRequest * request = (nsCacheRequest *)PR_LIST_HEAD(&entry->mRequestQ); + + while (request != &entry->mRequestQ) { + nsCacheRequest * next = (nsCacheRequest *)PR_NEXT_LINK(request); + + // XXX we're just dropping these on the floor for now...definitely wrong. + PR_REMOVE_AND_INIT_LINK(request); + delete request; + request = next; + } +} + + +void +nsCacheService::ClearDoomList() +{ + nsCacheEntry * entry = (nsCacheEntry *)PR_LIST_HEAD(&mDoomedEntries); + + while (entry != &mDoomedEntries) { + nsCacheEntry * next = (nsCacheEntry *)PR_NEXT_LINK(entry); + + entry->DetachDescriptors(); + DeactivateEntry(entry); + entry = next; + } +} + + +void +nsCacheService::ClearActiveEntries() +{ + // XXX really we want a different finalize callback for mActiveEntries + PL_DHashTableEnumerate(&mActiveEntries.table, DeactiveateAndClearEntry, nsnull); +} + + +PLDHashOperator +nsCacheService::DeactiveateAndClearEntry(PLDHashTable * table, + PLDHashEntryHdr * hdr, + PRUint32 number, + void * arg) +{ + nsCacheEntry * entry = ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry; + NS_ASSERTION(entry, "### active entry = nsnull!"); + gService->ClearPendingRequests(entry); + entry->DetachDescriptors(); + gService->DeactivateEntry(entry); + + ((nsCacheEntryHashTableEntry *)hdr)->keyHash = 1; // mark removed + ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry = nsnull; + return PL_DHASH_NEXT; +} + + NS_IMETHODIMP nsCacheService::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData) { return Shutdown(); diff --git a/mozilla/netwerk/cache/src/nsCacheService.h b/mozilla/netwerk/cache/src/nsCacheService.h index d2c61a32aaa..3c1e1fa3272 100644 --- a/mozilla/netwerk/cache/src/nsCacheService.h +++ b/mozilla/netwerk/cache/src/nsCacheService.h @@ -134,6 +134,16 @@ private: nsresult ProcessPendingRequests(nsCacheEntry * entry); + void ClearPendingRequests(nsCacheEntry * entry); + void ClearDoomList(void); + void ClearActiveEntries(void); + + static + PLDHashOperator DeactiveateAndClearEntry(PLDHashTable * table, + PLDHashEntryHdr * hdr, + PRUint32 number, + void * arg); + /** * Data Members */ @@ -153,6 +163,14 @@ private: nsCacheEntryHashTable mActiveEntries; PRCList mDoomedEntries; + // stats + PRUint32 mTotalEntries; + PRUint32 mCacheHits; + PRUint32 mCacheMisses; + PRUint32 mMaxKeyLength; + PRUint32 mMaxDataSize; + PRUint32 mMaxMetaSize; + // Unexpected error totals PRUint32 mDeactivateFailures; PRUint32 mDeactivatedUnboundEntries; diff --git a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp index ff2cf198cd4..4b7ad21cbad 100644 --- a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp +++ b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.cpp @@ -27,6 +27,8 @@ #include "nsNetCID.h" #include "nsIObserverService.h" #include "nsIPref.h" +#include "nsICacheVisitor.h" +#include "signal.h" static NS_DEFINE_CID(kStorageTransportCID, NS_STORAGETRANSPORT_CID); @@ -46,6 +48,9 @@ nsMemoryCacheDevice::nsMemoryCacheDevice() nsMemoryCacheDevice::~nsMemoryCacheDevice() { +#if DEBUG + printf("### starting ~nsMemoryCacheDevice()\n"); +#endif // XXX dealloc all memory nsresult rv; NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv); @@ -66,9 +71,11 @@ nsMemoryCacheDevice::MemoryCacheSizeChanged(const char * pref, void * closure) if (NS_FAILED(rv)) return rv; rv = prefs->GetIntPref(gMemoryCacheSizePref, (PRInt32 *)&softLimit); + if (NS_FAILED(rv)) return rv; + softLimit *= 1024; // convert k into bytes PRUint32 hardLimit = softLimit + 1024*1024*2; // XXX find better limit than +2Meg - rv = device->AdjustMemoryLimits(softLimit, hardLimit); + device->AdjustMemoryLimits(softLimit, hardLimit); return 0; // XXX what are we supposed to return? } @@ -80,16 +87,21 @@ nsMemoryCacheDevice::Init() nsresult rv; rv = mMemCacheEntries.Init(); + + // set some default memory limits, in case prefs aren't available + mSoftLimit = 1024 * 1024 * 3; + mHardLimit = mSoftLimit + 1024 *1024 * 2; - // XXX read user prefs for memory cache limits + // read user prefs for memory cache limits NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; + if (NS_SUCCEEDED(rv)) { - rv = prefs->RegisterCallback(gMemoryCacheSizePref, MemoryCacheSizeChanged, this); - if (NS_FAILED(rv)) return rv; + rv = prefs->RegisterCallback(gMemoryCacheSizePref, MemoryCacheSizeChanged, this); + if (NS_FAILED(rv)) return rv; - // Initialize the pref - MemoryCacheSizeChanged(gMemoryCacheSizePref, this); + // Initialize the pref + MemoryCacheSizeChanged(gMemoryCacheSizePref, this); + } // Register as a memory pressure observer NS_WITH_SERVICE(nsIObserverService, @@ -121,7 +133,9 @@ nsMemoryCacheDevice::FindEntry(nsCString * key) PR_REMOVE_AND_INIT_LINK(entry); PR_APPEND_LINK(entry, &mEvictionList); - return entry;; + mInactiveSize -= entry->Size(); + + return entry; } @@ -142,6 +156,9 @@ nsMemoryCacheDevice::DeactivateEntry(nsCacheEntry * entry) if (ourEntry != entry) return NS_ERROR_INVALID_POINTER; + mInactiveSize += entry->Size(); + EvictEntriesIfNecessary(); + return NS_OK; } @@ -161,7 +178,13 @@ nsMemoryCacheDevice::BindEntry(nsCacheEntry * entry) return rv; } - // XXX add size of entry to memory totals + // add size of entry to memory totals + ++mEntryCount; + if (mMaxEntryCount < mEntryCount) mMaxEntryCount = mEntryCount; + + mTotalSize += entry->Size(); + EvictEntriesIfNecessary(); + return NS_OK; } @@ -174,6 +197,10 @@ nsMemoryCacheDevice::DoomEntry(nsCacheEntry * entry) // remove entry from our eviction list PR_REMOVE_AND_INIT_LINK(entry); + + // adjust our totals + mTotalSize -= entry->Size(); + mInactiveSize -= entry->Size(); } @@ -217,7 +244,15 @@ nsMemoryCacheDevice::GetFileForEntry( nsCacheEntry * entry, nsresult nsMemoryCacheDevice::OnDataSizeChange( nsCacheEntry * entry, PRInt32 deltaSize) { - // XXX keep track of totals + if (entry->IsStreamData()) { + // we have the right to refuse or pre-evict + } + + // adjust our totals + mTotalSize += deltaSize; + + EvictEntriesIfNecessary(); + return NS_OK; } @@ -225,28 +260,29 @@ nsMemoryCacheDevice::OnDataSizeChange( nsCacheEntry * entry, PRInt32 deltaSize) nsresult nsMemoryCacheDevice::Visit(nsICacheVisitor * visitor) { + // visitor->VisitDevice(GetDeviceID(), deviceInfo); return NS_OK; } -nsresult +void nsMemoryCacheDevice::AdjustMemoryLimits(PRUint32 softLimit, PRUint32 hardLimit) { mSoftLimit = softLimit; mHardLimit = hardLimit; - - if ((mTotalSize > mHardLimit) || (mInactiveSize > softLimit)) { - // XXX rv = EvictEntries(); - } - return NS_OK; + EvictEntriesIfNecessary(); } -nsresult -nsMemoryCacheDevice::EvictEntries(void) +void +nsMemoryCacheDevice::EvictEntriesIfNecessary(void) { - nsCacheEntry * entry; - nsresult rv = NS_OK; + nsCacheEntry * entry, * next; + + if ((mTotalSize < mHardLimit) && (mInactiveSize < mSoftLimit)) + return; + + // XXX implement more sophisticated eviction ordering entry = (nsCacheEntry *)PR_LIST_HEAD(&mEvictionList); while (entry != &mEvictionList) { @@ -259,24 +295,97 @@ nsMemoryCacheDevice::EvictEntries(void) mMemCacheEntries.RemoveEntry(entry); // remove entry from the eviction list + next = (nsCacheEntry *)PR_NEXT_LINK(entry); PR_REMOVE_AND_INIT_LINK(entry); // update statistics - PRUint32 memoryRecovered = entry->DataSize() + entry->MetaDataSize(); + PRUint32 memoryRecovered = entry->Size(); mTotalSize -= memoryRecovered; mInactiveSize -= memoryRecovered; --mEntryCount; + delete entry; + entry = next; if ((mTotalSize < mHardLimit) && (mInactiveSize < mSoftLimit)) break; } +} + +/****************************************************************************** + * nsMemoryCacheDeviceInfo - for implementing about:cache + *****************************************************************************/ + +class nsMemoryCacheDeviceInfo : public nsICacheDeviceInfo { +public: + NS_DECL_ISUPPORTS + NS_DECL_NSICACHEDEVICEINFO + + nsMemoryCacheDeviceInfo(nsMemoryCacheDevice* device) + : mDevice(device) + { + NS_INIT_ISUPPORTS(); + } + + virtual ~nsMemoryCacheDeviceInfo() {} + +private: + nsMemoryCacheDevice* mDevice; +}; + + +NS_IMPL_ISUPPORTS1(nsMemoryCacheDeviceInfo, nsICacheDeviceInfo); + + +NS_IMETHODIMP +nsMemoryCacheDeviceInfo::GetDescription(char ** result) +{ + NS_ENSURE_ARG_POINTER(result); + *result = nsCRT::strdup("Memory cache device"); + if (!*result) return NS_ERROR_OUT_OF_MEMORY; return NS_OK; } - -// XXX need methods for enumerating entries +NS_IMETHODIMP +nsMemoryCacheDeviceInfo::GetUsageReport(char ** result) +{ + NS_ENSURE_ARG_POINTER(result); + *result = nsCRT::strdup("Memory cache usage report:"); + if (!*result) return NS_ERROR_OUT_OF_MEMORY; + return NS_OK; +} +NS_IMETHODIMP +nsMemoryCacheDeviceInfo::GetEntryCount(PRUint32 * result) +{ + NS_ENSURE_ARG_POINTER(result); + // XXX compare calculated count vs. mEntryCount + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsMemoryCacheDeviceInfo::GetTotalSize(PRUint32 * result) +{ + NS_ENSURE_ARG_POINTER(result); + // *aTotalSize = mDevice->getCacheSize(); + return NS_OK; +} + + +NS_IMETHODIMP +nsMemoryCacheDeviceInfo::GetMaximumSize(PRUint32 * result) +{ + NS_ENSURE_ARG_POINTER(result); + // *aMaximumSize = mDevice->getCacheCapacity(); + return NS_OK; +} + + +/****************************************************************************** + * nsMemoryCacheEntryInfo - for implementing about:cache + *****************************************************************************/ + diff --git a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h index de4d93a5824..75bd7558289 100644 --- a/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h +++ b/mozilla/netwerk/cache/src/nsMemoryCacheDevice.h @@ -29,6 +29,7 @@ #include "nsCacheEntry.h" +class nsMemoryCacheDeviceInfo; class nsMemoryCacheDevice : public nsCacheDevice { @@ -39,10 +40,11 @@ public: virtual nsresult Init(); virtual const char * GetDeviceID(void); - virtual nsCacheEntry * FindEntry( nsCString * key ); - 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, @@ -58,8 +60,9 @@ public: static int PR_CALLBACK MemoryCacheSizeChanged(const char * pref, void * closure); private: - nsresult AdjustMemoryLimits(PRUint32 softLimit, PRUint32 hardLimit); - nsresult EvictEntries(void); + friend class nsMemoryCacheDeviceInfo; + void AdjustMemoryLimits(PRUint32 softLimit, PRUint32 hardLimit); + void EvictEntriesIfNecessary(void); nsCacheEntryHashTable mMemCacheEntries; PRCList mEvictionList; @@ -77,4 +80,6 @@ private: }; + + #endif // _nsMemoryCacheDevice_h_