Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Private Types | Private Member Functions | Private Attributes | Friends
nsMemoryCacheDevice Class Reference

#include <nsMemoryCacheDevice.h>

Inheritance diagram for nsMemoryCacheDevice:
Inheritance graph
[legend]
Collaboration diagram for nsMemoryCacheDevice:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 nsMemoryCacheDevice ()
virtual ~nsMemoryCacheDevice ()
virtual nsresult Init ()
virtual nsresult Shutdown ()
virtual const char * GetDeviceID (void)
virtual nsresult BindEntry (nsCacheEntry *entry)
virtual nsCacheEntryFindEntry (nsCString *key, PRBool *collision)
virtual void DoomEntry (nsCacheEntry *entry)
virtual nsresult DeactivateEntry (nsCacheEntry *entry)
virtual nsresult OpenInputStreamForEntry (nsCacheEntry *entry, nsCacheAccessMode mode, PRUint32 offset, nsIInputStream **result)
virtual nsresult OpenOutputStreamForEntry (nsCacheEntry *entry, nsCacheAccessMode mode, PRUint32 offset, nsIOutputStream **result)
virtual nsresult GetFileForEntry (nsCacheEntry *entry, nsIFile **result)
virtual nsresult OnDataSizeChange (nsCacheEntry *entry, PRInt32 deltaSize)
virtual nsresult Visit (nsICacheVisitor *visitor)
virtual nsresult EvictEntries (const char *clientID)
 Device must evict entries associated with clientID.
void SetCapacity (PRInt32 capacity)

Private Types

enum  { DELETE_ENTRY = PR_TRUE, DO_NOT_DELETE_ENTRY = PR_FALSE }
enum  { kQueueCount = 24 }

Private Member Functions

void AdjustMemoryLimits (PRInt32 softLimit, PRInt32 hardLimit)
void EvictEntry (nsCacheEntry *entry, PRBool deleteEntry)
void EvictEntriesIfNecessary ()
int EvictionList (nsCacheEntry *entry, PRInt32 deltaSize)

Private Attributes

nsCacheEntryHashTable mMemCacheEntries
PRBool mInitialized
PRCList mEvictionList [kQueueCount]
PRInt32 mEvictionThreshold
PRInt32 mHardLimit
PRInt32 mSoftLimit
PRInt32 mTotalSize
PRInt32 mInactiveSize
PRInt32 mEntryCount
PRInt32 mMaxEntryCount

Friends

class nsMemoryCacheDeviceInfo

Detailed Description

Definition at line 55 of file nsMemoryCacheDevice.h.


Member Enumeration Documentation

anonymous enum [private]
Enumerator:
DELETE_ENTRY 
DO_NOT_DELETE_ENTRY 

Definition at line 94 of file nsMemoryCacheDevice.h.

anonymous enum [private]
Enumerator:
kQueueCount 

Definition at line 108 of file nsMemoryCacheDevice.h.

         {
        kQueueCount = 24   // entries > 2^23 (8Mb) start in last queue
    };

Constructor & Destructor Documentation

Definition at line 64 of file nsMemoryCacheDevice.cpp.

    : mInitialized(PR_FALSE),
      mEvictionThreshold(PR_INT32_MAX),
      mHardLimit(4 * 1024 * 1024),       // default, if no pref
      mSoftLimit((mHardLimit * 9) / 10), // default, if no pref
      mTotalSize(0),
      mInactiveSize(0),
      mEntryCount(0),
      mMaxEntryCount(0)
{
    for (int i=0; i<kQueueCount; ++i)
        PR_INIT_CLIST(&mEvictionList[i]);
}

Definition at line 79 of file nsMemoryCacheDevice.cpp.

{    
    Shutdown();
}

Here is the call graph for this function:


Member Function Documentation

void nsMemoryCacheDevice::AdjustMemoryLimits ( PRInt32  softLimit,
PRInt32  hardLimit 
) [private]

Definition at line 323 of file nsMemoryCacheDevice.cpp.

{
    mSoftLimit = softLimit;
    mHardLimit = hardLimit;

    // First, evict entries that won't fit into the new cache size.
    EvictEntriesIfNecessary();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsCacheDevice.

Definition at line 188 of file nsMemoryCacheDevice.cpp.

{
       if (!entry->IsDoomed()) {
           NS_ASSERTION(PR_CLIST_IS_EMPTY(entry),"entry is already on a list!");
       
              // append entry to the eviction list
        PR_APPEND_LINK(entry, &mEvictionList[EvictionList(entry, 0)]);

        // add entry to hashtable of mem cache entries
        nsresult  rv = mMemCacheEntries.AddEntry(entry);
        if (NS_FAILED(rv)) {
            PR_REMOVE_AND_INIT_LINK(entry);
            return rv;
        }
       }

    // add size of entry to memory totals
    ++mEntryCount;
    if (mMaxEntryCount < mEntryCount) mMaxEntryCount = mEntryCount;

    mTotalSize += entry->Size();
    EvictEntriesIfNecessary();
    
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsCacheDevice.

Definition at line 162 of file nsMemoryCacheDevice.cpp.

{
    if (entry->IsDoomed()) {
#ifdef DEBUG
        // XXX verify we've removed it from mMemCacheEntries & eviction list
#endif
        delete entry;
        return NS_OK;
    }

#ifdef DEBUG
    nsCacheEntry * ourEntry = mMemCacheEntries.GetEntry(entry->Key());
    NS_ASSERTION(ourEntry, "DeactivateEntry called for an entry we don't have!");
    NS_ASSERTION(entry == ourEntry, "entry doesn't match ourEntry");
    if (ourEntry != entry)
        return NS_ERROR_INVALID_POINTER;
#endif

    mInactiveSize += entry->Size();
    EvictEntriesIfNecessary();

    return NS_OK;
}

Here is the call graph for this function:

Implements nsCacheDevice.

Definition at line 216 of file nsMemoryCacheDevice.cpp.

{
#ifdef DEBUG
    // debug code to verify we have entry
    nsCacheEntry * hashEntry = mMemCacheEntries.GetEntry(entry->Key());
    if (!hashEntry)               NS_WARNING("no entry for key");
    else if (entry != hashEntry)  NS_WARNING("entry != hashEntry");
#endif

    EvictEntry(entry, DO_NOT_DELETE_ENTRY);
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsMemoryCacheDevice::EvictEntries ( const char *  clientID) [virtual]

Device must evict entries associated with clientID.

If clientID == nsnull, all entries must be evicted. Active entries must be doomed, rather than evicted.

Implements nsCacheDevice.

Definition at line 433 of file nsMemoryCacheDevice.cpp.

{
    nsCacheEntry * entry;
    PRUint32 prefixLength = (clientID ? strlen(clientID) : 0);

    for (int i = kQueueCount - 1; i >= 0; --i) {
        PRCList * elem = PR_LIST_HEAD(&mEvictionList[i]);
        while (elem != &mEvictionList[i]) {
            entry = (nsCacheEntry *)elem;
            elem = PR_NEXT_LINK(elem);
            
            const char * key = entry->Key()->get();
            if (clientID && nsCRT::strncmp(clientID, key, prefixLength) != 0)
                continue;
            
            if (entry->IsInUse()) {
                nsresult rv = nsCacheService::DoomEntry(entry);
                if (NS_FAILED(rv)) {
                    CACHE_LOG_WARNING(("memCache->EvictEntries() aborted: rv =%x", rv));
                    return rv;
                }
            } else {
                EvictEntry(entry, DELETE_ENTRY);
            }
        }
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 354 of file nsMemoryCacheDevice.cpp.

{
    nsCacheEntry * entry, * next;

    if ((mTotalSize < mHardLimit) && (mInactiveSize < mSoftLimit))
        return;

    for (int i = kQueueCount - 1; i >= 0; --i) {
        entry = (nsCacheEntry *)PR_LIST_HEAD(&mEvictionList[i]);
        while (entry != &mEvictionList[i]) {
            if (entry->IsInUse()) {
                entry = (nsCacheEntry *)PR_NEXT_LINK(entry);
                continue;
            }

            next = (nsCacheEntry *)PR_NEXT_LINK(entry);
            EvictEntry(entry, DELETE_ENTRY);
            entry = next;

            if ((mTotalSize < mHardLimit) && (mInactiveSize < mSoftLimit))
                return;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsMemoryCacheDevice::EvictEntry ( nsCacheEntry entry,
PRBool  deleteEntry 
) [private]

Definition at line 334 of file nsMemoryCacheDevice.cpp.

{
    // remove entry from our hashtable
    mMemCacheEntries.RemoveEntry(entry);
    
    // remove entry from the eviction list
    PR_REMOVE_AND_INIT_LINK(entry);
    
    // update statistics
    PRInt32 memoryRecovered = (PRInt32)entry->Size();
    mTotalSize    -= memoryRecovered;
    if (!entry->IsDoomed())
        mInactiveSize -= memoryRecovered;
    --mEntryCount;
    
    if (deleteEntry)  delete entry;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nsMemoryCacheDevice::EvictionList ( nsCacheEntry entry,
PRInt32  deltaSize 
) [private]

Definition at line 381 of file nsMemoryCacheDevice.cpp.

{
    // favor items which never expire by putting them in the lowest-index queue
    if (entry->ExpirationTime() == NO_EXPIRATION_TIME)
        return 0;

    // compute which eviction queue this entry should go into,
    // based on floor(log2(size/nref))
    PRInt32  size       = deltaSize + (PRInt32)entry->Size();
    PRInt32  fetchCount = PR_MAX(1, entry->FetchCount());

    return PR_MIN(PR_FloorLog2(size / fetchCount), kQueueCount - 1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsCacheEntry * nsMemoryCacheDevice::FindEntry ( nsCString key,
PRBool collision 
) [virtual]

Implements nsCacheDevice.

Definition at line 146 of file nsMemoryCacheDevice.cpp.

{
    nsCacheEntry * entry = mMemCacheEntries.GetEntry(key);
    if (!entry)  return nsnull;

    // move entry to the tail of an eviction list
    PR_REMOVE_AND_INIT_LINK(entry);
    PR_APPEND_LINK(entry, &mEvictionList[EvictionList(entry, 0)]);
    
    mInactiveSize -= entry->Size();

    return entry;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsCacheDevice.

Definition at line 139 of file nsMemoryCacheDevice.cpp.

{
    return gMemoryDeviceID;
}
nsresult nsMemoryCacheDevice::GetFileForEntry ( nsCacheEntry entry,
nsIFile **  result 
) [virtual]

Implements nsCacheDevice.

Definition at line 288 of file nsMemoryCacheDevice.cpp.

Implements nsCacheDevice.

Definition at line 86 of file nsMemoryCacheDevice.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsMemoryCacheDevice::OnDataSizeChange ( nsCacheEntry entry,
PRInt32  deltaSize 
) [virtual]

Implements nsCacheDevice.

Definition at line 296 of file nsMemoryCacheDevice.cpp.

{
    if (entry->IsStreamData()) {
        // we have the right to refuse or pre-evict
        PRUint32  newSize = entry->DataSize() + deltaSize;
        if ((PRInt32) newSize > mSoftLimit) {
            nsresult rv = nsCacheService::DoomEntry(entry);
            NS_ASSERTION(NS_SUCCEEDED(rv),"DoomEntry() failed.");
            return NS_ERROR_ABORT;
        }
    }

    // adjust our totals
    mTotalSize    += deltaSize;
    
    if (!entry->IsDoomed()) {
        // move entry to the tail of the appropriate eviction list
        PR_REMOVE_AND_INIT_LINK(entry);
        PR_APPEND_LINK(entry, &mEvictionList[EvictionList(entry, deltaSize)]);
    }

    EvictEntriesIfNecessary();
    return NS_OK;
}

Here is the call graph for this function:

Implements nsCacheDevice.

Definition at line 230 of file nsMemoryCacheDevice.cpp.

{
    NS_ENSURE_ARG_POINTER(entry);
    NS_ENSURE_ARG_POINTER(result);

    nsCOMPtr<nsIStorageStream> storage;
    nsresult rv;

    nsISupports *data = entry->Data();
    if (data) {
        storage = do_QueryInterface(data, &rv);
        if (NS_FAILED(rv))
            return rv;
    }
    else {
        rv = NS_NewStorageStream(4096, PRUint32(-1), getter_AddRefs(storage));
        if (NS_FAILED(rv))
            return rv;
        entry->SetData(storage);
    }

    return storage->NewInputStream(offset, result);
}

Here is the call graph for this function:

Implements nsCacheDevice.

Definition at line 259 of file nsMemoryCacheDevice.cpp.

{
    NS_ENSURE_ARG_POINTER(entry);
    NS_ENSURE_ARG_POINTER(result);

    nsCOMPtr<nsIStorageStream> storage;
    nsresult rv;

    nsISupports *data = entry->Data();
    if (data) {
        storage = do_QueryInterface(data, &rv);
        if (NS_FAILED(rv))
            return rv;
    }
    else {
        rv = NS_NewStorageStream(4096, PRUint32(-1), getter_AddRefs(storage));
        if (NS_FAILED(rv))
            return rv;
        entry->SetData(storage);
    }

    return storage->GetOutputStream(offset, result);
}

Here is the call graph for this function:

Definition at line 466 of file nsMemoryCacheDevice.cpp.

{
    PRInt32 hardLimit = capacity * 1024;  // convert k into bytes
    PRInt32 softLimit = (hardLimit * 9) / 10;
    AdjustMemoryLimits(softLimit, hardLimit);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsCacheDevice.

Definition at line 97 of file nsMemoryCacheDevice.cpp.

{
    NS_ASSERTION(mInitialized, "### attempting shutdown while not initialized");
    NS_ENSURE_TRUE(mInitialized, NS_ERROR_NOT_INITIALIZED);
    
    mMemCacheEntries.Shutdown();

    // evict all entries
    nsCacheEntry * entry, * next;

    for (int i = kQueueCount - 1; i >= 0; --i) {
        entry = (nsCacheEntry *)PR_LIST_HEAD(&mEvictionList[i]);
        while (entry != &mEvictionList[i]) {
            NS_ASSERTION(entry->IsInUse() == PR_FALSE, "### shutting down with active entries.\n");
            next = (nsCacheEntry *)PR_NEXT_LINK(entry);
            PR_REMOVE_AND_INIT_LINK(entry);
        
            // update statistics
            PRInt32 memoryRecovered = (PRInt32)entry->Size();
            mTotalSize    -= memoryRecovered;
            mInactiveSize -= memoryRecovered;
            --mEntryCount;

            delete entry;
            entry = next;
        }
    }

/*
 * we're not factoring in changes to meta data yet...    
 *  NS_ASSERTION(mTotalSize == 0, "### mem cache leaking entries?\n");
 */
    NS_ASSERTION(mInactiveSize == 0, "### mem cache leaking entries?\n");
    NS_ASSERTION(mEntryCount == 0, "### mem cache leaking entries?\n");
    
    mInitialized = PR_FALSE;

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Implements nsCacheDevice.

Definition at line 397 of file nsMemoryCacheDevice.cpp.

{
    nsMemoryCacheDeviceInfo * deviceInfo = new nsMemoryCacheDeviceInfo(this);
    nsCOMPtr<nsICacheDeviceInfo> deviceRef(deviceInfo);
    if (!deviceInfo) return NS_ERROR_OUT_OF_MEMORY;

    PRBool keepGoing;
    nsresult rv = visitor->VisitDevice(gMemoryDeviceID, deviceInfo, &keepGoing);
    if (NS_FAILED(rv)) return rv;

    if (!keepGoing)
        return NS_OK;

    nsCacheEntry *              entry;
    nsCOMPtr<nsICacheEntryInfo> entryRef;

    for (int i = kQueueCount - 1; i >= 0; --i) {
        entry = (nsCacheEntry *)PR_LIST_HEAD(&mEvictionList[i]);
        while (entry != &mEvictionList[i]) {
            nsCacheEntryInfo * entryInfo = new nsCacheEntryInfo(entry);
            if (!entryInfo) return NS_ERROR_OUT_OF_MEMORY;
            entryRef = entryInfo;

            rv = visitor->VisitEntry(gMemoryDeviceID, entryInfo, &keepGoing);
            entryInfo->DetachEntry();
            if (NS_FAILED(rv)) return rv;
            if (!keepGoing) break;

            entry = (nsCacheEntry *)PR_NEXT_LINK(entry);
        }
    }
    return NS_OK;
}

Here is the call graph for this function:


Friends And Related Function Documentation

friend class nsMemoryCacheDeviceInfo [friend]

Definition at line 93 of file nsMemoryCacheDevice.h.


Member Data Documentation

Definition at line 124 of file nsMemoryCacheDevice.h.

Definition at line 115 of file nsMemoryCacheDevice.h.

Definition at line 116 of file nsMemoryCacheDevice.h.

Definition at line 118 of file nsMemoryCacheDevice.h.

Definition at line 122 of file nsMemoryCacheDevice.h.

Definition at line 113 of file nsMemoryCacheDevice.h.

Definition at line 125 of file nsMemoryCacheDevice.h.

Definition at line 112 of file nsMemoryCacheDevice.h.

Definition at line 119 of file nsMemoryCacheDevice.h.

Definition at line 121 of file nsMemoryCacheDevice.h.


The documentation for this class was generated from the following files: