зеркало из https://github.com/mozilla/gecko-dev.git
[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.
This commit is contained in:
Родитель
506015d5ae
Коммит
a4e0ca3017
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
|
@ -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_
|
||||
|
|
Загрузка…
Ссылка в новой задаче