[not part of build]

Fixed cache meta data. Implemented eviction list for memory cache device. Worked on entry deactivation, validation, and doom.


git-svn-id: svn://10.0.0.236/trunk@88364 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
gordon%netscape.com 2001-03-02 01:51:41 +00:00
parent 56da764588
commit 383d3db210
9 changed files with 153 additions and 118 deletions

View File

@ -67,9 +67,8 @@ nsCacheEntry::nsCacheEntry(nsCString * key,
nsCacheEntry::~nsCacheEntry()
{
if (mCacheDevice) {
//** ask device to clean up
}
delete mKey;
delete mMetaData;
}
@ -105,12 +104,9 @@ nsCacheEntry::SetMetaDataElement( const nsAReadableCString& key,
const nsAReadableCString& value)
{
if (!mMetaData) {
mMetaData = new nsCacheMetaData();
mMetaData = nsCacheMetaData::Create();
if (!mMetaData)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mMetaData->Init();
if (NS_FAILED(rv))
return rv;
}
nsresult rv = mMetaData->SetElement(key, value);
if (NS_SUCCEEDED(rv))
@ -135,15 +131,6 @@ nsCacheEntry::GetKeyValueArray(nsCacheMetaDataKeyValuePair ** array,
}
void
nsCacheEntry::MarkValid()
{
//** bind if not bound
//** convert pending requests to descriptors, etc.
mFlags |= eValidMask;
}
/**
* cache entry states
* 0 descriptors (new entry)

View File

@ -103,16 +103,20 @@ public:
};
void MarkDoomed() { mFlags |= eDoomedMask; }
void MarkEntryDirty() { mFlags |= eEntryDirtyMask; }
void MarkDataDirty() { mFlags |= eDataDirtyMask; }
void MarkMetaDataDirty() { mFlags |= eMetaDataDirtyMask; }
void MarkStreamData() { mFlags |= eStreamDataMask; }
void MarkActive() { mFlags |= eActiveMask; }
void MarkDoomed() { mFlags |= eDoomedMask; }
void MarkEntryDirty() { mFlags |= eEntryDirtyMask; }
void MarkEntryClean() { mFlags &= ~eEntryDirtyMask; }
void MarkDataDirty() { mFlags |= eDataDirtyMask; }
void MarkDataClean() { mFlags &= ~eDataDirtyMask; }
void MarkMetaDataDirty() { mFlags |= eMetaDataDirtyMask; }
void MarkMetaDataClean() { mFlags &= ~eMetaDataDirtyMask; }
void MarkStreamData() { mFlags |= eStreamDataMask; }
void MarkActive() { mFlags |= eActiveMask; }
void MarkInactive() { mFlags &= ~eActiveMask; }
void MarkValid();
void MarkAllowedInMemory() { mFlags |= eAllowedInMemoryMask; }
void MarkAllowedOnDisk() { mFlags |= eAllowedOnDiskMask; }
void MarkValid() { mFlags |= eValidMask; }
void MarkInvalid() { mFlags &= ~eValidMask; }
void MarkAllowedInMemory() { mFlags |= eAllowedInMemoryMask; }
void MarkAllowedOnDisk() { mFlags |= eAllowedOnDiskMask; }
PRBool IsDoomed() { return (mFlags & eDoomedMask) != 0; }
PRBool IsEntryDirty() { return (mFlags & eEntryDirtyMask) != 0; }

View File

@ -316,17 +316,13 @@ nsCacheEntryDescriptor::GetMetaDataElement(const char *key, char ** result)
if (NS_SUCCEEDED(rv) && (value)) {
*result = ToNewCString(*value);
if (!*result) rv = NS_ERROR_OUT_OF_MEMORY;
else {
NS_ASSERTION(PR_FALSE, "FindCharInRead failed to find ':'");
rv = NS_ERROR_UNEXPECTED;
}
}
return rv;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetMetadataElement(const char *key, const char *value)
nsCacheEntryDescriptor::SetMetaDataElement(const char *key, const char *value)
{
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;

View File

@ -68,17 +68,41 @@ nsCacheMetaData::Init()
}
nsCacheMetaData *
nsCacheMetaData::Create()
{
nsCacheMetaData * metaData = new nsCacheMetaData();
if (!metaData)
return nsnull;
nsresult rv = metaData->Init();
if (NS_FAILED(rv)) {
delete metaData;
return nsnull;
}
return metaData;
}
nsAReadableCString *
nsCacheMetaData::GetElement(const nsAReadableCString * key)
{
PLDHashEntryHdr * hashEntry;
nsCString * result = nsnull;
//** need to copy string until we have scc's new flat string abstract class
//** see nsCacheMetaData::HashKey below (bug 70075)
nsCString * tempKey = new nsCString(*key);
if (!tempKey) return result;
NS_ASSERTION(initialized, "nsCacheMetaDataHashTable not initialized");
hashEntry = PL_DHashTableOperate(&table, key, PL_DHASH_LOOKUP);
hashEntry = PL_DHashTableOperate(&table, tempKey, PL_DHASH_LOOKUP);
if (PL_DHASH_ENTRY_IS_BUSY(hashEntry)) {
result = ((nsCacheMetaDataHashTableEntry *)hashEntry)->value;
}
delete tempKey;
return result;
}
@ -87,29 +111,38 @@ nsresult
nsCacheMetaData::SetElement(const nsAReadableCString& key,
const nsAReadableCString& value)
{
nsCacheMetaDataHashTableEntry * metaEntry;
nsCacheMetaDataHashTableEntry * metaEntry;
NS_ASSERTION(initialized, "nsCacheMetaDataHashTable not initialized");
NS_ASSERTION(initialized, "nsCacheMetaDataHashTable not initialized");
//** should empty value remove the key?
//** need to copy string until we have scc's new flat string abstract class
//** see nsCacheMetaData::HashKey below (bug 70075)
nsCString * tempKey = new nsCString(key);
if (!tempKey) return NS_ERROR_OUT_OF_MEMORY;
metaEntry = (nsCacheMetaDataHashTableEntry *)
PL_DHashTableOperate(&table, &key, PL_DHASH_ADD);
if (metaEntry->key == nsnull) {
metaEntry->key = new nsCString(key);
if (metaEntry->key == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
if (metaEntry->value != nsnull)
delete metaEntry->value;
//** should empty value remove the key?
metaEntry->value = new nsCString(value);
if (metaEntry->value == nsnull) {
//** remove key?
return NS_ERROR_OUT_OF_MEMORY;
}
metaEntry = (nsCacheMetaDataHashTableEntry *)
PL_DHashTableOperate(&table, tempKey, PL_DHASH_ADD);
if (metaEntry->key == nsnull) {
metaEntry->key = new nsCString(key);
if (metaEntry->key == nsnull) {
delete tempKey;
return NS_ERROR_OUT_OF_MEMORY;
}
}
if (metaEntry->value != nsnull)
delete metaEntry->value;
return NS_OK;
metaEntry->value = new nsCString(value);
if (metaEntry->value == nsnull) {
//** remove key?
delete tempKey;
return NS_ERROR_OUT_OF_MEMORY;
}
delete tempKey;
return NS_OK;
}
@ -144,6 +177,7 @@ nsCacheMetaData::GetKey( PLDHashTable * /* table */, PLDHashEntryHdr *hashEntry)
return ((nsCacheMetaDataHashTableEntry *)hashEntry)->key;
}
PLDHashNumber
nsCacheMetaData::HashKey( PLDHashTable * table, const void *key)
{
@ -151,6 +185,7 @@ nsCacheMetaData::HashKey( PLDHashTable * table, const void *key)
return PL_DHashStringKey(table, ((nsCString *)key)->get());
}
PRBool
nsCacheMetaData::MatchEntry(PLDHashTable * /* table */,
const PLDHashEntryHdr * hashEntry,
@ -159,7 +194,8 @@ nsCacheMetaData::MatchEntry(PLDHashTable * /* table */,
NS_ASSERTION(key != nsnull, "nsCacheMetaDataHashTable::MatchEntry : null key");
nsCString * entryKey = ((nsCacheMetaDataHashTableEntry *)hashEntry)->key;
NS_ASSERTION(entryKey, "hashEntry->key == nsnull");
return nsStr::StrCompare(*(nsCString *)key, *entryKey, -1, PR_FALSE) == 0;
return entryKey->Equals(*NS_STATIC_CAST(const nsAReadableCString*,key));
}

View File

@ -48,8 +48,11 @@ class nsCacheMetaData {
public:
nsCacheMetaData();
~nsCacheMetaData();
nsresult Init();
static
nsCacheMetaData * Create(void);
nsresult Init(void);
nsAReadableCString * GetElement(const nsAReadableCString * key);

View File

@ -39,7 +39,9 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheService, nsICacheService)
nsCacheService::nsCacheService()
: mCacheServiceLock(nsnull),
mMemoryDevice(nsnull),
mDiskDevice(nsnull)
mDiskDevice(nsnull),
mDeactivateFailures(0),
mDeactivatedUnboundEntries(0)
{
NS_INIT_REFCNT();
@ -371,6 +373,17 @@ nsCacheService::BindEntry(nsCacheEntry * entry)
}
nsresult
nsCacheService::ValidateEntry(nsCacheEntry * entry)
{
//** bind if not bound
//** convert pending requests to descriptors, etc.
entry->MarkValid();
return NS_OK;
}
nsresult
nsCacheService::DoomEntry(nsCacheEntry * entry)
{
@ -463,15 +476,26 @@ nsCacheService::CloseDescriptor(nsCacheEntryDescriptor * descriptor)
void
nsCacheService::DeactivateEntry(nsCacheEntry * entry)
{
//** check if entry is doomed
//** remove from hashtable
nsresult rv = NS_OK;
if (entry->IsDoomed()) {
// remove from Doomed list
PR_REMOVE_AND_INIT_LINK(entry->GetListNode());
} else {
// remove from active entries
rv = mActiveEntries.RemoveEntry(entry);
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to remove an active entry !?!");
}
nsCacheDevice * device = entry->CacheDevice();
if (device) {
nsresult rv = device->DeactivateEntry(entry);
rv = device->DeactivateEntry(entry);
if (NS_FAILED(rv)) {
//** what do we do on errors?
// increment deactivate failure count
++mDeactivateFailures;
}
} else {
//** increment deactivating unbound entry statistic
// increment deactivating unbound entry statistic
++mDeactivatedUnboundEntries;
}
}

View File

@ -73,6 +73,8 @@ public:
nsresult OnDataSizeChange(nsCacheEntry * entry, PRInt32 deltaSize);
nsresult ValidateEntry(nsCacheEntry * entry);
nsresult GetTransportForEntry(nsCacheEntry * entry,
nsCacheAccessMode mode,
nsITransport ** result);
@ -128,6 +130,10 @@ private:
// nsCacheClientHashTable mClientIDs;
nsCacheEntryHashTable mActiveEntries;
PRCList mDoomedEntries;
// Unexpected error totals
PRUint32 mDeactivateFailures;
PRUint32 mDeactivatedUnboundEntries;
};

View File

@ -43,7 +43,7 @@ nsMemoryCacheDevice::Init()
{
nsresult rv;
rv = mInactiveEntries.Init();
rv = mMemCacheEntries.Init();
//** read user prefs for memory cache limits
@ -61,12 +61,14 @@ nsMemoryCacheDevice::GetDeviceID()
nsCacheEntry *
nsMemoryCacheDevice::FindEntry(nsCString * key)
{
nsCacheEntry * entry = mInactiveEntries.GetEntry(key);
nsCacheEntry * entry = mMemCacheEntries.GetEntry(key);
if (!entry) return nsnull;
//** need entry->UpdateFrom(ourEntry);
entry->MarkActive(); // so we don't evict it
//** find eviction element and move it to the tail of the queue
// move entry to the tail of the eviction list
PR_REMOVE_AND_INIT_LINK(entry->GetListNode());
PR_APPEND_LINK(entry->GetListNode(), &mEvictionList);
return entry;;
}
@ -75,25 +77,39 @@ nsMemoryCacheDevice::FindEntry(nsCString * key)
nsresult
nsMemoryCacheDevice::DeactivateEntry(nsCacheEntry * entry)
{
nsCString * key = entry->Key();
if (entry->IsDoomed()) {
#if debug
//** verify we've removed it from mMemCacheEntries & eviction list
#endif
delete entry;
return NS_OK;
}
nsCacheEntry * ourEntry = mInactiveEntries.GetEntry(key);
nsCacheEntry * ourEntry = mMemCacheEntries.GetEntry(entry->Key());
NS_ASSERTION(ourEntry, "DeactivateEntry called for an entry we don't have!");
if (!ourEntry)
NS_ASSERTION(entry == ourEntry, "entry doesn't match ourEntry");
if (ourEntry != entry)
return NS_ERROR_INVALID_POINTER;
//** need ourEntry->UpdateFrom(entry);
//** MarkInactive(); // to make it evictable again
return NS_ERROR_NOT_IMPLEMENTED;
entry->MarkInactive(); // to make it evictable again
return NS_OK;
}
nsresult
nsMemoryCacheDevice::BindEntry(nsCacheEntry * entry)
{
nsresult rv = mInactiveEntries.AddEntry(entry);
if (NS_FAILED(rv))
NS_ASSERTION(PR_CLIST_IS_EMPTY(entry->GetListNode()),"entry is already on a list!");
// append entry to the eviction list
PR_APPEND_LINK(entry->GetListNode(), &mEvictionList);
// add entry to hashtable of mem cache entries
nsresult rv = mMemCacheEntries.AddEntry(entry);
if (NS_FAILED(rv)) {
PR_REMOVE_AND_INIT_LINK(entry->GetListNode());
return rv;
}
//** add size of entry to memory totals
return NS_OK;
@ -103,7 +119,14 @@ nsMemoryCacheDevice::BindEntry(nsCacheEntry * entry)
nsresult
nsMemoryCacheDevice::DoomEntry(nsCacheEntry * entry)
{
return NS_ERROR_NOT_IMPLEMENTED;
nsresult rv = mMemCacheEntries.RemoveEntry(entry);
NS_ASSERTION(NS_SUCCEEDED(rv), "dooming entry that we don't have");
if (NS_FAILED(rv)) return rv;
// remove entry from our eviction list
PR_REMOVE_AND_INIT_LINK(entry->GetListNode());
return NS_OK;
}

View File

@ -51,10 +51,10 @@ public:
virtual nsresult OnDataSizeChange( nsCacheEntry * entry, PRInt32 deltaSize );
private:
nsCacheEntryHashTable mInactiveEntries;
nsCacheEntryHashTable mMemCacheEntries;
PRUint32 mTemporaryMaxLimit;
PRUint32 mNormalMaxLimit;
PRUint32 mHardLimit;
PRUint32 mSoftLimit;
PRUint32 mCurrentTotal;
PRCList mEvictionList;
@ -62,49 +62,5 @@ private:
//** what other stats do we want to keep?
};
#if 0
class nsMemoryCacheEntry
{
public:
nsMemoryCacheEntry(nsCacheEntry *entry)
{
PR_INIT_CLIST(&mListLink);
entry->GetKey(&mKey);
GetFetchCount(&mFetchCount);
GetLastFetched(&mLastFetched);
GetLastValidated(&mLastValidated);
GetExpirationTime(&mExpirationTime);
//** flags
GetDataSize(&mDataSize);
GetMetaDataSize(&mMetaSize);
GetData(getter_AddRefs(mData)); //** check about ownership
GetMetaData
}
~nsMemoryCacheEntry() {}
PRCList * GetListNode(void) { return &mListLink; }
static nsMemoryCacheEntry * GetInstance(PRCList * qp) {
return (nsMemoryCacheEntry*)((char*)qp -
offsetof(nsMemoryCacheEntry, mListLink));
}
private:
PRCList mListLink; // 8
nsCString * mKey; // 4 //** ask scc about const'ness
PRUint32 mFetchCount; // 4
PRTime mLastFetched; // 8
PRTime mLastValidated; // 8
PRTime mExpirationTime; // 8
PRUint32 mFlags; // 4
PRUint32 mDataSize; // 4
PRUint32 mMetaSize; // 4
nsCOMPtr<nsISupports> mData; // 4 //** issues with updating/replacing
nsCacheMetaData * mMetaData; // 4
};
#endif
#endif // _nsMemoryCacheDevice_h_