Back to index

lightning-sunbird  0.9+nobinonly
Public Member Functions | Static Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes
nsCacheService Class Reference

#include <nsCacheService.h>

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

List of all members.

Public Member Functions

NS_DECL_ISUPPORTS
NS_DECL_NSICACHESERVICE 
nsCacheService ()
virtual ~nsCacheService ()
nsresult Init ()
void Shutdown ()
nsICacheSession createSession (in string clientID, in nsCacheStoragePolicy storagePolicy, in boolean streamBased)
 Create a cache session.
void visitEntries (in nsICacheVisitor visitor)
 Visit entries stored in the cache.
void evictEntries (in nsCacheStoragePolicy storagePolicy)
 Evicts all entries in all devices implied by the storage policy.

Static Public Member Functions

static NS_METHOD Create (nsISupports *outer, const nsIID &iid, void **result)
static nsresult OpenCacheEntry (nsCacheSession *session, const nsACString &key, nsCacheAccessMode accessRequested, PRBool blockingMode, nsICacheListener *listener, nsICacheEntryDescriptor **result)
 Methods called by nsCacheSession.
static nsresult EvictEntriesForSession (nsCacheSession *session)
static nsresult IsStorageEnabledForPolicy (nsCacheStoragePolicy storagePolicy, PRBool *result)
static void CloseDescriptor (nsCacheEntryDescriptor *descriptor)
 Methods called by nsCacheEntryDescriptor.
static nsresult GetFileForEntry (nsCacheEntry *entry, nsIFile **result)
static nsresult OpenInputStreamForEntry (nsCacheEntry *entry, nsCacheAccessMode mode, PRUint32 offset, nsIInputStream **result)
static nsresult OpenOutputStreamForEntry (nsCacheEntry *entry, nsCacheAccessMode mode, PRUint32 offset, nsIOutputStream **result)
static nsresult OnDataSizeChange (nsCacheEntry *entry, PRInt32 deltaSize)
static PRLockServiceLock ()
static nsresult SetCacheElement (nsCacheEntry *entry, nsISupports *element)
static nsresult ValidateEntry (nsCacheEntry *entry)
static nsCacheServiceGlobalInstance ()
 Methods called by any cache classes.
static nsresult DoomEntry (nsCacheEntry *entry)
static void ProxyObjectRelease (nsISupports *object, PRThread *thread)
static PRBool IsStorageEnabledForPolicy_Locked (nsCacheStoragePolicy policy)
static void OnProfileShutdown (PRBool cleanse)
 Methods called by nsCacheProfilePrefObserver.
static void OnProfileChanged ()
static void SetDiskCacheEnabled (PRBool enabled)
static void SetDiskCacheCapacity (PRInt32 capacity)
static void SetMemoryCacheEnabled (PRBool enabled)
static void SetMemoryCacheCapacity (PRInt32 capacity)

Private Member Functions

nsresult CreateDiskDevice ()
 Internal Methods.
nsresult CreateMemoryDevice ()
nsresult CreateRequest (nsCacheSession *session, const nsACString &clientKey, nsCacheAccessMode accessRequested, PRBool blockingMode, nsICacheListener *listener, nsCacheRequest **request)
nsresult DoomEntry_Internal (nsCacheEntry *entry)
nsresult EvictEntriesForClient (const char *clientID, nsCacheStoragePolicy storagePolicy)
nsresult NotifyListener (nsCacheRequest *request, nsICacheEntryDescriptor *descriptor, nsCacheAccessMode accessGranted, nsresult error)
nsresult ActivateEntry (nsCacheRequest *request, nsCacheEntry **entry)
nsCacheDeviceEnsureEntryHasDevice (nsCacheEntry *entry)
nsCacheEntrySearchCacheDevices (nsCString *key, nsCacheStoragePolicy policy, PRBool *collision)
void DeactivateEntry (nsCacheEntry *entry)
nsresult ProcessRequest (nsCacheRequest *request, PRBool calledFromOpenCacheEntry, nsICacheEntryDescriptor **result)
nsresult ProcessPendingRequests (nsCacheEntry *entry)
void ClearPendingRequests (nsCacheEntry *entry)
void ClearDoomList (void)
void ClearActiveEntries (void)
void DoomActiveEntries (void)
PRInt32 CacheMemoryAvailable ()
 CacheMemoryAvailable.

Static Private Member Functions

static PLDHashOperator PR_CALLBACK DeactivateAndClearEntry (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void *arg)
static PLDHashOperator PR_CALLBACK RemoveActiveEntry (PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void *arg)

Private Attributes

nsCOMPtr< nsIEventQueueServicemEventQService
nsCOMPtr< nsIProxyObjectManagermProxyObjectManager
nsCacheProfilePrefObservermObserver
PRLockmCacheServiceLock
PRBool mInitialized
PRBool mEnableMemoryDevice
PRBool mEnableDiskDevice
nsMemoryCacheDevicemMemoryDevice
nsDiskCacheDevicemDiskDevice
nsCacheEntryHashTable mActiveEntries
PRCList mDoomedEntries
PRUint32 mTotalEntries
PRUint32 mCacheHits
PRUint32 mCacheMisses
PRUint32 mMaxKeyLength
PRUint32 mMaxDataSize
PRUint32 mMaxMetaSize
PRUint32 mDeactivateFailures
PRUint32 mDeactivatedUnboundEntries

Static Private Attributes

static nsCacheServicegService = nsnull
 Data Members.

Detailed Description

Definition at line 68 of file nsCacheService.h.


Constructor & Destructor Documentation

Definition at line 417 of file nsCacheService.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 443 of file nsCacheService.cpp.

{
    if (mInitialized) // Shutdown hasn't been called yet.
        (void) Shutdown();

    PR_DestroyLock(mCacheServiceLock);
    gService = nsnull;
}

Here is the call graph for this function:


Member Function Documentation

nsresult nsCacheService::ActivateEntry ( nsCacheRequest request,
nsCacheEntry **  entry 
) [private]

Definition at line 925 of file nsCacheService.cpp.

{
    nsresult        rv = NS_OK;

    NS_ASSERTION(request != nsnull, "ActivateEntry called with no request");
    if (result) *result = nsnull;
    if ((!request) || (!result))  return NS_ERROR_NULL_POINTER;

    // check if the request can be satisfied
    if (!mEnableMemoryDevice && !request->IsStreamBased())
        return NS_ERROR_FAILURE;
    if (!IsStorageEnabledForPolicy_Locked(request->StoragePolicy()))
        return NS_ERROR_FAILURE;

    // search active entries (including those not bound to device)
    nsCacheEntry *entry = mActiveEntries.GetEntry(request->mKey);

    if (!entry) {
        // search cache devices for entry
        PRBool collision = PR_FALSE;
        entry = SearchCacheDevices(request->mKey, request->StoragePolicy(), &collision);
        // When there is a hashkey collision just refuse to cache it...
        if (collision) return NS_ERROR_CACHE_IN_USE;

        if (entry)  entry->MarkInitialized();
    }

    if (entry) {
        ++mCacheHits;
        entry->Fetched();
    } else {
        ++mCacheMisses;
    }

    if (entry &&
        ((request->AccessRequested() == nsICache::ACCESS_WRITE) ||
         (entry->mExpirationTime <= SecondsFromPRTime(PR_Now()) &&
          request->WillDoomEntriesIfExpired())))
    {
        // this is FORCE-WRITE request or the entry has expired
        rv = DoomEntry_Internal(entry);
        if (NS_FAILED(rv)) {
            // XXX what to do?  Increment FailedDooms counter?
        }
        entry = nsnull;
    }

    if (!entry) {
        if (! (request->AccessRequested() & nsICache::ACCESS_WRITE)) {
            // this is a READ-ONLY request
            rv = NS_ERROR_CACHE_KEY_NOT_FOUND;
            goto error;
        }

        entry = new nsCacheEntry(request->mKey,
                                 request->IsStreamBased(),
                                 request->StoragePolicy());
        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
    }

    if (!entry->IsActive()) {
        rv = mActiveEntries.AddEntry(entry);
        if (NS_FAILED(rv)) goto error;
        entry->MarkActive();  // mark entry active, because it's now in mActiveEntries
    }
    *result = entry;
    return NS_OK;
    
 error:
    *result = nsnull;
    if (entry) {
        delete entry;
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

CacheMemoryAvailable.

If the browser.cache.memory.capacity preference is positive, we use that value for the amount of memory available for the cache.

If browser.cache.memory.capacity is zero, the memory cache is disabled.

If browser.cache.memory.capacity is negative or not present, we use a formula that grows less than linearly with the amount of system memory, with an upper limit on the cache size. No matter how much physical RAM is present, the default cache size would not exceed 32 MB. This maximum would apply only to systems with more than 4 GB of RAM (e.g. terminal servers)

RAM Cache


32 Mb 2 Mb 64 Mb 4 Mb 128 Mb 6 Mb 256 Mb 10 Mb 512 Mb 14 Mb 1024 Mb 18 Mb 2048 Mb 24 Mb 4096 Mb 30 Mb

The equation for this is (for cache size C and memory size K (kbytes)): C = x^2/3 + x + 2/3 + 0.1 (0.1 for rounding) if (C > 32) C = 32

Definition at line 1325 of file nsCacheService.cpp.

{
    PRInt32 capacity = mObserver->MemoryCacheCapacity();
    if (capacity >= 0)
        return capacity;

    PRUint64 bytes = PR_GetPhysicalMemorySize();

    if (LL_CMP(bytes, ==, LL_ZERO))
        return 0;

    // Conversion from unsigned int64 to double doesn't work on all platforms.
    // We need to truncate the value at LL_MAXINT to make sure we don't
    // overflow.
    if (LL_CMP(bytes, >, LL_MAXINT))
        bytes = LL_MAXINT;

    PRUint64 kbytes;
    LL_SHR(kbytes, bytes, 10);

    double kBytesD;
    LL_L2D(kBytesD, (PRInt64) kbytes);

    double x = log(kBytesD)/log(2.0) - 14;
    if (x > 0) {
        capacity = (PRInt32)(x * x / 3.0 + x + 2.0 / 3 + 0.1); // 0.1 for rounding
        if (capacity > 32)
            capacity = 32;
        capacity   *= 1024;
    } else {
        capacity    = 0;
    }

    return capacity;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1643 of file nsCacheService.cpp.

{
    // XXX really we want a different finalize callback for mActiveEntries
    PL_DHashTableEnumerate(&mActiveEntries.table, DeactivateAndClearEntry, nsnull);
    mActiveEntries.Shutdown();
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1628 of file nsCacheService.cpp.

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1612 of file nsCacheService.cpp.

{
    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;
    }
}

Here is the caller graph for this function:

Methods called by nsCacheEntryDescriptor.

Definition at line 1370 of file nsCacheService.cpp.

{
    // ask entry to remove descriptor
    nsCacheEntry * entry       = descriptor->CacheEntry();
    PRBool         stillActive = entry->RemoveDescriptor(descriptor);
    nsresult       rv          = NS_OK;

    if (!entry->IsValid()) {
        rv = gService->ProcessPendingRequests(entry);
    }

    if (!stillActive) {
        gService->DeactivateEntry(entry);
    }
}

Here is the call graph for this function:

NS_METHOD nsCacheService::Create ( nsISupports *  outer,
const nsIID iid,
void **  result 
) [static]

Definition at line 529 of file nsCacheService.cpp.

{
    nsresult  rv;

    if (aOuter != nsnull)
        return NS_ERROR_NO_AGGREGATION;

    nsCacheService * cacheService = new nsCacheService();
    if (cacheService == nsnull)
        return NS_ERROR_OUT_OF_MEMORY;

    NS_ADDREF(cacheService);
    rv = cacheService->Init();
    if (NS_SUCCEEDED(rv)) {
        rv = cacheService->QueryInterface(aIID, aResult);
    }
    NS_RELEASE(cacheService);
    return rv;
}

Here is the call graph for this function:

Internal Methods.

Definition at line 713 of file nsCacheService.cpp.

{
#ifdef NECKO_DISK_CACHE
    if (!mEnableDiskDevice) return NS_ERROR_NOT_AVAILABLE;
    if (mDiskDevice)        return NS_OK;

    mDiskDevice = new nsDiskCacheDevice;
    if (!mDiskDevice)       return NS_ERROR_OUT_OF_MEMORY;

    // set the preferences
    mDiskDevice->SetCacheParentDirectory(mObserver->DiskCacheParentDirectory());
    mDiskDevice->SetCapacity(mObserver->DiskCacheCapacity());
    
    nsresult rv = mDiskDevice->Init();
    if (NS_FAILED(rv)) {
#if DEBUG
        printf("###\n");
        printf("### mDiskDevice->Init() failed (0x%.8x)\n", rv);
        printf("###    - disabling disk cache for this session.\n");
        printf("###\n");
#endif        
        mEnableDiskDevice = PR_FALSE;
        delete mDiskDevice;
        mDiskDevice = nsnull;
    }
    return rv;
#else // !NECKO_DISK_CACHE
    NS_NOTREACHED("nsCacheService::CreateDiskDevice");
    return NS_ERROR_NOT_IMPLEMENTED;
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 747 of file nsCacheService.cpp.

{
    if (!mEnableMemoryDevice) return NS_ERROR_NOT_AVAILABLE;
    if (mMemoryDevice)        return NS_OK;

    mMemoryDevice = new nsMemoryCacheDevice;
    if (!mMemoryDevice)       return NS_ERROR_OUT_OF_MEMORY;
    
    // set preference
    mMemoryDevice->SetCapacity(CacheMemoryAvailable());

    nsresult rv = mMemoryDevice->Init();
    if (NS_FAILED(rv)) {
        NS_WARNING("Initialization of Memory Cache failed.");
        delete mMemoryDevice;
        mMemoryDevice = nsnull;
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsCacheService::CreateRequest ( nsCacheSession session,
const nsACString &  clientKey,
nsCacheAccessMode  accessRequested,
PRBool  blockingMode,
nsICacheListener listener,
nsCacheRequest **  request 
) [private]

Definition at line 769 of file nsCacheService.cpp.

{
    NS_ASSERTION(request, "CreateRequest: request is null");
     
    nsCString * key = new nsCString(*session->ClientID());
    if (!key)
        return NS_ERROR_OUT_OF_MEMORY;
    key->Append(':');
    key->Append(clientKey);

    if (mMaxKeyLength < key->Length()) mMaxKeyLength = key->Length();

    // create request
    *request = new  nsCacheRequest(key, listener, accessRequested, blockingMode, session);    
    if (!*request) {
        delete key;
        return NS_ERROR_OUT_OF_MEMORY;
    }

    if (!listener)  return NS_OK;  // we're sync, we're done.

    // get the nsIEventQueue for the request's thread
    (*request)->mThread = PR_GetCurrentThread();
    
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsICacheSession nsICacheService::createSession ( in string  clientID,
in nsCacheStoragePolicy  storagePolicy,
in boolean  streamBased 
) [inherited]

Create a cache session.

A cache session represents a client's access into the cache. The cache session is not "owned" by the cache service. Hence, it is possible to create duplicate cache sessions. Entries created by a cache session are invisible to other cache sessions, unless the cache sessions are equivalent.

Parameters:
clientID- Specifies the name of the client using the cache.
storagePolicy- Limits the storage policy for all entries accessed via the returned session. As a result, devices excluded by the storage policy will not be searched when opening entries from the returned session.
streamBased- Indicates whether or not the data being cached can be represented as a stream. The storagePolicy must be consistent with the value of this field. For example, a non-stream- based cache entry can only have a storage policy of STORE_IN_MEMORY.
Returns:
new cache session.
PLDHashOperator PR_CALLBACK nsCacheService::DeactivateAndClearEntry ( PLDHashTable table,
PLDHashEntryHdr hdr,
PRUint32  number,
void arg 
) [static, private]

Definition at line 1652 of file nsCacheService.cpp.

{
    nsCacheEntry * entry = ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry;
    NS_ASSERTION(entry, "### active entry = nsnull!");
    gService->ClearPendingRequests(entry);
    entry->DetachDescriptors();
    
    entry->MarkInactive();  // so we don't call Remove() while we're enumerating
    gService->DeactivateEntry(entry);
    
    return PL_DHASH_REMOVE; // and continue enumerating
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1471 of file nsCacheService.cpp.

{
    nsresult  rv = NS_OK;
    NS_ASSERTION(entry->IsNotInUse(), "### deactivating an entry while in use!");
    nsCacheDevice * device = nsnull;

    if (mMaxDataSize < entry->DataSize() )     mMaxDataSize = entry->DataSize();
    if (mMaxMetaSize < entry->MetaDataSize() ) mMaxMetaSize = entry->MetaDataSize();

    if (entry->IsDoomed()) {
        // remove from Doomed list
        PR_REMOVE_AND_INIT_LINK(entry);
    } else if (entry->IsActive()) {
        // remove from active entries
        mActiveEntries.RemoveEntry(entry);
        entry->MarkInactive();

        // bind entry if necessary to store meta-data
        device = EnsureEntryHasDevice(entry); 
        if (!device) {
            NS_WARNING("DeactivateEntry: unable to bind active entry\n");
            return;
        }
    } else {
        // if mInitialized == PR_FALSE,
        // then we're shutting down and this state is okay.
        NS_ASSERTION(!mInitialized, "DeactivateEntry: bad cache entry state.");
    }

    device = entry->CacheDevice();
    if (device) {
        rv = device->DeactivateEntry(entry);
        if (NS_FAILED(rv)) {
            // increment deactivate failure count
            ++mDeactivateFailures;
        }
    } else {
        // increment deactivating unbound entry statistic
        ++mDeactivatedUnboundEntries;
        delete entry; // because no one else will
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1670 of file nsCacheService.cpp.

{
    nsAutoVoidArray array;

    PL_DHashTableEnumerate(&mActiveEntries.table, RemoveActiveEntry, &array);

    PRUint32 count = array.Count();
    for (PRUint32 i=0; i < count; ++i)
        DoomEntry_Internal((nsCacheEntry *) array[i]);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1085 of file nsCacheService.cpp.

{
    return gService->DoomEntry_Internal(entry);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1092 of file nsCacheService.cpp.

{
    if (entry->IsDoomed())  return NS_OK;
    
    nsresult  rv = NS_OK;
    entry->MarkDoomed();
    
    NS_ASSERTION(!entry->IsBinding(), "Dooming entry while binding device.");
    nsCacheDevice * device = entry->CacheDevice();
    if (device)  device->DoomEntry(entry);

    if (entry->IsActive()) {
        // remove from active entries
        mActiveEntries.RemoveEntry(entry);
        entry->MarkInactive();
     }

    // put on doom list to wait for descriptors to close
    NS_ASSERTION(PR_CLIST_IS_EMPTY(entry), "doomed entry still on device list");
    PR_APPEND_LINK(entry, &mDoomedEntries);

    // tell pending requests to get on with their lives...
    rv = ProcessPendingRequests(entry);
    
    // All requests have been removed, but there may still be open descriptors
    if (entry->IsNotInUse()) {
        DeactivateEntry(entry); // tell device to get rid of it
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1042 of file nsCacheService.cpp.

{
    nsCacheDevice * device = entry->CacheDevice();
    if (device)  return device;

#ifdef NECKO_DISK_CACHE
    if (entry->IsStreamData() && entry->IsAllowedOnDisk() && mEnableDiskDevice) {
        // this is the default
        if (!mDiskDevice) {
            (void)CreateDiskDevice();  // ignore the error (check for mDiskDevice instead)
        }

        if (mDiskDevice) {
            entry->MarkBinding();  // enter state of binding
            nsresult rv = mDiskDevice->BindEntry(entry);
            entry->ClearBinding(); // exit state of binding
            if (NS_SUCCEEDED(rv))
                device = mDiskDevice;
        }
    }
#endif // !NECKO_DISK_CACHE
     
    // if we can't use mDiskDevice, try mMemoryDevice
    if (!device && mEnableMemoryDevice && entry->IsAllowedInMemory()) {        
        if (!mMemoryDevice) {
            (void)CreateMemoryDevice();  // ignore the error (check for mMemoryDevice instead)
        }
        if (mMemoryDevice) {
            entry->MarkBinding();  // enter state of binding
            nsresult rv = mMemoryDevice->BindEntry(entry);
            entry->ClearBinding(); // exit state of binding
            if (NS_SUCCEEDED(rv))
                device = mMemoryDevice;
        }
    }

    if (device) 
        entry->SetCacheDevice(device);
    return device;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Evicts all entries in all devices implied by the storage policy.

nsresult nsCacheService::EvictEntriesForClient ( const char *  clientID,
nsCacheStoragePolicy  storagePolicy 
) [private]

Definition at line 579 of file nsCacheService.cpp.

{
    if (this == nsnull) return NS_ERROR_NOT_AVAILABLE; // XXX eh?

    nsCOMPtr<nsIObserverService> obsSvc =
        do_GetService("@mozilla.org/observer-service;1");
    if (obsSvc) {
        // Proxy to the UI thread since the observer service isn't thredsafe.
        // We use an async proxy, since this it's not important whether this
        // notification happens before or after the actual eviction.

        nsCOMPtr<nsIObserverService> obsProxy;
        NS_GetProxyForObject(NS_UI_THREAD_EVENTQ,
                             NS_GET_IID(nsIObserverService),
                             obsSvc, PROXY_ASYNC, getter_AddRefs(obsProxy));

        if (obsProxy) {
            obsProxy->NotifyObservers(this,
                                      NS_CACHESERVICE_EMPTYCACHE_TOPIC_ID,
                                      nsnull);
        }
    }

    nsAutoLock lock(mCacheServiceLock);
    nsresult rv = NS_OK;

#ifdef NECKO_DISK_CACHE
    if (storagePolicy == nsICache::STORE_ANYWHERE ||
        storagePolicy == nsICache::STORE_ON_DISK) {

        if (mEnableDiskDevice) {
            if (!mDiskDevice) {
                rv = CreateDiskDevice();
                if (NS_FAILED(rv)) return rv;
            }
            rv = mDiskDevice->EvictEntries(clientID);
            if (NS_FAILED(rv)) return rv;
        }
    }
#endif // !NECKO_DISK_CACHE

    if (storagePolicy == nsICache::STORE_ANYWHERE ||
        storagePolicy == nsICache::STORE_IN_MEMORY) {

        // If there is no memory device, there is no need to evict it...
        if (mMemoryDevice) {
            rv = mMemoryDevice->EvictEntries(clientID);
            if (NS_FAILED(rv)) return rv;
        }
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 570 of file nsCacheService.cpp.

{
    NS_ASSERTION(gService, "nsCacheService::gService is null.");
    return gService->EvictEntriesForClient(session->ClientID()->get(),
                                 session->StoragePolicy());
}

Here is the call graph for this function:

nsresult nsCacheService::GetFileForEntry ( nsCacheEntry entry,
nsIFile **  result 
) [static]

Definition at line 1388 of file nsCacheService.cpp.

{
    nsCacheDevice * device = gService->EnsureEntryHasDevice(entry);
    if (!device)  return  NS_ERROR_UNEXPECTED;
    
    return device->GetFileForEntry(entry, result);
}

Here is the call graph for this function:

static nsCacheService* nsCacheService::GlobalInstance ( ) [inline, static]

Methods called by any cache classes.

Definition at line 130 of file nsCacheService.h.

{ return gService; }

Here is the caller graph for this function:

Definition at line 454 of file nsCacheService.cpp.

{
    NS_ASSERTION(!mInitialized, "nsCacheService already initialized.");
    if (mInitialized)
        return NS_ERROR_ALREADY_INITIALIZED;

    if (mCacheServiceLock == nsnull)
        return NS_ERROR_OUT_OF_MEMORY;

    CACHE_LOG_INIT();

    // initialize hashtable for active cache entries
    nsresult rv = mActiveEntries.Init();
    if (NS_FAILED(rv)) return rv;
    
    // get references to services we'll be using frequently
    mEventQService = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
    if (NS_FAILED(rv)) return rv;
    
    mProxyObjectManager = do_GetService(NS_XPCOMPROXY_CONTRACTID, &rv);
    if (NS_FAILED(rv)) return rv;

    // create profile/preference observer
    mObserver = new nsCacheProfilePrefObserver();
    if (!mObserver)  return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(mObserver);
    
    mObserver->Install();
    mEnableDiskDevice =   mObserver->DiskCacheEnabled();
    mEnableMemoryDevice = mObserver->MemoryCacheEnabled();

    rv = CreateMemoryDevice();
    if (NS_FAILED(rv) && (rv != NS_ERROR_NOT_AVAILABLE))
        return rv;
    
    mInitialized = PR_TRUE;
    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 636 of file nsCacheService.cpp.

Here is the call graph for this function:

Definition at line 648 of file nsCacheService.cpp.

{
    if (gService->mEnableMemoryDevice &&
        (storagePolicy == nsICache::STORE_ANYWHERE ||
         storagePolicy == nsICache::STORE_IN_MEMORY)) {
        return PR_TRUE;
    }
    if (gService->mEnableDiskDevice &&
        (storagePolicy == nsICache::STORE_ANYWHERE ||
         storagePolicy == nsICache::STORE_ON_DISK  ||
         storagePolicy == nsICache::STORE_ON_DISK_AS_FILE)) {
        return PR_TRUE;
    }
    
    return PR_FALSE;
}

Here is the caller graph for this function:

nsresult nsCacheService::NotifyListener ( nsCacheRequest request,
nsICacheEntryDescriptor descriptor,
nsCacheAccessMode  accessGranted,
nsresult  error 
) [private]

Definition at line 803 of file nsCacheService.cpp.

{
    nsresult rv;

    nsCOMPtr<nsICacheListener> listenerProxy;
    NS_ASSERTION(request->mThread, "no thread set in async request!");
    nsCOMPtr<nsIEventQueue> eventQ;
    mEventQService->GetThreadEventQueue(request->mThread,
                                        getter_AddRefs(eventQ));
    rv = mProxyObjectManager->GetProxyForObject(eventQ,
                                                NS_GET_IID(nsICacheListener),
                                                request->mListener,
                                                PROXY_ASYNC|PROXY_ALWAYS,
                                                getter_AddRefs(listenerProxy));
    if (NS_FAILED(rv)) return rv;

    return listenerProxy->OnCacheEntryAvailable(descriptor, accessGranted, error);
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsCacheService::OnDataSizeChange ( nsCacheEntry entry,
PRInt32  deltaSize 
) [static]

Definition at line 1424 of file nsCacheService.cpp.

{
    nsCacheDevice * device = gService->EnsureEntryHasDevice(entry);
    if (!device)  return  NS_ERROR_UNEXPECTED;

    return device->OnDataSizeChange(entry, deltaSize);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1191 of file nsCacheService.cpp.

{
    if (!gService)  return;
 
    nsresult   rv = NS_OK;
    nsAutoLock lock(gService->mCacheServiceLock);
    
    gService->mEnableDiskDevice   = gService->mObserver->DiskCacheEnabled();
    gService->mEnableMemoryDevice = gService->mObserver->MemoryCacheEnabled();
    
    if (gService->mEnableMemoryDevice && !gService->mMemoryDevice) {
        (void) gService->CreateMemoryDevice();
    }

#ifdef NECKO_DISK_CACHE
    if (gService->mDiskDevice) {
        gService->mDiskDevice->SetCacheParentDirectory(gService->mObserver->DiskCacheParentDirectory());
        gService->mDiskDevice->SetCapacity(gService->mObserver->DiskCacheCapacity());

        // XXX initialization of mDiskDevice could be made lazily, if mEnableDiskDevice is false
        rv = gService->mDiskDevice->Init();
        if (NS_FAILED(rv)) {
            NS_ERROR("nsCacheService::OnProfileChanged: Re-initializing disk device failed");
            gService->mEnableDiskDevice = PR_FALSE;
            // XXX delete mDiskDevice?
        }
    }
#endif // !NECKO_DISK_CACHE
    
    if (gService->mMemoryDevice) {
        gService->mMemoryDevice->SetCapacity(gService->CacheMemoryAvailable());
        rv = gService->mMemoryDevice->Init();
        if (NS_FAILED(rv) && (rv != NS_ERROR_ALREADY_INITIALIZED)) {
            NS_ERROR("nsCacheService::OnProfileChanged: Re-initializing memory device failed");
            gService->mEnableMemoryDevice = PR_FALSE;
            // XXX delete mMemoryDevice?
        }
    }
}

Here is the call graph for this function:

Methods called by nsCacheProfilePrefObserver.

Definition at line 1164 of file nsCacheService.cpp.

{
    if (!gService)  return;
    nsAutoLock lock(gService->mCacheServiceLock);

    gService->DoomActiveEntries();
    gService->ClearDoomList();

#ifdef NECKO_DISK_CACHE
    if (gService->mDiskDevice && gService->mEnableDiskDevice) {
        if (cleanse)
            gService->mDiskDevice->EvictEntries(nsnull);

        gService->mDiskDevice->Shutdown();
        gService->mEnableDiskDevice = PR_FALSE;
    }
#endif // !NECKO_DISK_CACHE

    if (gService->mMemoryDevice) {
        // clear memory cache
        gService->mMemoryDevice->EvictEntries(nsnull);
    }

}

Here is the call graph for this function:

nsresult nsCacheService::OpenCacheEntry ( nsCacheSession session,
const nsACString &  key,
nsCacheAccessMode  accessRequested,
PRBool  blockingMode,
nsICacheListener listener,
nsICacheEntryDescriptor **  result 
) [static]

Methods called by nsCacheSession.

Definition at line 892 of file nsCacheService.cpp.

{
    NS_ASSERTION(gService, "nsCacheService::gService is null.");
    if (result)
        *result = nsnull;

    nsCacheRequest * request = nsnull;

    nsAutoLock lock(gService->mCacheServiceLock);
    nsresult rv = gService->CreateRequest(session,
                                          key,
                                          accessRequested,
                                          blockingMode,
                                          listener,
                                          &request);
    if (NS_FAILED(rv))  return rv;

    rv = gService->ProcessRequest(request, PR_TRUE, result);

    // delete requests that have completed
    if (!(listener && (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION)))
        delete request;

    return rv;
}

Here is the call graph for this function:

Definition at line 1399 of file nsCacheService.cpp.

{
    nsCacheDevice * device = gService->EnsureEntryHasDevice(entry);
    if (!device)  return  NS_ERROR_UNEXPECTED;

    return device->OpenInputStreamForEntry(entry, mode, offset, result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1411 of file nsCacheService.cpp.

{
    nsCacheDevice * device = gService->EnsureEntryHasDevice(entry);
    if (!device)  return  NS_ERROR_UNEXPECTED;

    return device->OpenOutputStreamForEntry(entry, mode, offset, result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1516 of file nsCacheService.cpp.

{
    nsresult            rv = NS_OK;
    nsCacheRequest *    request = (nsCacheRequest *)PR_LIST_HEAD(&entry->mRequestQ);
    nsCacheRequest *    nextRequest;
    PRBool              newWriter = PR_FALSE;
    
    if (request == &entry->mRequestQ)  return NS_OK;    // no queued requests

    if (!entry->IsDoomed() && entry->IsInvalid()) {
        // 1st descriptor closed w/o MarkValid()
        NS_ASSERTION(PR_CLIST_IS_EMPTY(&entry->mDescriptorQ), "shouldn't be here with open descriptors");

#if DEBUG
        // verify no ACCESS_WRITE requests(shouldn't have any of these)
        while (request != &entry->mRequestQ) {
            NS_ASSERTION(request->AccessRequested() != nsICache::ACCESS_WRITE,
                         "ACCESS_WRITE request should have been given a new entry");
            request = (nsCacheRequest *)PR_NEXT_LINK(request);
        }
        request = (nsCacheRequest *)PR_LIST_HEAD(&entry->mRequestQ);        
#endif
        // find first request with ACCESS_READ_WRITE (if any) and promote it to 1st writer
        while (request != &entry->mRequestQ) {
            if (request->AccessRequested() == nsICache::ACCESS_READ_WRITE) {
                newWriter = PR_TRUE;
                break;
            }

            request = (nsCacheRequest *)PR_NEXT_LINK(request);
        }
        
        if (request == &entry->mRequestQ)   // no requests asked for ACCESS_READ_WRITE, back to top
            request = (nsCacheRequest *)PR_LIST_HEAD(&entry->mRequestQ);
        
        // XXX what should we do if there are only READ requests in queue?
        // XXX serialize their accesses, give them only read access, but force them to check validate flag?
        // XXX or do readers simply presume the entry is valid
    }

    nsCacheAccessMode  accessGranted = nsICache::ACCESS_NONE;

    while (request != &entry->mRequestQ) {
        nextRequest = (nsCacheRequest *)PR_NEXT_LINK(request);

        if (request->mListener) {

            // Async request
            PR_REMOVE_AND_INIT_LINK(request);

            if (entry->IsDoomed()) {
                rv = ProcessRequest(request, PR_FALSE, nsnull);
                if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION)
                    rv = NS_OK;
                else
                    delete request;

                if (NS_FAILED(rv)) {
                    // XXX what to do?
                }
            } else if (entry->IsValid() || newWriter) {
                rv = entry->RequestAccess(request, &accessGranted);
                NS_ASSERTION(NS_SUCCEEDED(rv),
                             "if entry is valid, RequestAccess must succeed.");
                // XXX if (newWriter)  NS_ASSERTION( accessGranted == request->AccessRequested(), "why not?");

                // entry->CreateDescriptor dequeues request, and queues descriptor
                nsCOMPtr<nsICacheEntryDescriptor> descriptor;
                rv = entry->CreateDescriptor(request,
                                             accessGranted,
                                             getter_AddRefs(descriptor));
                
                // post call to listener to report error or descriptor
                rv = NotifyListener(request, descriptor, accessGranted, rv);
                delete request;
                if (NS_FAILED(rv)) {
                    // XXX what to do?
                }
                
            } else {
                // XXX bad state
            }
        } else {

            // Synchronous request
            request->WakeUp();
        }
        if (newWriter)  break;  // process remaining requests after validation
        request = nextRequest;
    }

    return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsCacheService::ProcessRequest ( nsCacheRequest request,
PRBool  calledFromOpenCacheEntry,
nsICacheEntryDescriptor **  result 
) [private]

Definition at line 827 of file nsCacheService.cpp.

{
    // !!! must be called with mCacheServiceLock held !!!
    nsresult           rv;
    nsCacheEntry *     entry = nsnull;
    nsCacheAccessMode  accessGranted = nsICache::ACCESS_NONE;
    if (result) *result = nsnull;

    while(1) {  // Activate entry loop
        rv = ActivateEntry(request, &entry);  // get the entry for this request
        if (NS_FAILED(rv))  break;

        while(1) { // Request Access loop
            NS_ASSERTION(entry, "no entry in Request Access loop!");
            // entry->RequestAccess queues request on entry
            rv = entry->RequestAccess(request, &accessGranted);
            if (rv != NS_ERROR_CACHE_WAIT_FOR_VALIDATION) break;
            
            if (request->mListener) // async exits - validate, doom, or close will resume
                return rv;
            
            if (request->IsBlocking()) {
                PR_Unlock(mCacheServiceLock);
                rv = request->WaitForValidation();
                PR_Lock(mCacheServiceLock);
            }

            PR_REMOVE_AND_INIT_LINK(request);
            if (NS_FAILED(rv)) break;   // non-blocking mode returns WAIT_FOR_VALIDATION error
            // okay, we're ready to process this request, request access again
        }
        if (rv != NS_ERROR_CACHE_ENTRY_DOOMED)  break;

        if (entry->IsNotInUse()) {
            // this request was the last one keeping it around, so get rid of it
            DeactivateEntry(entry);
        }
        // loop back around to look for another entry
    }

    nsCOMPtr<nsICacheEntryDescriptor> descriptor;
    
    if (NS_SUCCEEDED(rv))
        rv = entry->CreateDescriptor(request, accessGranted, getter_AddRefs(descriptor));

    if (request->mListener) {  // Asynchronous
    
        if (NS_FAILED(rv) && calledFromOpenCacheEntry)
            return rv;  // skip notifying listener, just return rv to caller
            
        // call listener to report error or descriptor
        nsresult rv2 = NotifyListener(request, descriptor, accessGranted, rv);
        if (NS_FAILED(rv2) && NS_SUCCEEDED(rv)) {
            rv = rv2;  // trigger delete request
        }
    } else {        // Synchronous
        NS_IF_ADDREF(*result = descriptor);
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsCacheService::ProxyObjectRelease ( nsISupports *  object,
PRThread thread 
) [static]

Definition at line 1141 of file nsCacheService.cpp.

{
    NS_ASSERTION(gService, "nsCacheService not initialized");
    NS_ASSERTION(thread, "no thread");
    // XXX if thread == current thread, we could avoid posting an event,
    // XXX by add this object to a queue and release it when the cache service is unlocked.
    
    nsCOMPtr<nsIEventQueue> eventQ;
    gService->mEventQService->GetThreadEventQueue(thread, getter_AddRefs(eventQ));
    NS_ASSERTION(eventQ, "no event queue for thread");
    if (!eventQ)  return;
    
    PLEvent * event = new PLEvent;
    if (!event) {
        NS_WARNING("failed to allocate a PLEvent.");
        return;
    }
    PL_InitEvent(event, object, EventHandler, DestroyHandler);
    eventQ->PostEvent(event);
}

Here is the call graph for this function:

Here is the caller graph for this function:

PLDHashOperator PR_CALLBACK nsCacheService::RemoveActiveEntry ( PLDHashTable table,
PLDHashEntryHdr hdr,
PRUint32  number,
void arg 
) [static, private]

Definition at line 1683 of file nsCacheService.cpp.

{
    nsCacheEntry * entry = ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry;
    NS_ASSERTION(entry, "### active entry = nsnull!");

    nsVoidArray * array = (nsVoidArray *) arg;
    NS_ASSERTION(array, "### array = nsnull!");
    array->AppendElement(entry);

    // entry is being removed from the active entry list
    entry->MarkInactive();
    return PL_DHASH_REMOVE; // and continue enumerating
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsCacheEntry * nsCacheService::SearchCacheDevices ( nsCString key,
nsCacheStoragePolicy  policy,
PRBool collision 
) [private]

Definition at line 1010 of file nsCacheService.cpp.

{
    nsCacheEntry * entry = nsnull;

    *collision = PR_FALSE;
    if ((policy == nsICache::STORE_ANYWHERE) || (policy == nsICache::STORE_IN_MEMORY)) {
        // If there is no memory device, then there is nothing to search...
        if (mMemoryDevice)
            entry = mMemoryDevice->FindEntry(key, collision);
    }

    if (!entry && 
        ((policy == nsICache::STORE_ANYWHERE) || (policy == nsICache::STORE_ON_DISK))) {

#ifdef NECKO_DISK_CACHE
        if (mEnableDiskDevice) {
            if (!mDiskDevice) {
                nsresult rv = CreateDiskDevice();
                if (NS_FAILED(rv))
                    return nsnull;
            }
            
            entry = mDiskDevice->FindEntry(key, collision);
        }
#endif // !NECKO_DISK_CACHE
    }

    return entry;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1434 of file nsCacheService.cpp.

{
    NS_ASSERTION(gService, "nsCacheService::gService is null.");
    return gService->mCacheServiceLock;
}

Here is the caller graph for this function:

nsresult nsCacheService::SetCacheElement ( nsCacheEntry entry,
nsISupports *  element 
) [static]

Definition at line 1442 of file nsCacheService.cpp.

{
    entry->SetThread(PR_GetCurrentThread());
    entry->SetData(element);
    entry->TouchData();
    return NS_OK;
}

Here is the call graph for this function:

Definition at line 1242 of file nsCacheService.cpp.

{
    if (!gService)  return;
    nsAutoLock lock(gService->mCacheServiceLock);

#ifdef NECKO_DISK_CACHE
    if (gService->mDiskDevice) {
        gService->mDiskDevice->SetCapacity(capacity);
    }
#endif // !NECKO_DISK_CACHE
    
    gService->mEnableDiskDevice = gService->mObserver->DiskCacheEnabled();
}

Here is the call graph for this function:

Definition at line 1233 of file nsCacheService.cpp.

{
    if (!gService)  return;
    nsAutoLock lock(gService->mCacheServiceLock);
    gService->mEnableDiskDevice = enabled;
}

Definition at line 1258 of file nsCacheService.cpp.

{
    if (!gService)  return;
    nsAutoLock lock(gService->mCacheServiceLock);
    gService->mEnableMemoryDevice = enabled;

    if (enabled) {
        if (!gService->mMemoryDevice) {
            // allocate memory device, if necessary
            (void) gService->CreateMemoryDevice();
        }
    } else {
        if (gService->mMemoryDevice) {
            // tell memory device to evict everything
            gService->mMemoryDevice->SetCapacity(0);
        }
    }
}

Here is the call graph for this function:

Definition at line 495 of file nsCacheService.cpp.

{
    nsAutoLock  lock(mCacheServiceLock);
    NS_ASSERTION(mInitialized, 
                 "can't shutdown nsCacheService unless it has been initialized.");

    if (mInitialized) {

        mInitialized = PR_FALSE;

        mObserver->Remove();
        NS_RELEASE(mObserver);
        
        // Clear entries
        ClearDoomList();
        ClearActiveEntries();

        // deallocate memory and disk caches
        delete mMemoryDevice;
        mMemoryDevice = nsnull;

#ifdef NECKO_DISK_CACHE
        delete mDiskDevice;
        mDiskDevice = nsnull;

#if defined(PR_LOGGING)
        LogCacheStatistics();
#endif
#endif
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 1452 of file nsCacheService.cpp.

{
    nsCacheDevice * device = gService->EnsureEntryHasDevice(entry);
    if (!device)  return  NS_ERROR_UNEXPECTED;

    entry->MarkValid();
    nsresult rv = gService->ProcessPendingRequests(entry);
    NS_ASSERTION(rv == NS_OK, "ProcessPendingRequests failed.");
    // XXX what else should be done?

    return rv;
}

Here is the call graph for this function:

Visit entries stored in the cache.

Used to implement about:cache.


Member Data Documentation

Data Members.

Definition at line 217 of file nsCacheService.h.

Definition at line 233 of file nsCacheService.h.

Definition at line 239 of file nsCacheService.h.

Definition at line 240 of file nsCacheService.h.

Definition at line 223 of file nsCacheService.h.

Definition at line 247 of file nsCacheService.h.

Definition at line 246 of file nsCacheService.h.

Definition at line 231 of file nsCacheService.h.

PRCList nsCacheService::mDoomedEntries [private]

Definition at line 234 of file nsCacheService.h.

Definition at line 228 of file nsCacheService.h.

Definition at line 227 of file nsCacheService.h.

Definition at line 218 of file nsCacheService.h.

Definition at line 225 of file nsCacheService.h.

Definition at line 242 of file nsCacheService.h.

Definition at line 241 of file nsCacheService.h.

Definition at line 243 of file nsCacheService.h.

Definition at line 230 of file nsCacheService.h.

Definition at line 221 of file nsCacheService.h.

Definition at line 219 of file nsCacheService.h.

Definition at line 238 of file nsCacheService.h.


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