Rough first cut of cache service and memory object cache. It currently builds on linux.

git-svn-id: svn://10.0.0.236/trunk@87809 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
gordon%netscape.com 2001-02-23 13:18:01 +00:00
parent 5237da31b9
commit cfbd099fb3
14 changed files with 2244 additions and 0 deletions

View File

@ -0,0 +1,57 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheDevice.h, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#ifndef _nsCacheDevice_h_
#define _nsCacheDevice_h_
#include "nspr.h"
#include "nsError.h"
class nsCacheEntry;
class nsCacheDevice {
public:
nsCacheDevice(PRUint32 deviceID) : mDeviceID(deviceID){}
virtual ~nsCacheDevice() = 0;
//** decide on strings or ints for IDs
virtual PRUint32 GetDeviceID(void) { return mDeviceID; }
virtual nsresult ActivateEntryIfFound( nsCacheEntry * entry ) = 0;
virtual nsresult DeactivateEntry( nsCacheEntry * entry ) = 0;
virtual nsresult BindEntry( nsCacheEntry * entry ) = 0;
//** need to define stream factory methods
//** need to define methods for enumerating entries
//** need notification methods for size changes on non-streamBased entries
protected:
PRUint32 mDeviceID;
};
#endif // _nsCacheDevice_h_

View File

@ -0,0 +1,329 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheEntry.cpp, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#include "nspr.h"
#include "nsCacheEntry.h"
#include "nsCacheEntryDescriptor.h"
#include "nsCacheMetaData.h"
#include "nsCacheRequest.h"
#include "nsError.h"
#include "nsICacheService.h"
#define ONE_YEAR (PR_USEC_PER_SEC * 60 * 60 * 24 * 365)
nsCacheEntry::nsCacheEntry(nsCString * key)
: mKey(key),
mFetchCount(0),
mFlags(0),
mDataSize(0),
mMetaSize(0),
mCacheDevice(nsnull),
mData(nsnull),
mMetaData(nsnull)
{
PR_INIT_CLIST(&mRequestQ);
PR_INIT_CLIST(&mDescriptorQ);
mLastFetched = mLastValidated = PR_Now();
mExpirationTime = 0;
}
nsCacheEntry::~nsCacheEntry()
{
if (mCacheDevice) {
//** ask device to clean up
}
}
nsresult
nsCacheEntry::GetData(nsISupports **result)
{
if (IsStreamData())
return NS_ERROR_CACHE_DATA_IS_STREAM;
if (result) *result = mData;
return NS_OK;
}
nsresult
nsCacheEntry::SetData(nsISupports * data)
{
if (IsStreamData())
return NS_ERROR_CACHE_DATA_IS_STREAM;
mData = data;
return NS_OK;
}
nsresult
nsCacheEntry::GetMetaDataElement( const nsAReadableCString& key,
nsAReadableCString ** value)
{
*value = mMetaData ? mMetaData->GetElement(&key) : nsnull;
return NS_OK;
}
nsresult
nsCacheEntry::SetMetaDataElement( const nsAReadableCString& key,
const nsAReadableCString& value)
{
if (!mMetaData) {
mMetaData = new nsCacheMetaData();
if (!mMetaData)
return NS_ERROR_OUT_OF_MEMORY;
}
return mMetaData->SetElement(&key, &value);
}
/**
* cache entry states
* 0 descriptors (new entry)
* 0 descriptors (existing, bound entry)
* n descriptors (existing, bound entry) valid
* n descriptors (existing, bound entry) not valid (wait until valid or doomed)
*/
nsresult
nsCacheEntry::CommonOpen(nsCacheRequest * request, PRUint32 *accessGranted)
{
nsresult rv = NS_OK;
if (!IsInitialized()) {
// brand new, unbound entry
NS_ASSERTION(request->mAccessRequested & nsICacheService::WRITE,
"new cache entry for READ-ONLY request");
if (request->mStreamBased) MarkStreamBased();
mFetchCount = 1;
MarkInitialized();
*accessGranted = request->mAccessRequested & ~nsICacheService::WRITE;
return rv;
}
if (IsStreamData() != request->mStreamBased) {
*accessGranted = nsICacheService::NO_ACCESS;
return request->mStreamBased ?
NS_ERROR_CACHE_DATA_IS_NOT_STREAM : NS_ERROR_CACHE_DATA_IS_STREAM;
}
if (PR_CLIST_IS_EMPTY(&mDescriptorQ)) {
// 1st descriptor for existing, bound entry
*accessGranted = request->mAccessRequested;
} else {
// nth request for existing, bound entry
*accessGranted = request->mAccessRequested & ~nsICacheService::WRITE;
if (!IsValid())
rv = NS_ERROR_CACHE_WAIT_FOR_VALIDATION;
}
return rv;
}
nsresult
nsCacheEntry::Open(nsCacheRequest * request, nsICacheEntryDescriptor ** result)
{
if (!request) return NS_ERROR_NULL_POINTER;
PRUint32 accessGranted;
nsresult rv = CommonOpen(request, &accessGranted);
if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
//** queue request
//** allocate PRCondVar for request, if none
//** release service lock
//** wait until valid or doomed
}
if (NS_SUCCEEDED(rv)) {
rv = nsCacheEntryDescriptor::Create(this, accessGranted, result);
//** queue the descriptor
}
return rv;
}
nsresult
nsCacheEntry::AsyncOpen(nsCacheRequest * request)
{
if (!request) return NS_ERROR_NULL_POINTER;
PRUint32 accessGranted;
nsresult rv = CommonOpen(request, &accessGranted);
if (NS_SUCCEEDED(rv)) {
nsICacheEntryDescriptor * descriptor;
rv = nsCacheEntryDescriptor::Create(this, accessGranted, &descriptor);
if (NS_SUCCEEDED(rv)) {
//** queue the descriptor
//** post event to call listener with
}
} else if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
//** queue request and we're done (MarkValid will notify pending requests)
} else {
}
return NS_ERROR_NOT_IMPLEMENTED;
}
/*
* nsCacheEntryHashTable
*/
PLDHashTableOps
nsCacheEntryHashTable::ops =
{
PL_DHashAllocTable,
PL_DHashFreeTable,
GetKey,
HashKey,
MatchEntry,
MoveEntry,
ClearEntry,
Finalize
};
nsCacheEntryHashTable::nsCacheEntryHashTable()
: initialized(0)
{
}
nsCacheEntryHashTable::~nsCacheEntryHashTable()
{
//** maybe we should finalize the table...
}
nsresult
nsCacheEntryHashTable::Init()
{
nsresult rv = NS_OK;
initialized = PL_DHashTableInit(&table, &ops, nsnull,
sizeof(nsCacheEntryHashTableEntry), 512);
if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
nsCacheEntry *
nsCacheEntryHashTable::GetEntry( const nsCString * key)
{
PLDHashEntryHdr *hashEntry;
nsCacheEntry *result = nsnull;
NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized");
hashEntry = PL_DHashTableOperate(&table, key, PL_DHASH_LOOKUP);
if (PL_DHASH_ENTRY_IS_BUSY(hashEntry)) {
result = ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry;
}
return result;
}
nsresult
nsCacheEntryHashTable::AddEntry( nsCacheEntry *cacheEntry)
{
PLDHashEntryHdr *hashEntry;
NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized");
if (!cacheEntry) return NS_ERROR_NULL_POINTER;
hashEntry = PL_DHashTableOperate(&table, cacheEntry->mKey, PL_DHASH_ADD);
NS_ASSERTION(((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry != 0,
"nsCacheEntryHashTable::AddEntry - entry already used");
((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry = cacheEntry;
return NS_OK;
}
nsresult
nsCacheEntryHashTable::RemoveEntry( nsCacheEntry *cacheEntry)
{
PLDHashEntryHdr *hashEntry;
NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized");
if (!cacheEntry) return NS_ERROR_NULL_POINTER;
hashEntry = PL_DHashTableOperate(&table, cacheEntry->mKey, PL_DHASH_ADD);
if (PL_DHASH_ENTRY_IS_FREE(hashEntry)) {
// it's not in the table!?!
return NS_ERROR_UNEXPECTED;
}
return NS_OK;
}
/*
* hash table operation callback functions
*/
const void *
nsCacheEntryHashTable::GetKey( PLDHashTable * /*table*/, PLDHashEntryHdr *hashEntry)
{
nsCacheEntry *cacheEntry = ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry;
return cacheEntry->mKey;
}
PRBool
nsCacheEntryHashTable::MatchEntry(PLDHashTable * /* table */,
const PLDHashEntryHdr * hashEntry,
const void * key)
{
NS_ASSERTION(key != nsnull, "nsCacheEntryHashTable::MatchEntry : null key");
nsCacheEntry *cacheEntry = ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry;
return nsStr::StrCompare(*cacheEntry->mKey, *(nsCString *)key, -1, PR_FALSE) == 0;
}
void
nsCacheEntryHashTable::MoveEntry(PLDHashTable * /* table */,
const PLDHashEntryHdr *from,
PLDHashEntryHdr *to)
{
to->keyHash = from->keyHash;
((nsCacheEntryHashTableEntry *)to)->cacheEntry =
((nsCacheEntryHashTableEntry *)from)->cacheEntry;
}
void
nsCacheEntryHashTable::ClearEntry(PLDHashTable * /* table */,
PLDHashEntryHdr * hashEntry)
{
((nsCacheEntryHashTableEntry *)hashEntry)->keyHash = 0;
((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry = 0;
}
void
nsCacheEntryHashTable::Finalize(PLDHashTable * /* table */)
{
//** gee, if there's anything left in the table, maybe we should get rid of it.
}

190
mozilla/netwerk/cache/src/nsCacheEntry.h vendored Normal file
View File

@ -0,0 +1,190 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheEntry.h, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#ifndef _nsCacheEntry_h_
#define _nsCacheEntry_h_
#include "nspr.h"
#include "pldhash.h"
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsAReadableString.h"
#include "nsICacheEntryDescriptor.h"
class nsCacheDevice;
class nsCacheMetaData;
class nsCacheRequest;
class nsCacheEntry
{
public:
enum CacheEntryFlags {
eDoomedMask = 1,
eEntryDirtyMask = 2,
eDataDirtyMask = 4,
eMetaDataDirtyMask = 8,
eStreamDataMask = 16,
eActiveMask = 32,
eInitializedMask = 64,
eValidMask = 128,
eAllowInMemoryMask = 256,
eAllowOnDiskMask = 512
};
nsCacheEntry(nsCString * key);
~nsCacheEntry();
void GetKey( nsCString ** key) { if (key) *key = mKey; }
void GetFetchCount( PRUint32 * result) { if (result) *result = mFetchCount; }
void SetFetchCount( PRUint32 count) { mFetchCount = count; }
void GetLastFetched( PRTime * result) { if (result) *result = mLastFetched; }
void SetLastFetched( PRTime lastFetched)
{ if (lastFetched) mLastFetched = lastFetched; }
void GetLastValidated( PRTime * result) { if (result) *result = mLastValidated; }
void SetLastValidated( PRTime lastValidated)
{ if (lastValidated) mLastValidated = lastValidated; }
void GetExpirationTime( PRTime * result) { if (result) *result = mExpirationTime; }
void SetExpirationTime( PRTime expires) { if (expires) mExpirationTime = expires; }
void GetDataSize( PRUint32 * result) { if (result) *result = mDataSize; }
void SetDataSize( PRUint32 size) { mDataSize = size; }
void GetMetaDataSize( PRUint32 * result) { if (result) *result = mMetaSize; }
void SetMetaDataSize( PRUint32 size) { mMetaSize = size; }
void GetCacheDevice( nsCacheDevice ** result) { if (result) *result = mCacheDevice; }
void SetCacheDevice( nsCacheDevice * device) { mCacheDevice = device; }
nsresult GetData( nsISupports ** result);
nsresult SetData( nsISupports * data);
//** should we make these string references instead of pointers?
nsresult GetMetaDataElement( const nsAReadableCString& key,
nsAReadableCString ** value);
nsresult SetMetaDataElement( const nsAReadableCString& key,
const nsAReadableCString& value);
//** enumerate MetaData method
void MarkEntryDirty() { mFlags |= eEntryDirtyMask;}
void MarkDataDirty() { mFlags |= eDataDirtyMask; }
void MarkMetaDataDirty() { mFlags |= eMetaDataDirtyMask; }
void MarkActive() { mFlags |= eActiveMask; }
void MarkInactive() { mFlags &= ~eActiveMask; }
void MarkValid();
PRBool IsDoomed() { return (mFlags & eDoomedMask) != 0; }
PRBool IsEntryDirty() { return (mFlags & eEntryDirtyMask) != 0; }
PRBool IsDataDirty() { return (mFlags & eDataDirtyMask) != 0; }
PRBool IsMetaDataDirty() { return (mFlags & eMetaDataDirtyMask) != 0; }
PRBool IsStreamData() { return (mFlags & eStreamDataMask) != 0; }
PRBool IsActive() { return (mFlags & eActiveMask) != 0; }
PRBool IsInitialized() { return (mFlags & eInitializedMask) != 0; }
PRBool IsValid() { return (mFlags & eValidMask) != 0; }
private:
friend class nsCacheEntryHashTable;
friend class nsCacheService;
// methods for nsCacheService
nsresult Open(nsCacheRequest *request, nsICacheEntryDescriptor ** result);
nsresult AsyncOpen(nsCacheRequest *request);
nsresult Doom() { return NS_ERROR_NOT_IMPLEMENTED; } //** implement
// internal methods
nsresult CommonOpen(nsCacheRequest * request, PRUint32 *accessGranted);
void MarkStreamBased() { mFlags |= eStreamDataMask; }
void MarkInitialized() { mFlags |= eInitializedMask; }
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
nsCacheDevice * mCacheDevice; // 4
nsCOMPtr<nsISupports> mData; // 4
nsCacheMetaData * mMetaData; // 4
PRCList mRequestQ; // 8 = 64
PRCList mDescriptorQ; // 8 = 72
};
typedef struct {
PLDHashNumber keyHash;
nsCacheEntry *cacheEntry;
} nsCacheEntryHashTableEntry;
class nsCacheEntryHashTable
{
public:
nsCacheEntryHashTable();
~nsCacheEntryHashTable();
nsresult Init();
nsCacheEntry *GetEntry( const nsCString * key);
nsresult AddEntry( nsCacheEntry *entry);
nsresult RemoveEntry( nsCacheEntry *entry);
//** enumerate entries?
private:
// PLDHashTable operation callbacks
static const void * GetKey( PLDHashTable *table, PLDHashEntryHdr *entry);
static PLDHashNumber HashKey( PLDHashTable *table, const void *key);
static PRBool MatchEntry( PLDHashTable * table,
const PLDHashEntryHdr * entry,
const void * key);
static void MoveEntry( PLDHashTable *table,
const PLDHashEntryHdr *from,
PLDHashEntryHdr *to);
static void ClearEntry( PLDHashTable *table, PLDHashEntryHdr *entry);
static void Finalize( PLDHashTable *table);
// member variables
static PLDHashTableOps ops;
PLDHashTable table;
PRBool initialized;
};
#endif // _nsCacheEntry_h_

View File

@ -0,0 +1,349 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheEntryDescriptor.cpp, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#include "nsCacheEntryDescriptor.h"
#include "nsCacheEntry.h"
#include "nsReadableUtils.h"
NS_IMPL_ISUPPORTS1(nsCacheEntryDescriptor, nsICacheEntryDescriptor)
nsCacheEntryDescriptor::nsCacheEntryDescriptor(nsCacheEntry * entry,
PRUint32 accessGranted)
: mCacheEntry(entry), mAccessGranted(accessGranted)
{
NS_INIT_ISUPPORTS();
PR_INIT_CLIST(&mListLink);
}
nsCacheEntryDescriptor::~nsCacheEntryDescriptor()
{
/* destructor code */
}
NS_METHOD
nsCacheEntryDescriptor::Create(nsCacheEntry * entry, PRUint32 accessGranted,
nsICacheEntryDescriptor ** result)
{
nsresult rv = nsnull;
nsCacheEntryDescriptor * descriptor =
new nsCacheEntryDescriptor(entry, accessGranted);
if (descriptor == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(descriptor);
rv = descriptor->QueryInterface(NS_GET_IID(nsICacheEntryDescriptor), (void**)result);
NS_RELEASE(descriptor);
return rv;
}
/* readonly attribute string key; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetKey(char ** result)
{
//** copy key, stripping clientID
nsCString * key;
nsresult rv = NS_OK;
*result = nsnull;
mCacheEntry->GetKey(&key);
nsReadingIterator<char> start;
key->BeginReading(start);
nsReadingIterator<char> end;
key->EndReading(end);
if (FindCharInReadable(':', start, end)) {
++start; // advance past clientID ':' delimiter
*result = ToNewCString( Substring(*key, start, end));
if (!*result) rv = NS_ERROR_OUT_OF_MEMORY;
} else {
NS_ASSERTION(PR_FALSE, "FindCharInRead failed to find ':'");
rv = NS_ERROR_UNEXPECTED;
}
return rv;
}
/* readonly attribute unsigned long fetchCount; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetFetchCount(PRUint32 *fetchCount)
{
if (!fetchCount) return NS_ERROR_NULL_POINTER;
mCacheEntry->GetFetchCount(fetchCount);
return NS_OK;
}
/* readonly attribute PRTime lastFetched; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetLastFetched(PRTime *lastFetched)
{
if (!lastFetched) return NS_ERROR_NULL_POINTER;
mCacheEntry->GetLastFetched(lastFetched);
return NS_OK;
}
/* readonly attribute PRTime lastValidated; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetLastValidated(PRTime *lastValidated)
{
if (!lastValidated) return NS_ERROR_NULL_POINTER;
mCacheEntry->GetLastValidated(lastValidated);
return NS_OK;
}
/* attribute PRTime expires; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetExpirationTime(PRTime *expirationTime)
{
if (!expirationTime) return NS_ERROR_NULL_POINTER;
mCacheEntry->GetExpirationTime(expirationTime);
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetExpirationTime(PRTime expirationTime)
{
mCacheEntry->SetExpirationTime(expirationTime);
return NS_OK;
}
/* boolean isStreamBased (); */
NS_IMETHODIMP nsCacheEntryDescriptor::IsStreamBased(PRBool *streamBased)
{
if (!streamBased) return NS_ERROR_NULL_POINTER;
*streamBased = mCacheEntry->IsStreamData(); //** which name is better?
return NS_OK;
}
/* attribute nsISupports cacheElement; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetCacheElement(nsISupports * *cacheElement)
{
return mCacheEntry->GetData(cacheElement);
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetCacheElement(nsISupports * cacheElement)
{
return mCacheEntry->SetData(cacheElement);
}
/* readonly attribute unsigned long accessGranted; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetAccessGranted(PRUint32 *accessGranted)
{
*accessGranted = mAccessGranted;
return NS_OK;
}
/* attribute unsigned long storageFlags; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetStorageFlags(PRUint32 *storageFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetStorageFlags(PRUint32 storageFlags)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean allowInMemory; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetAllowInMemory(PRBool *aAllowInMemory)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetAllowInMemory(PRBool aAllowInMemory)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean allowOnDisk; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetAllowOnDisk(PRBool *aAllowOnDisk)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetAllowOnDisk(PRBool aAllowOnDisk)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void doom (); */
NS_IMETHODIMP
nsCacheEntryDescriptor::Doom()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void doomAndFailPendingRequests (in nsresult status); */
NS_IMETHODIMP
nsCacheEntryDescriptor::DoomAndFailPendingRequests(nsresult status)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void truncateExistingData (in unsigned long newLength); */
NS_IMETHODIMP
nsCacheEntryDescriptor::TruncateExistingData(PRUint32 newLength)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void appendToExistingData (); */
NS_IMETHODIMP
nsCacheEntryDescriptor::AppendToExistingData()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void markValid (); */
NS_IMETHODIMP
nsCacheEntryDescriptor::MarkValid()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* string getMetaDataElement (in string key); */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetMetaDataElement(const char *key, char **result)
{
if (!key | !result) return NS_ERROR_NULL_POINTER;
nsAReadableCString *value;
*result = nsnull;
nsresult rv = mCacheEntry->GetMetaDataElement(nsLiteralCString(key), &value);
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;
}
/* void setMetadataElement (in string key, in string value); */
NS_IMETHODIMP
nsCacheEntryDescriptor::SetMetadataElement(const char *key, const char *value)
{
if (!key) return NS_ERROR_NULL_POINTER;
//** allow null value, for clearing key?
nsresult rv = mCacheEntry->SetMetaDataElement(nsLiteralCString(key),
nsLiteralCString(value));
return rv;
}
/* nsISimpleEnumerator getMetaDataEnumerator (); */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetMetaDataEnumerator(nsISimpleEnumerator **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsISupports securityInfo; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIProgressEventSink progressEventSink; */
NS_IMETHODIMP
nsCacheEntryDescriptor::GetProgressEventSink(nsIProgressEventSink * *aProgressEventSink)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::SetProgressEventSink(nsIProgressEventSink * aProgressEventSink)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::OpenInputStream(PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIInputStream **result)
{
*result = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::OpenOutputStream(PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIOutputStream **result)
{
*result = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::AsyncRead(nsIStreamListener *listener,
nsISupports * ctxt,
PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIRequest **result)
{
*result = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryDescriptor::AsyncWrite(nsIStreamProvider *provider,
nsISupports * ctxt,
PRUint32 offset,
PRUint32 count,
PRUint32 flags,
nsIRequest **result)
{
*result = nsnull;
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheEntryDescriptor.h, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#ifndef _nsCacheEntryDescriptor_h_
#define _nsCacheEntryDescriptor_h_
#include "nsICacheEntryDescriptor.h"
#include "nsCacheEntry.h"
class nsCacheEntryDescriptor : public nsICacheEntryDescriptor
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSITRANSPORT
NS_DECL_NSICACHEENTRYDESCRIPTOR
nsCacheEntryDescriptor(nsCacheEntry * entry, PRUint32 flags);
virtual ~nsCacheEntryDescriptor();
static nsresult Create(nsCacheEntry * entry, PRUint32 accessGranted,
nsICacheEntryDescriptor ** result);
/**
* routines for manipulating descriptors in PRCLists
*/
PRCList* GetListNode(void) { return &mListLink; }
static nsCacheEntryDescriptor* GetInstance(PRCList* qp) {
return (nsCacheEntryDescriptor*)
((char*)qp - offsetof(nsCacheEntryDescriptor, mListLink));
}
protected:
PRCList mListLink;
nsCacheEntry * mCacheEntry; // we are a child of the entry
PRUint32 mAccessGranted;
};
#endif // _nsCacheEntryDescriptor_h_

View File

@ -0,0 +1,170 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheMetaData.cpp, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#include "nsCacheMetaData.h"
#include "nsString.h"
/*
* nsCacheClientHashTable
*/
PLDHashTableOps
nsCacheMetaData::ops =
{
PL_DHashAllocTable,
PL_DHashFreeTable,
GetKey,
HashKey,
MatchEntry,
MoveEntry,
ClearEntry,
Finalize
};
nsCacheMetaData::nsCacheMetaData()
: initialized(0)
{
}
nsCacheMetaData::~nsCacheMetaData()
{
//** maybe we should finalize the table...
}
nsresult
nsCacheMetaData::Init()
{
nsresult rv = NS_OK;
initialized = PL_DHashTableInit(&table, &ops, nsnull,
sizeof(nsCacheMetaDataHashTableEntry), 16);
if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
nsAReadableCString *
nsCacheMetaData::GetElement(const nsAReadableCString * key)
{
PLDHashEntryHdr * hashEntry;
nsCString * result = nsnull;
NS_ASSERTION(initialized, "nsCacheMetaDataHashTable not initialized");
hashEntry = PL_DHashTableOperate(&table, key, PL_DHASH_LOOKUP);
if (PL_DHASH_ENTRY_IS_BUSY(hashEntry)) {
result = ((nsCacheMetaDataHashTableEntry *)hashEntry)->value;
}
return result;
}
nsresult
nsCacheMetaData::SetElement(const nsAReadableCString * key,
const nsAReadableCString * value)
{
nsCacheMetaDataHashTableEntry * metaEntry;
NS_ASSERTION(initialized, "nsCacheMetaDataHashTable not initialized");
if (!key) return NS_ERROR_NULL_POINTER;
//** should value == nsnull remove the key?
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;
if (value) {
metaEntry->value = new nsCString(*value);
if (metaEntry->value == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
} else {
metaEntry->value = nsnull;
}
return NS_OK;
}
//** enumerate MetaData elements
/*
* hash table operation callback functions
*/
const void *
nsCacheMetaData::GetKey( PLDHashTable * /*table*/, PLDHashEntryHdr *hashEntry)
{
return ((nsCacheMetaDataHashTableEntry *)hashEntry)->key;
}
PRBool
nsCacheMetaData::MatchEntry(PLDHashTable * /* table */,
const PLDHashEntryHdr * hashEntry,
const void * key)
{
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;
}
void
nsCacheMetaData::MoveEntry(PLDHashTable * /* table */,
const PLDHashEntryHdr *from,
PLDHashEntryHdr *to)
{
to->keyHash = from->keyHash;
((nsCacheMetaDataHashTableEntry *)to)->key =
((nsCacheMetaDataHashTableEntry *)from)->key;
((nsCacheMetaDataHashTableEntry *)to)->value =
((nsCacheMetaDataHashTableEntry *)from)->value;
}
void
nsCacheMetaData::ClearEntry(PLDHashTable * /* table */,
PLDHashEntryHdr * hashEntry)
{
((nsCacheMetaDataHashTableEntry *)hashEntry)->keyHash = 0;
((nsCacheMetaDataHashTableEntry *)hashEntry)->key = 0;
((nsCacheMetaDataHashTableEntry *)hashEntry)->value = 0;
}
void
nsCacheMetaData::Finalize(PLDHashTable * /* table */)
{
//** gee, if there's anything left in the table, maybe we should get rid of it.
}

View File

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheMetaData.h, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#ifndef _nsCacheMetaData_h_
#define _nsCacheMetaData_h_
#include "nspr.h"
#include "pldhash.h"
#include "nscore.h"
// #include "nsCOMPtr.h"
#include "nsString.h"
// #include "nsAReadableString.h"
typedef struct {
PLDHashNumber keyHash;
nsCString * key;
nsCString * value;
} nsCacheMetaDataHashTableEntry;
class nsCacheMetaData {
public:
nsCacheMetaData();
~nsCacheMetaData();
nsresult Init();
nsAReadableCString * GetElement(const nsAReadableCString * key);
nsresult SetElement(const nsAReadableCString * key,
const nsAReadableCString * value);
private:
// PLDHashTable operation callbacks
static const void * GetKey( PLDHashTable *table, PLDHashEntryHdr *entry);
static PLDHashNumber HashKey( PLDHashTable *table, const void *key);
static PRBool MatchEntry( PLDHashTable * table,
const PLDHashEntryHdr * entry,
const void * key);
static void MoveEntry( PLDHashTable *table,
const PLDHashEntryHdr *from,
PLDHashEntryHdr *to);
static void ClearEntry( PLDHashTable *table, PLDHashEntryHdr *entry);
static void Finalize( PLDHashTable *table);
// member variables
static PLDHashTableOps ops;
PLDHashTable table;
PRBool initialized;
};
#endif // _nsCacheMetaData_h

View File

@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheRequest.h, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#ifndef _nsCacheRequest_h_
#define _nsCacheRequest_h_
#include "nspr.h"
#include "nsCOMPtr.h"
#include "nsICacheListener.h"
class nsCacheRequest
{
private:
friend class nsCacheService;
friend class nsCacheEntry;
nsCacheRequest( nsCString * key,
nsICacheListener * listener,
PRUint32 accessRequested,
PRBool streamBased)
: mKey(key),
mListener(listener),
mAccessRequested(accessRequested),
mStreamBased(streamBased)
{
mRequestThread = PR_GetCurrentThread();
PR_INIT_CLIST(&mListLink);
}
virtual ~nsCacheRequest();
PRCList* GetListNode(void) { return &mListLink; }
static nsCacheRequest* GetInstance(PRCList* qp) {
return (nsCacheRequest*)
((char*)qp - offsetof(nsCacheRequest, mListLink));
}
nsCString * mKey;
nsCOMPtr<nsICacheListener> mListener;
PRUint32 mAccessRequested;
PRBool mStreamBased;
PRThread * mRequestThread;
PRCList mListLink;
};
#endif // _nsCacheRequest_h_

View File

@ -0,0 +1,442 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheService.cpp, released February 10, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 10-February-2001
*/
#include "nsCacheService.h"
#include "nsCacheDevice.h"
#include "nsMemoryCacheDevice.h"
#include "nsAutoLock.h"
#include "nsVoidArray.h"
nsCacheService * nsCacheService::gService = nsnull;
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCacheService, nsICacheService)
nsCacheService::nsCacheService()
: mCacheServiceLock(nsnull)
{
NS_INIT_REFCNT();
NS_ASSERTION(gService==nsnull, "multiple nsCacheService instances!");
gService = this;
// create list of cache devices
PR_INIT_CLIST(&mDeviceList);
}
nsCacheService::~nsCacheService()
{
if (mCacheServiceLock) // Shutdown hasn't been called yet.
(void) Shutdown();
gService = nsnull;
}
NS_IMETHODIMP
nsCacheService::Init()
{
nsresult rv;
NS_ASSERTION(mCacheServiceLock== nsnull, "nsCacheService already initialized.");
if (mCacheServiceLock)
return NS_ERROR_ALREADY_INITIALIZED;
mCacheServiceLock = PR_NewLock();
if (mCacheServiceLock == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
// initialize hashtable for client ids
rv = mClientIDs.Init();
NS_ASSERTION(NS_SUCCEEDED(rv), "mClientIDs.Init() failed");
// initialize hashtable for active cache entries
rv = mActiveEntries.Init();
if (NS_SUCCEEDED(rv)) {
// create memory cache
#if 0
nsMemoryCacheDevice *device = new nsMemoryCacheDevice;
// (void) mDeviceList.AppendElement(device);
PRUint32 deviceID = device->GetDeviceID();
#endif
if (NS_SUCCEEDED(rv)) {
// create disk cache
}
}
if (NS_FAILED(rv)) {
// if mem cache - destroy it
// if disk cache - destroy it
PR_DestroyLock(mCacheServiceLock);
mCacheServiceLock = nsnull;
// finish mActiveEntries hashtable
}
return rv;
}
NS_IMETHODIMP
nsCacheService::Shutdown()
{
NS_ASSERTION(mCacheServiceLock != nsnull,
"can't shutdown nsCacheService unless it has been initialized.");
if (mCacheServiceLock) {
//** check for pending requests...
//** finalize active entries and clientID
//** deallocate memory and disk caches
PR_DestroyLock(mCacheServiceLock);
mCacheServiceLock = nsnull;
}
return NS_OK;
}
NS_METHOD
nsCacheService::Create(nsISupports* aOuter, const nsIID& aIID, void* *aResult)
{
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;
}
nsresult
nsCacheService::CommonOpenCacheEntry(const char *clientID, const char *clientKey,
PRUint32 accessRequested, PRBool streamBased,
nsCacheRequest **request, nsCacheEntry **entry)
{
NS_ASSERTION(request && entry, "CommonOpenCacheEntry: request or entry is null");
nsAutoLock lock(mCacheServiceLock);
mClientIDs.AddClientID(clientID); // add clientID to list of clientIDs
nsCString * key = new nsCString(nsLiteralCString(clientID) +
nsLiteralCString(clientKey));
if (!key) {
return NS_ERROR_OUT_OF_MEMORY;
}
// create request
*request = new nsCacheRequest(key, (nsICacheListener *)nsnull,
accessRequested, streamBased);
// procure active entry (and queue request?)
return ActivateEntry(*request, entry);
}
NS_IMETHODIMP
nsCacheService::OpenCacheEntry(const char *clientID, const char *clientKey,
PRUint32 accessRequested, PRBool streamBased,
nsICacheEntryDescriptor **result)
{
result = nsnull;
if (!mCacheServiceLock)
return NS_ERROR_NOT_INITIALIZED;
nsCacheRequest * request = nsnull;
nsCacheEntry * entry = nsnull;
nsresult rv = CommonOpenCacheEntry(clientID, clientKey, accessRequested, streamBased,
&request, &entry);
if (NS_FAILED(rv)) return rv;
while (1) {
rv = entry->Open(request, result);
if (NS_SUCCEEDED(rv) | (rv != NS_ERROR_CACHE_ENTRY_DOOMED)) break;
rv = ActivateEntry(request, &entry);
if (NS_FAILED(rv)) break;
}
return rv;
}
NS_IMETHODIMP
nsCacheService::AsyncOpenCacheEntry(const char * clientID, const char * key,
PRUint32 accessRequested, PRBool streamBased,
nsICacheListener *listener)
{
if (!mCacheServiceLock)
return NS_ERROR_NOT_INITIALIZED;
nsCacheRequest * request = nsnull;
nsCacheEntry * entry = nsnull;
nsresult rv = CommonOpenCacheEntry(clientID, key, accessRequested, streamBased,
&request, &entry);
if (NS_SUCCEEDED(rv)) {
entry->AsyncOpen(request);
}
return rv;
}
nsresult
nsCacheService::ActivateEntry(nsCacheRequest * request,
nsCacheEntry ** result)
{
nsresult rv = NS_OK;
PRBool entryIsNew = PR_FALSE;
nsCacheDevice * device = nsnull;
NS_ASSERTION(request != nsnull, "ActivateEntry called with no request");
if (request == nsnull) return NS_ERROR_NULL_POINTER;
if (result) *result = nsnull;
// PRBool asyncRequest = (result == nsnull);
nsAutoLock lock(mCacheServiceLock); // hold monitor to keep mActiveEntries coherent
// search active entries (including those not bound to device)
nsCacheEntry *entry = mActiveEntries.GetEntry(request->mKey);
// doom existing entry if we are processing a FORCE-WRITE
if (entry && (request->mAccessRequested == nsICacheService::WRITE)) {
entry->Doom();
}
if (!entry) {
entry = new nsCacheEntry(request->mKey);
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
entryIsNew = PR_TRUE;
rv = mActiveEntries.AddEntry(entry);
if (NS_FAILED(rv)) return rv;
//** queue request
rv = SearchCacheDevices(entry, &device);
if ((rv == NS_ERROR_CACHE_KEY_NOT_FOUND) &&
!(request->mAccessRequested & nsICacheService::WRITE)) {
// this was a READ-ONLY request, deallocate entry
//** dealloc entry, call listener with error, etc.
*result = nsnull;
return NS_ERROR_CACHE_KEY_NOT_FOUND;
}
} else {
//** queue request
}
return rv;
}
nsresult
SearchCacheDevices(nsCacheEntry * entry, nsCacheDevice ** result)
{
nsresult rv = NS_OK;
nsCacheDevice * device;
*result = nsnull;
// if we don't alter the device list after initialization,
// we don't have to protect it with the monitor
//** first device
while (device) {
rv = device->ActivateEntryIfFound(entry);
if (NS_SUCCEEDED(rv)) {
*result = device;
break;
} else if (rv != NS_ERROR_CACHE_KEY_NOT_FOUND) {
//** handle errors (no memory, disk full, mismatched streamBased, whatever)
}
//** next device
}
return rv;
}
nsCacheEntry *
nsCacheService::SearchActiveEntries(const nsCString * key)
{
return nsnull;
}
NS_IMETHODIMP
nsCacheService::EnumerateDeviceIDs(nsISimpleEnumerator **_retval)
{
if (!mCacheServiceLock)
return NS_ERROR_NOT_INITIALIZED;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheService::EnumerateClientIDs(nsISimpleEnumerator **_retval)
{
if (!mCacheServiceLock)
return NS_ERROR_NOT_INITIALIZED;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheService::EnumerateEntries(const char *deviceID, const char *clientID,
nsISimpleEnumerator **_retval)
{
if (!mCacheServiceLock)
return NS_ERROR_NOT_INITIALIZED;
return NS_ERROR_NOT_IMPLEMENTED;
}
/*
* nsCacheClientHashTable
*/
PLDHashTableOps
nsCacheClientHashTable::ops =
{
PL_DHashAllocTable,
PL_DHashFreeTable,
GetKey,
HashKey,
MatchEntry,
MoveEntry,
ClearEntry,
Finalize
};
nsCacheClientHashTable::nsCacheClientHashTable()
: initialized(0)
{
}
nsCacheClientHashTable::~nsCacheClientHashTable()
{
//** maybe we should finalize the table...
}
nsresult
nsCacheClientHashTable::Init()
{
nsresult rv = NS_OK;
initialized = PL_DHashTableInit(&table, &ops, nsnull,
sizeof(nsCacheClientHashTableEntry), 16);
if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY;
return rv;
}
void
nsCacheClientHashTable::AddClientID(const char * clientID)
{
PLDHashEntryHdr *hashEntry;
char * copy;
hashEntry = PL_DHashTableOperate(&table, clientID, PL_DHASH_ADD);
if (((nsCacheClientHashTableEntry *)hashEntry)->clientID == 0) {
copy = nsCRT::strdup(clientID);
((nsCacheClientHashTableEntry *)hashEntry)->clientID = copy;
}
}
//** enumerate clientIDs
/*
* hash table operation callback functions
*/
const void *
nsCacheClientHashTable::GetKey( PLDHashTable * /*table*/, PLDHashEntryHdr *hashEntry)
{
return ((nsCacheClientHashTableEntry *)hashEntry)->clientID;
}
PRBool
nsCacheClientHashTable::MatchEntry(PLDHashTable * /* table */,
const PLDHashEntryHdr * hashEntry,
const void * key)
{
NS_ASSERTION(key != nsnull, "nsCacheClientHashTable::MatchEntry : null key");
char * clientID = ((nsCacheClientHashTableEntry *)hashEntry)->clientID;
return nsCRT::strcmp((char *)key, clientID) == 0;
}
void
nsCacheClientHashTable::MoveEntry(PLDHashTable * /* table */,
const PLDHashEntryHdr *from,
PLDHashEntryHdr *to)
{
to->keyHash = from->keyHash;
((nsCacheClientHashTableEntry *)to)->clientID =
((nsCacheClientHashTableEntry *)from)->clientID;
}
void
nsCacheClientHashTable::ClearEntry(PLDHashTable * /* table */,
PLDHashEntryHdr * hashEntry)
{
((nsCacheClientHashTableEntry *)hashEntry)->keyHash = 0;
((nsCacheClientHashTableEntry *)hashEntry)->clientID = 0;
}
void
nsCacheClientHashTable::Finalize(PLDHashTable * /* table */)
{
//** gee, if there's anything left in the table, maybe we should get rid of it.
}

View File

@ -0,0 +1,149 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsCacheService.h, released February 10, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 10-February-2001
*/
#ifndef _nsCacheService_h_
#define _nsCacheService_h_
#include "nspr.h"
#include "nsICacheService.h"
#include "nsCacheDevice.h"
#include "nsCacheEntry.h"
#include "nsCacheRequest.h"
class nsCacheDeviceElement {
public:
nsCacheDeviceElement(PRUint32 id, nsCacheDevice * cacheDevice)
: deviceID(id),
device(cacheDevice)
{
PR_INIT_CLIST(&link);
}
~nsCacheDeviceElement() {}
private:
friend class nsCacheService;
PRCList * GetListNode(void) { return &link; }
static nsCacheDeviceElement * GetInstance(PRCList * qp) {
return (nsCacheDeviceElement*)((char*)qp - offsetof(nsCacheDeviceElement, link));
}
PRCList link;
PRUint32 deviceID;
nsCacheDevice *device;
};
typedef struct {
PLDHashNumber keyHash;
char * clientID;
} nsCacheClientHashTableEntry;
class nsCacheClientHashTable
{
public:
nsCacheClientHashTable();
~nsCacheClientHashTable();
nsresult Init();
void AddClientID(const char *clientID);
//** enumerate clientIDs
private:
// PLDHashTable operation callbacks
static const void * GetKey( PLDHashTable *table, PLDHashEntryHdr *entry);
static PLDHashNumber HashKey( PLDHashTable *table, const void *key);
static PRBool MatchEntry( PLDHashTable * table,
const PLDHashEntryHdr * entry,
const void * key);
static void MoveEntry( PLDHashTable *table,
const PLDHashEntryHdr *from,
PLDHashEntryHdr *to);
static void ClearEntry( PLDHashTable *table, PLDHashEntryHdr *entry);
static void Finalize( PLDHashTable *table);
// member variables
static PLDHashTableOps ops;
PLDHashTable table;
PRBool initialized;
};
/**
* nsCacheService
*/
class nsCacheService : public nsICacheService
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICACHESERVICE
nsCacheService();
virtual ~nsCacheService();
// Define a Create method to be used with a factory:
static NS_METHOD
Create(nsISupports* outer, const nsIID& iid, void* *result);
private:
nsresult ActivateEntry(nsCacheRequest * request, nsCacheEntry ** entry);
nsCacheEntry * SearchActiveEntries(const nsCString * key);
nsresult SearchCacheDevices(nsCacheEntry *entry, nsCacheDevice ** result);
nsresult CommonOpenCacheEntry(const char *clientID, const char *clientKey,
PRUint32 accessRequested, PRBool streamBased,
nsCacheRequest **request, nsCacheEntry **entry);
/**
* Data Members
*/
static nsCacheService * gService; // "There can be only one..."
enum {
cacheServiceActiveMask = 1
};
PRLock* mCacheServiceLock;
PRCList mDeviceList;
nsCacheClientHashTable mClientIDs;
nsCacheEntryHashTable mActiveEntries;
PRCList mDoomedEntries;
};
#endif // _nsCacheService_h_

View File

@ -0,0 +1,86 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsMemoryCacheDevice.cpp, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#include "nsDiskCacheDevice.h"
#include "nsICacheService.h"
nsDiskCacheDevice::nsDiskCacheDevice()
: nsCacheDevice(kDiskCacheID)
{
}
nsDiskCacheDevice::~nsDiskCacheDevice()
{
}
nsresult
nsDiskCacheDevice::Init()
{
return NS_OK;
}
nsresult
nsDiskCacheDevice::Create(nsCacheDevice **result)
{
nsDiskCacheDevice * device = new nsDiskCacheDevice();
if (!device) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = device->Init();
if (NS_FAILED(rv)) {
delete device;
device = nsnull;
}
*result = device;
return rv;
}
nsresult
nsDiskCacheDevice::ActivateEntryIfFound(nsCacheEntry * entry)
{
return NS_ERROR_CACHE_KEY_NOT_FOUND;
}
nsresult
nsDiskCacheDevice::DeactivateEntry(nsCacheEntry * entry)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsDiskCacheDevice::BindEntry(nsCacheEntry * entry)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//** need stream factory methods
//** need methods for enumerating entries

View File

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsMemoryCacheDevice.h, released February 20, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 20-February-2001
*/
#ifndef _nsDiskCacheDevice_h_
#define _nsDiskCacheDevice_h_
#include "nsCacheDevice.h"
class nsDiskCacheDevice : public nsCacheDevice
{
public:
enum { kDiskCacheID = 0x4469736B }; // 'Disk'
nsDiskCacheDevice();
virtual ~nsDiskCacheDevice();
nsresult Init();
static nsresult Create(nsCacheDevice **result);
virtual nsresult ActivateEntryIfFound( nsCacheEntry * entry );
virtual nsresult DeactivateEntry( nsCacheEntry * entry );
virtual nsresult BindEntry( nsCacheEntry * entry );
private:
};
#endif // _nsDiskCacheDevice_h_

View File

@ -0,0 +1,119 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsMemoryCacheDevice.cpp, released February 22, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 22-February-2001
*/
#include "nsMemoryCacheDevice.h"
#include "nsICacheService.h"
nsMemoryCacheDevice::nsMemoryCacheDevice()
: nsCacheDevice(kMemoryCacheID)
{
}
nsMemoryCacheDevice::~nsMemoryCacheDevice()
{
//** dealloc all memory
}
nsresult
nsMemoryCacheDevice::Init()
{
nsresult rv;
rv = mInactiveEntries.Init();
//** read user prefs for memory cache limits
return rv;
}
nsresult
nsMemoryCacheDevice::Create(nsCacheDevice **result)
{
nsMemoryCacheDevice * device = new nsMemoryCacheDevice();
if (!device) return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = device->Init();
if (NS_FAILED(rv)) {
delete device;
device = nsnull;
}
*result = device;
return rv;
}
nsresult
nsMemoryCacheDevice::ActivateEntryIfFound(nsCacheEntry * entry)
{
//** get the key from the entry
nsCString * key = nsnull; //** = key from entry
nsCacheEntry * ourEntry = mInactiveEntries.GetEntry(key);
if (!ourEntry) {
*entry = nsnull;
return NS_ERROR_CACHE_KEY_NOT_FOUND;
}
//** need entry->UpdateFrom(ourEntry);
entry->MarkActive(); // so we don't evict it
//** find eviction element and move it to the tail of the queue
return NS_OK;
}
nsresult
nsMemoryCacheDevice::DeactivateEntry(nsCacheEntry * entry)
{
nsCString * key;
entry->GetKey(&key);
nsCacheEntry * ourEntry = mInactiveEntries.GetEntry(key);
NS_ASSERTION(ourEntry, "DeactivateEntry called for an entry we don't have!");
if (!ourEntry)
return NS_ERROR_INVALID_POINTER;
//** need ourEntry->UpdateFrom(entry);
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult
nsMemoryCacheDevice::BindEntry(nsCacheEntry * entry)
{
nsresult rv = mInactiveEntries.AddEntry(entry);
if (NS_FAILED(rv))
return rv;
//** add size of entry to memory totals
return NS_ERROR_NOT_IMPLEMENTED;
}
//** need stream factory methods
//** need methods for enumerating entries
//** need notification methods for size changes on non-streamBased entries (for eviction)

View File

@ -0,0 +1,89 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is nsMemoryCacheDevice.h, released February 20, 2001.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Gordon Sheridan, 20-February-2001
*/
#ifndef _nsMemoryCacheDevice_h_
#define _nsMemoryCacheDevice_h_
#include "nsCacheDevice.h"
#include "pldhash.h"
#include "nsCacheEntry.h"
class nsMemoryCacheDevice : public nsCacheDevice
{
public:
enum { kMemoryCacheID = 0x4d656d43 }; // 'MemC'
nsMemoryCacheDevice();
virtual ~nsMemoryCacheDevice();
nsresult Init();
static nsresult Create(nsCacheDevice **result);
virtual nsresult ActivateEntryIfFound( nsCacheEntry * entry );
virtual nsresult DeactivateEntry( nsCacheEntry * entry );
virtual nsresult BindEntry( nsCacheEntry * entry );
private:
nsCacheEntryHashTable mInactiveEntries;
PRUint32 mTemporaryMaxLimit;
PRUint32 mNormalMaxLimit;
PRUint32 mCurrentTotal;
PRCList mEvictionList;
//** what other stats do we want to keep?
};
class nsMemoryEvictionElement
{
private:
friend class nsMemoryCacheDevice;
nsMemoryEvictionElement(nsCacheEntry *entry)
: entry(entry)
{
PR_INIT_CLIST(&link);
}
~nsMemoryEvictionElement() {}
PRCList * GetListNode(void) { return &link; }
static nsMemoryEvictionElement * GetInstance(PRCList * qp) {
return (nsMemoryEvictionElement*)((char*)qp -
offsetof(nsMemoryEvictionElement, link));
}
PRCList link;
nsCacheEntry * entry;
//** need backpointers from entry, or more sophisticated structure to optimize
//** finding the eviction element quickly. Otherwise we just walk the list :-(
};
#endif // _nsMemoryCacheDevice_h_