Added rough cut of pref code for memory cache device to get cache size, and implemented simple eviction method.

Restructured nsCacheEntryDescriptor to add SecurityInfo attribute.  Created nsTransportWrapper as nested class (and member) that addrefs the descriptor instead of itself (like nsPipe).  Also rename nsCacheOutputStream to nsOutputStreamWrapper and made it a nested class as well.
This commit is contained in:
gordon%netscape.com 2001-03-07 09:27:36 +00:00
Родитель 3bc7a8b81e
Коммит acd18fda01
6 изменённых файлов: 455 добавлений и 214 удалений

21
netwerk/cache/src/nsCacheEntry.cpp поставляемый
Просмотреть файл

@ -76,6 +76,22 @@ nsCacheEntry::~nsCacheEntry()
delete mMetaData;
}
nsresult
nsCacheEntry::GetSecurityInfo( nsISupports ** result)
{
NS_ENSURE_ARG_POINTER(result);
NS_IF_ADDREF(*result = mSecurityInfo);
return NS_OK;
}
nsresult
nsCacheEntry::SetSecurityInfo( nsISupports * info)
{
mSecurityInfo = info;
return NS_OK;
}
nsresult
nsCacheEntry::GetData(nsISupports **result)
@ -197,6 +213,11 @@ nsCacheEntry::RequestAccess(nsCacheRequest * request, nsCacheAccessMode *accessG
if (PR_CLIST_IS_EMPTY(&mDescriptorQ)) {
// 1st descriptor for existing bound entry
*accessGranted = request->AccessRequested();
if (*accessGranted & nsICache::ACCESS_WRITE) {
MarkInvalid();
} else {
MarkValid();
}
} else {
// nth request for existing, bound entry
*accessGranted = request->AccessRequested() & ~nsICache::ACCESS_WRITE;

10
netwerk/cache/src/nsCacheEntry.h поставляемый
Просмотреть файл

@ -80,6 +80,9 @@ public:
nsCacheDevice * CacheDevice(void) { return mCacheDevice;}
void SetCacheDevice( nsCacheDevice * device) { mCacheDevice = device;}
nsresult GetSecurityInfo( nsISupports ** result);
nsresult SetSecurityInfo( nsISupports * info);
nsresult GetData( nsISupports ** result);
nsresult SetData( nsISupports * data);
@ -169,10 +172,11 @@ private:
PRUint32 mDataSize; // 4
PRUint32 mMetaSize; // 4
nsCacheDevice * mCacheDevice; // 4
nsCOMPtr<nsISupports> mData; // 4
nsCOMPtr<nsISupports> mSecurityInfo;
nsCOMPtr<nsISupports> mData; //
nsCacheMetaData * mMetaData; // 4
PRCList mRequestQ; // 8 = 64
PRCList mDescriptorQ; // 8 = 72
PRCList mRequestQ; // 8
PRCList mDescriptorQ; // 8
};

414
netwerk/cache/src/nsCacheEntryDescriptor.cpp поставляемый
Просмотреть файл

@ -28,12 +28,13 @@
#include "nsReadableUtils.h"
#include "nsIOutputStream.h"
NS_IMPL_ISUPPORTS2(nsCacheEntryDescriptor, nsICacheEntryDescriptor, nsITransport)
NS_IMPL_ISUPPORTS1(nsCacheEntryDescriptor, nsICacheEntryDescriptor)
nsCacheEntryDescriptor::nsCacheEntryDescriptor(nsCacheEntry * entry,
nsCacheAccessMode accessGranted)
: mCacheEntry(entry), mAccessGranted(accessGranted)
: mCacheEntry(entry),
mAccessGranted(accessGranted)
{
NS_INIT_ISUPPORTS();
PR_INIT_CLIST(this);
@ -207,7 +208,7 @@ nsCacheEntryDescriptor::GetTransport(nsITransport ** result)
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
if (!mCacheEntry->IsStreamData()) return NS_ERROR_CACHE_DATA_IS_NOT_STREAM;
NS_ADDREF(*result = this);
NS_ADDREF(*result = &mTransportWrapper);
return NS_OK;
}
@ -260,6 +261,7 @@ nsCacheEntryDescriptor::SetStoragePolicy(nsCacheStoragePolicy policy)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::GetFile(nsIFile ** result)
{
@ -269,6 +271,27 @@ nsCacheEntryDescriptor::GetFile(nsIFile ** result)
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::GetSecurityInfo(nsISupports ** result)
{
NS_ENSURE_ARG_POINTER(result);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
return mCacheEntry->GetSecurityInfo(result);
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetSecurityInfo(nsISupports * securityInfo)
{
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
mCacheEntry->SetSecurityInfo(securityInfo);
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::Doom()
{
@ -353,195 +376,128 @@ nsCacheEntryDescriptor::GetMetaDataEnumerator(nsISimpleEnumerator ** result)
}
NS_IMETHODIMP
nsCacheEntryDescriptor::GetSecurityInfo(nsISupports ** result)
{
NS_ENSURE_ARG_POINTER(result);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
/******************************************************************************
* nsCacheTransportWrapper
******************************************************************************/
return NS_ERROR_NOT_IMPLEMENTED;
// XXX NS_IMPL_ISUPPORTS1(nsCacheEntryDescriptor::nsTransportWrapper, nsITransport);
NS_IMPL_QUERY_INTERFACE1(nsCacheEntryDescriptor::nsTransportWrapper, nsITransport)
// special AddRef and Release, because we are part of the descriptor
#define GET_DESCRIPTOR_FROM_TRANSPORT_WRAPPER(_this) \
((nsCacheEntryDescriptor*)((char*)(_this) - \
offsetof(nsCacheEntryDescriptor, mTransportWrapper)))
NS_IMETHODIMP_(nsrefcnt) nsCacheEntryDescriptor::
nsTransportWrapper::AddRef(void)
{
return GET_DESCRIPTOR_FROM_TRANSPORT_WRAPPER(this)->AddRef();
}
NS_IMETHODIMP_(nsrefcnt) nsCacheEntryDescriptor::
nsTransportWrapper::Release(void)
{
return GET_DESCRIPTOR_FROM_TRANSPORT_WRAPPER(this)->Release();
}
NS_IMETHODIMP
nsCacheEntryDescriptor::GetNotificationCallbacks(nsIInterfaceRequestor **result)
nsresult nsCacheEntryDescriptor::
nsTransportWrapper::EnsureTransportWithAccess(nsCacheAccessMode mode)
{
NS_ENSURE_ARG_POINTER(result);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
nsresult rv = NS_OK;
return NS_ERROR_NOT_IMPLEMENTED;
}
nsCacheEntryDescriptor * descriptor = GET_DESCRIPTOR_FROM_TRANSPORT_WRAPPER(this);
if (!descriptor->mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
if (!descriptor->mAccessGranted & mode) {
rv = (mode == nsICache::ACCESS_READ) ?
NS_ERROR_CACHE_READ_ACCESS_DENIED : NS_ERROR_CACHE_WRITE_ACCESS_DENIED;
return rv;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetNotificationCallbacks(nsIInterfaceRequestor *requestor,
PRBool isBackground)
{
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::OpenInputStream(PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIInputStream ** result)
{
NS_ENSURE_ARG_POINTER(result);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
if (!(mAccessGranted & nsICache::ACCESS_READ))
return NS_ERROR_CACHE_READ_ACCESS_DENIED;
if (!mTransport) {
nsresult rv;
rv = nsCacheService::GlobalInstance()->
GetTransportForEntry(mCacheEntry,
mAccessGranted,
GetTransportForEntry(descriptor->mCacheEntry,
descriptor->mAccessGranted,
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
}
return mTransport->OpenInputStream(offset, count, flags, result);
}
/**
* nsCacheOutputStream - a wrapper for nsIOutputstream to track the amount of data
* written to a cache entry.
*/
class nsCacheOutputStream : public nsIOutputStream {
nsCacheEntryDescriptor* mDescriptor;
nsCOMPtr<nsIOutputStream> mOutput;
public:
NS_DECL_ISUPPORTS
nsCacheOutputStream(nsCacheEntryDescriptor* descriptor, nsIOutputStream* output)
: mDescriptor(nsnull), mOutput(output)
{
NS_INIT_ISUPPORTS();
NS_ADDREF(mDescriptor = descriptor);
}
virtual ~nsCacheOutputStream()
{
NS_RELEASE(mDescriptor);
}
nsresult Init();
NS_IMETHOD Close() { return mOutput->Close(); }
NS_IMETHOD Flush() { return mOutput->Flush(); }
NS_IMETHOD Write(const char *buf, PRUint32 count, PRUint32 *_retval);
NS_IMETHOD WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval);
NS_IMETHOD WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval);
NS_IMETHOD GetNonBlocking(PRBool *aNonBlocking) { return mOutput->GetNonBlocking(aNonBlocking); }
NS_IMETHOD SetNonBlocking(PRBool aNonBlocking) { return mOutput->SetNonBlocking(aNonBlocking); }
NS_IMETHOD GetObserver(nsIOutputStreamObserver * *aObserver) { return mOutput->GetObserver(aObserver); }
NS_IMETHOD SetObserver(nsIOutputStreamObserver * aObserver) { return mOutput->SetObserver(aObserver); }
private:
nsresult OnWrite(PRUint32 count);
};
NS_IMPL_ISUPPORTS1(nsCacheOutputStream, nsIOutputStream);
nsresult
nsCacheOutputStream::Init()
{
nsCacheAccessMode mode;
nsresult rv = mDescriptor->GetAccessGranted(&mode);
if (NS_FAILED(rv)) return rv;
if (mode == nsICache::ACCESS_WRITE) {
nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
nsCacheDevice* device = cacheEntry->CacheDevice();
if (!device) return NS_ERROR_NOT_AVAILABLE;
// the entry has been truncated to zero bytes, inform the device.
PRInt32 delta = -cacheEntry->DataSize();
rv = device->OnDataSizeChange(cacheEntry, delta);
cacheEntry->SetDataSize(0);
}
return rv;
}
NS_IMETHODIMP
nsCacheOutputStream::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
nsresult rv = OnWrite(count);
if (NS_FAILED(rv)) return rv;
return mOutput->Write(buf, count, _retval);
}
NS_IMETHODIMP
nsCacheOutputStream::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
nsresult rv = OnWrite(count);
if (NS_FAILED(rv)) return rv;
return mOutput->WriteFrom(inStr, count, _retval);
}
NS_IMETHODIMP
nsCacheOutputStream::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
nsresult rv = OnWrite(count);
if (NS_FAILED(rv)) return rv;
return mOutput->WriteSegments(reader, closure, count, _retval);
}
nsresult
nsCacheOutputStream::OnWrite(PRUint32 count)
{
// XXX if count > 2^31 error_write_too_big
return mDescriptor->RequestDataSizeChange((PRInt32)count);
#if 0
nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
nsCacheDevice* device = cacheEntry->CacheDevice();
if (!device) return NS_ERROR_NOT_AVAILABLE;
nsresult rv = device->OnDataSizeChange(cacheEntry, count);
if (NS_FAILED(rv)) return rv;
cacheEntry->SetDataSize(cacheEntry->DataSize() + count);
return NS_OK;
#endif
}
static nsresult NS_NewCacheOutputStream(nsIOutputStream ** result,
nsCacheEntryDescriptor * descriptor,
nsIOutputStream * output)
static nsresult NS_NewOutputStreamWrapper(nsIOutputStream ** result,
nsCacheEntryDescriptor * descriptor,
nsIOutputStream * output)
{
nsCacheOutputStream* cacheOutput = new nsCacheOutputStream(descriptor, output);
nsCacheEntryDescriptor::nsOutputStreamWrapper* cacheOutput =
new nsCacheEntryDescriptor::nsOutputStreamWrapper(descriptor, output);
if (!cacheOutput) return NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsISupports> ref(cacheOutput);
nsresult rv = cacheOutput->Init();
nsresult rv = cacheOutput->Init();
if (NS_FAILED(rv)) return rv;
NS_ADDREF(*result = cacheOutput);
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::OpenOutputStream(PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIOutputStream ** result)
NS_IMETHODIMP nsCacheEntryDescriptor::
nsTransportWrapper::GetSecurityInfo(nsISupports ** securityInfo)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsCacheEntryDescriptor::
nsTransportWrapper::GetNotificationCallbacks(nsIInterfaceRequestor **result)
{
NS_ENSURE_ARG_POINTER(result);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
if (!(mAccessGranted & nsICache::ACCESS_WRITE))
return NS_ERROR_CACHE_WRITE_ACCESS_DENIED;
// if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
nsresult rv;
if (!mTransport) {
rv = nsCacheService::GlobalInstance()->
GetTransportForEntry(mCacheEntry,
mAccessGranted,
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
}
return NS_ERROR_NOT_IMPLEMENTED;
}
// XXX allow more than one output stream at a time on a descriptor?
NS_IMETHODIMP nsCacheEntryDescriptor::
nsTransportWrapper::SetNotificationCallbacks(nsIInterfaceRequestor *requestor,
PRBool isBackground)
{
// if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsCacheEntryDescriptor::
nsTransportWrapper::OpenInputStream(PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIInputStream ** result)
{
NS_ENSURE_ARG_POINTER(result);
nsresult rv = EnsureTransportWithAccess(nsICache::ACCESS_READ);
if (NS_FAILED(rv)) return rv;
return mTransport->OpenInputStream(offset, count, flags, result);
}
NS_IMETHODIMP nsCacheEntryDescriptor::
nsTransportWrapper::OpenOutputStream(PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIOutputStream ** result)
{
NS_ENSURE_ARG_POINTER(result);
nsresult rv = EnsureTransportWithAccess(nsICache::ACCESS_WRITE);
if (NS_FAILED(rv)) return rv;
// XXX allow more than one output stream at a time on a descriptor? Why?
// Create the underlying output stream using the wrapped transport.
nsCOMPtr<nsIOutputStream> output;
@ -552,59 +508,119 @@ nsCacheEntryDescriptor::OpenOutputStream(PRUint32 offset,
// to maintain the cache entry's size, and to inform the cache device. Eventually,
// this mechanism will provide a way for the cache device to enforce space limits,
// and to drive cache entry eviction.
return NS_NewCacheOutputStream(result, this, output);
nsCacheEntryDescriptor * descriptor = GET_DESCRIPTOR_FROM_TRANSPORT_WRAPPER(this);
return NS_NewOutputStreamWrapper(result, descriptor, output);
}
NS_IMETHODIMP
nsCacheEntryDescriptor::AsyncRead(nsIStreamListener * listener,
nsISupports * ctxt,
PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIRequest ** result)
NS_IMETHODIMP nsCacheEntryDescriptor::
nsTransportWrapper::AsyncRead(nsIStreamListener * listener,
nsISupports * ctxt,
PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIRequest ** result)
{
NS_ENSURE_ARG_POINTER(result);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
if (!(mAccessGranted & nsICache::ACCESS_READ))
return NS_ERROR_CACHE_READ_ACCESS_DENIED;
if (!mTransport) {
nsresult rv;
rv = nsCacheService::GlobalInstance()->
GetTransportForEntry(mCacheEntry,
mAccessGranted,
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
}
nsresult rv = EnsureTransportWithAccess(nsICache::ACCESS_READ);
if (NS_FAILED(rv)) return rv;
return mTransport->AsyncRead(listener, ctxt, offset, count, flags, result);
}
NS_IMETHODIMP
nsCacheEntryDescriptor::AsyncWrite(nsIStreamProvider * provider,
nsISupports * ctxt,
PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIRequest ** result)
NS_IMETHODIMP nsCacheEntryDescriptor::
nsTransportWrapper::AsyncWrite(nsIStreamProvider * provider,
nsISupports * ctxt,
PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIRequest ** result)
{
// we're not planning on implementing this
return NS_ERROR_NOT_IMPLEMENTED;
#if 0
NS_ENSURE_ARG_POINTER(result);
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
if (!(mAccessGranted & nsICache::ACCESS_WRITE))
return NS_ERROR_CACHE_WRITE_ACCESS_DENIED;
if (!mTransport) {
nsresult rv;
rv = nsCacheService::GlobalInstance()->
GetTransportForEntry(mCacheEntry,
mAccessGranted,
getter_AddRefs(mTransport));
if (NS_FAILED(rv)) return rv;
}
nsresult rv = EnsureTransportWithAccess(nsICache::ACCESS_WRITE);
if (NS_FAILED(rv)) return rv;
return mTransport->AsyncWrite(provider, ctxt, offset, count, flags, result);
#endif
}
/******************************************************************************
* nsCacheOutputStream - a wrapper for nsIOutputstream to track the amount of
* data written to a cache entry.
******************************************************************************/
NS_IMPL_ISUPPORTS1(nsCacheEntryDescriptor::nsOutputStreamWrapper, nsIOutputStream);
nsresult nsCacheEntryDescriptor::
nsOutputStreamWrapper::Init()
{
nsCacheAccessMode mode;
nsresult rv = mDescriptor->GetAccessGranted(&mode);
if (NS_FAILED(rv)) return rv;
if (mode == nsICache::ACCESS_WRITE) {
nsCacheEntry* cacheEntry = mDescriptor->CacheEntry();
if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE;
nsCacheDevice* device = cacheEntry->CacheDevice();
if (!device) return NS_ERROR_NOT_AVAILABLE;
// the entry has been truncated to zero bytes, inform the device.
PRInt32 delta = -cacheEntry->DataSize();
rv = device->OnDataSizeChange(cacheEntry, delta);
cacheEntry->SetDataSize(0);
}
return rv;
}
NS_IMETHODIMP nsCacheEntryDescriptor::
nsOutputStreamWrapper::Write(const char * buf,
PRUint32 count,
PRUint32 * result)
{
nsresult rv = OnWrite(count);
if (NS_FAILED(rv)) return rv;
return mOutput->Write(buf, count, result);
}
NS_IMETHODIMP nsCacheEntryDescriptor::
nsOutputStreamWrapper::WriteFrom(nsIInputStream * inStr,
PRUint32 count,
PRUint32 * result)
{
nsresult rv = OnWrite(count);
if (NS_FAILED(rv)) return rv;
return mOutput->WriteFrom(inStr, count, result);
}
NS_IMETHODIMP nsCacheEntryDescriptor::
nsOutputStreamWrapper::WriteSegments(nsReadSegmentFun reader,
void * closure,
PRUint32 count,
PRUint32 * result)
{
nsresult rv = OnWrite(count);
if (NS_FAILED(rv)) return rv;
return mOutput->WriteSegments(reader, closure, count, result);
}
nsresult nsCacheEntryDescriptor::
nsOutputStreamWrapper::OnWrite(PRUint32 count)
{
// XXX if count > 2^31 error_write_too_big
return mDescriptor->RequestDataSizeChange((PRInt32)count);
}

107
netwerk/cache/src/nsCacheEntryDescriptor.h поставляемый
Просмотреть файл

@ -27,15 +27,14 @@
#include "nsICacheEntryDescriptor.h"
#include "nsCacheEntry.h"
#include "nsIOutputStream.h"
class nsCacheEntryDescriptor :
public PRCList,
public nsICacheEntryDescriptor,
public nsITransport
{
public nsICacheEntryDescriptor
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITRANSPORT
NS_DECL_NSICACHEENTRYDESCRIPTOR
nsCacheEntryDescriptor(nsCacheEntry * entry, nsCacheAccessMode mode);
@ -55,11 +54,103 @@ public:
*/
nsCacheEntry * CacheEntry(void) { return mCacheEntry; }
protected:
private:
/**
* transport wrapper class -
*
* we want the transport wrapper to have the same lifetime as the descriptor,
* but since they each need to reference the other, we have the descriptor
* include the transport wrapper as a member, rather than just pointing to it,
* which avoids circular AddRefs.
*/
class nsTransportWrapper : public nsITransport
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSITRANSPORT
nsTransportWrapper() : mTransport(nsnull) {}
virtual ~nsTransportWrapper() {}
nsresult EnsureTransportWithAccess(nsCacheAccessMode mode);
nsCOMPtr<nsITransport> mTransport;
}; // end of class nsTransportWrapper
friend class nsTransportWrapper;
/**
* output stream wrapper class -
*
* The output stream wrapper references the descriptor, but the descriptor doesn't
* need any references to the stream wrapper, so we don't need the same kind of
* tricks that we're using for the transport wrapper.
*/
class nsOutputStreamWrapper : public nsIOutputStream {
private:
nsCacheEntryDescriptor * mDescriptor;
nsCOMPtr<nsIOutputStream> mOutput;
public:
NS_DECL_ISUPPORTS
// NS_DECL_NSIOUTPUTSTREAM
NS_IMETHOD Close(void) { return mOutput->Close(); }
NS_IMETHOD Flush(void) { return mOutput->Flush(); }
NS_IMETHOD Write(const char * buf,
PRUint32 count,
PRUint32 * result);
NS_IMETHOD WriteFrom(nsIInputStream * inStr,
PRUint32 count,
PRUint32 * result);
NS_IMETHOD WriteSegments(nsReadSegmentFun reader,
void * closure,
PRUint32 count,
PRUint32 * result);
NS_IMETHOD GetNonBlocking(PRBool * nonBlocking)
{ return mOutput->GetNonBlocking(nonBlocking); }
NS_IMETHOD SetNonBlocking(PRBool nonBlocking)
{ return mOutput->SetNonBlocking(nonBlocking); }
NS_IMETHOD GetObserver(nsIOutputStreamObserver ** observer)
{ return mOutput->GetObserver(observer); }
NS_IMETHOD SetObserver(nsIOutputStreamObserver * observer)
{ return mOutput->SetObserver(observer); }
nsOutputStreamWrapper(nsCacheEntryDescriptor * descriptor,
nsIOutputStream * output)
: mDescriptor(nsnull), mOutput(output)
{
NS_INIT_ISUPPORTS();
NS_ADDREF(mDescriptor = descriptor);
}
nsCacheEntry * mCacheEntry; // we are a child of the entry
nsCacheAccessMode mAccessGranted;
nsCOMPtr<nsITransport> mTransport;
virtual ~nsOutputStreamWrapper()
{
NS_RELEASE(mDescriptor);
}
nsresult Init();
private:
nsresult OnWrite(PRUint32 count);
}; // end of class nsOutputStreamWrapper
friend class nsOutputStreamWrapper;
private:
/**
* nsCacheEntryDescriptor data members
*/
nsCacheEntry * mCacheEntry; // we are a child of the entry
nsCacheAccessMode mAccessGranted;
nsTransportWrapper mTransportWrapper;
};

104
netwerk/cache/src/nsMemoryCacheDevice.cpp поставляемый
Просмотреть файл

@ -25,11 +25,21 @@
#include "nsICacheService.h"
#include "nsIComponentManager.h"
#include "nsNetCID.h"
#include "nsIObserverService.h"
#include "nsIPref.h"
static NS_DEFINE_CID(kStorageTransportCID, NS_STORAGETRANSPORT_CID);
const char *gMemoryCacheSizePref = "browser.cache.memory_cache_size";
nsMemoryCacheDevice::nsMemoryCacheDevice()
: mCurrentTotal(0)
: mHardLimit(0),
mSoftLimit(0),
mTotalSize(0),
mInactiveSize(0),
mEntryCount(0),
mMaxEntryCount(0)
{
PR_INIT_CLIST(&mEvictionList);
}
@ -37,6 +47,30 @@ nsMemoryCacheDevice::nsMemoryCacheDevice()
nsMemoryCacheDevice::~nsMemoryCacheDevice()
{
// XXX dealloc all memory
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
prefs->UnregisterCallback(gMemoryCacheSizePref, MemoryCacheSizeChanged, this);
}
}
int PR_CALLBACK
nsMemoryCacheDevice::MemoryCacheSizeChanged(const char * pref, void * closure)
{
nsresult rv;
PRUint32 softLimit = 0;
nsMemoryCacheDevice * device = (nsMemoryCacheDevice *)closure;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
rv = prefs->GetIntPref(gMemoryCacheSizePref, (PRInt32 *)&softLimit);
PRUint32 hardLimit = softLimit + 1024*1024*2; // XXX find better limit than +2Meg
rv = device->AdjustMemoryLimits(softLimit, hardLimit);
return 0; // XXX what are we supposed to return?
}
@ -48,6 +82,23 @@ nsMemoryCacheDevice::Init()
rv = mMemCacheEntries.Init();
// XXX read user prefs for memory cache limits
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_CONTRACTID, &rv);
if (NS_FAILED(rv)) return rv;
rv = prefs->RegisterCallback(gMemoryCacheSizePref, MemoryCacheSizeChanged, this);
if (NS_FAILED(rv)) return rv;
// Initialize the pref
MemoryCacheSizeChanged(gMemoryCacheSizePref, this);
// Register as a memory pressure observer
NS_WITH_SERVICE(nsIObserverService,
observerService,
NS_OBSERVERSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
// XXX rv = observerServcie->AddObserver(this, NS_MEMORY_PRESSURE_TOPIC);
}
// Ignore failure of memory pressure registration
return rv;
}
@ -165,7 +216,56 @@ nsMemoryCacheDevice::OnDataSizeChange( nsCacheEntry * entry, PRInt32 deltaSize)
return NS_OK;
}
nsresult
nsMemoryCacheDevice::AdjustMemoryLimits(PRUint32 softLimit, PRUint32 hardLimit)
{
mSoftLimit = softLimit;
mHardLimit = hardLimit;
if ((mTotalSize > mHardLimit) || (mInactiveSize > softLimit)) {
// XXX rv = EvictEntries();
}
return NS_OK;
}
nsresult
nsMemoryCacheDevice::EvictEntries(void)
{
nsCacheEntry * entry;
nsresult rv = NS_OK;
entry = (nsCacheEntry *)PR_LIST_HEAD(&mEvictionList);
while (entry != &mEvictionList) {
if (entry->IsInUse()) {
entry = (nsCacheEntry *)PR_NEXT_LINK(entry);
continue;
}
// remove entry from our hashtable
rv = mMemCacheEntries.RemoveEntry(entry);
NS_ASSERTION(NS_SUCCEEDED(rv), "RemoveEntry() failed?");
// remove entry from the eviction list
PR_REMOVE_AND_INIT_LINK(entry);
// update statistics
PRUint32 memoryRecovered = entry->DataSize() + entry->MetaDataSize();
mTotalSize -= memoryRecovered;
mInactiveSize -= memoryRecovered;
--mEntryCount;
delete entry;
if ((mTotalSize < mHardLimit) && (mInactiveSize < mSoftLimit))
break;
}
return NS_OK;
}
// XXX need methods for enumerating entries
// XXX check entry->IsInUse() before evicting.

13
netwerk/cache/src/nsMemoryCacheDevice.h поставляемый
Просмотреть файл

@ -49,16 +49,25 @@ public:
nsITransport **transport );
virtual nsresult OnDataSizeChange( nsCacheEntry * entry, PRInt32 deltaSize );
static int PR_CALLBACK MemoryCacheSizeChanged(const char * pref, void * closure);
private:
nsresult AdjustMemoryLimits(PRUint32 softLimit, PRUint32 hardLimit);
nsresult EvictEntries(void);
nsCacheEntryHashTable mMemCacheEntries;
PRCList mEvictionList;
PRUint32 mHardLimit;
PRUint32 mSoftLimit;
PRUint32 mCurrentTotal;
PRCList mEvictionList;
PRUint32 mTotalSize;
PRUint32 mInactiveSize;
PRUint32 mEntryCount;
PRUint32 mMaxEntryCount;
// XXX what other stats do we want to keep?
};