Landing of CacheIntegration_BRANCH in support of bug #8305 (Implement cache)

git-svn-id: svn://10.0.0.236/trunk@55511 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
fur%netscape.com 1999-12-07 02:07:31 +00:00
parent aadd0fb038
commit cb8d4be3b8
91 changed files with 7933 additions and 8833 deletions

View File

@ -26,7 +26,13 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public obj mgr pref module tests
DIRS = \
public \
memcache \
filecache \
mgr \
build \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -22,12 +22,12 @@
DEPTH=..\..
DIRS= \
public \
obj \
public \
mgr \
pref \
module \
tests \
memcache \
filecache \
build \
$(NULL)
include <$(DEPTH)\config\rules.mak>
include <$(DEPTH)\config\rules.mak>

54
mozilla/netwerk/cache/build/Makefile.in vendored Normal file
View File

@ -0,0 +1,54 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkcache
IS_COMPONENT = 1
CPPSRCS = nsNetDataCacheModule.cpp
SHARED_LIBRARY_LIBS = \
$(DIST)/lib/libnkcachemgr_s.a \
$(DIST)/lib/libnkfilecache_s.a \
$(DIST)/lib/libnkmemcache_s.a \
$(DIST)/lib/libmozdbm_s.a \
$(DIST)/lib/libxpcomio_s.a \
$(NULL)
LOCAL_INCLUDES = \
-I$(DEPTH)/netwerk/cache/memcache \
-I$(DEPTH)/netwerk/cache/filecache \
-I$(DEPTH)/netwerk/cache/mgr \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(MKSHLIB_FORCE_ALL) \
$(SHARED_LIBRARY_LIBS) \
$(MKSHLIB_UNFORCE_ALL) \
$(NULL)
include $(topsrcdir)/config/rules.mk
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile

View File

@ -17,44 +17,35 @@
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE=nkcache
MODULE=cachepref
IS_COMPONENT=1
MAKE_OBJ_TYPE=DLL
DLLNAME=cachepref
DLLNAME=nkcache
DLL=.\$(OBJDIR)\$(DLLNAME).dll
LLIBS= $(LLIBS) \
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
CPP_OBJS= \
.\$(OBJDIR)\nsNetDataCacheModule.obj \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsCachePref.obj \
$(NULL)
LLIBS= \
$(DIST)\lib\nkcachemgr_s.lib \
$(DIST)\lib\nkfilecache_s.lib \
$(DIST)\lib\nkmemcache_s.lib \
$(DIST)\lib\dbm32.lib \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR)
LOCAL_INCLUDES= -I. \
-I..\public \
-I..\include \
INCLUDES = $(LOCAL_INCLUDES)
REQUIRES = nspr
INCS = $(INCS) \
-I..\include \
-I..\public \
-I$(DEPTH)\dist\include \
INCS = $(INCS) \
-I$(DEPTH)\netwerk\cache\memcache \
-I$(DEPTH)\netwerk\cache\filecache \
-I$(DEPTH)\netwerk\cache\mgr \
$(NULL)
include <$(DEPTH)\config\rules.mak>
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) $(DLL) $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@ -0,0 +1,49 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsCOMPtr.h"
#include "nsIModule.h"
#include "nscore.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIGenericFactory.h"
#include "nsINetDataCache.h"
#include "nsINetDataCacheManager.h"
#include "nsMemCacheCID.h"
#include "nsMemCache.h"
#include "nsNetDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsCacheManager.h"
// Factory method to create a new nsMemCache instance. Used
// by nsNetDataCacheModule
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMemCache, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsNetDiskCache, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsCacheManager, Init)
static nsModuleComponentInfo components[] = {
{ "Memory Cache", NS_MEM_CACHE_FACTORY_CID, NS_NETWORK_MEMORY_CACHE_PROGID, nsMemCacheConstructor },
{ "File Cache", NS_NETDISKCACHE_CID, NS_NETWORK_FILE_CACHE_PROGID, nsNetDiskCacheConstructor },
{ "Cache Manager",NS_CACHE_MANAGER_CID, NS_NETWORK_CACHE_MANAGER_PROGID,nsCacheManagerConstructor }
};
NS_IMPL_NSGETMODULE("Network Data Cache", components)

View File

@ -0,0 +1,56 @@
#
# 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 Mozilla Communicator.
#
# The Initial Developer of the Original Code is Intel Corp.
# Portions created by Intel Corp. are
# Copyright (C) 1999, 1999 Intel Corp. All
# Rights Reserved.
#
# Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
# Carl Wong <carl.wong@intel.com>
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkfilecache_s
REQUIRES = nspr dbm
EXTRA_DSO_LDOPTS += -L$(DIST)/lib -lmozdbm_s
EXPORTS=nsNetDiskCacheCID.h
CPPSRCS = \
nsDBAccessor.cpp\
nsDBEnumerator.cpp \
nsNetDiskCache.cpp \
nsDiskCacheRecord.cpp \
nsDiskCacheRecordChannel.cpp \
$(NULL)
EXTRA_LIBS = $(NSPR_LIBS)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,44 @@
#!gmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = nkcache
LIBRARY_NAME = nkfilecache_s
CPP_OBJS= \
.\$(OBJDIR)\nsDBAccessor.obj \
.\$(OBJDIR)\nsDBEnumerator.obj \
.\$(OBJDIR)\nsNetDiskCache.obj \
.\$(OBJDIR)\nsDiskCacheRecord.obj \
.\$(OBJDIR)\nsDiskCacheRecordChannel.obj \
$(NULL)
EXPORTS=nsNetDiskCacheCID.h
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -rf $(OBJDIR)
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@ -0,0 +1,351 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#include "nsDBAccessor.h"
#include "nscore.h"
#include "prtypes.h"
#include "plhash.h"
#include "nsCRT.h"
#include "nsAutoLock.h"
nsDBAccessor::nsDBAccessor() :
mDB(0) ,
mSessionID(0) ,
mSessionCntr(0)
{
NS_INIT_REFCNT();
}
nsDBAccessor::~nsDBAccessor()
{
printf(" ~nsDBAccessor\n") ;
Shutdown() ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDBAccessor, NS_GET_IID(nsIDBAccessor))
///////////////////////////////////////////////////////////
// nsIDBAccessor methods
NS_IMETHODIMP
nsDBAccessor::Init(nsIFileSpec* dbfile)
{
// FUR - lock not needed
m_Lock = PR_NewLock() ;
if(!m_Lock)
return NS_ERROR_OUT_OF_MEMORY ;
char* dbname ;
// this should cover all platforms.
dbfile->GetNativePath(&dbname) ;
// FUR - how is page size chosen ? It's worth putting a comment
// in here about the possible usefulness of tuning these parameters
HASHINFO hash_info = {
16*1024 , /* bucket size */
0 , /* fill factor */
0 , /* number of elements */
0 , /* bytes to cache */
0 , /* hash function */
0} ; /* byte order */
// FUR - lock not needed
nsAutoLock lock(m_Lock) ;
mDB = dbopen(dbname,
O_RDWR | O_CREAT ,
0600 ,
DB_HASH ,
& hash_info) ;
// FUR - does dbname have to be free'ed ?
if(!mDB)
return NS_ERROR_FAILURE ;
// set mSessionID
// FUR - Why the +1 ? (No need for key to be NUL-terminated string.)
PRUint32 len = PL_strlen(SessionKey)+1 ;
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SessionKey) ;
db_key.size = len ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == -1) {
NS_ERROR("ERROR: failed get session id in database.") ;
return NS_ERROR_FAILURE ;
}
if(status == 0) {
// get the last session id
PRInt16 *old_ID = NS_STATIC_CAST(PRInt16*, db_data.data) ;
if(*old_ID < ini_sessionID) {
NS_ERROR("ERROR: Bad Session ID in database, corrupted db.") ;
return NS_ERROR_FAILURE ;
}
// FUR - need to comment out all printfs, or turn them into PR_LOG statements
printf("found previous session, id = %d\n", *old_ID) ;
mSessionID = *old_ID + 1 ;
}
else if(status == 1) {
// must be a new db
mSessionID = ini_sessionID ;
}
db_data.data = NS_REINTERPRET_CAST(void*, &mSessionID) ;
db_data.size = sizeof(PRInt16) ;
// store the new session id
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
else {
NS_ERROR("reset session ID failure.") ;
return NS_ERROR_FAILURE ;
}
}
NS_IMETHODIMP
nsDBAccessor::Shutdown(void)
{
if(mDB) {
(*mDB->sync)(mDB, 0) ;
(*mDB->close)(mDB) ;
mDB = nsnull ;
}
// FUR - locks not necessary
if(m_Lock)
PR_DestroyLock(m_Lock);
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::Get(PRInt32 aID, void** anEntry, PRUint32 *aLength)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
NS_ASSERTION(mDB, "no database") ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
int status = 0 ;
status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
return NS_OK ;
}
else if(status == 1)
return NS_OK ;
else
return NS_ERROR_FAILURE ;
}
NS_IMETHODIMP
nsDBAccessor::Put(PRInt32 aID, void* anEntry, PRUint32 aLength)
{
NS_ASSERTION(mDB, "no database") ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
db_data.data = anEntry ;
db_data.size = aLength ;
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
// FUR - I would avoid unnecessary sync'ing for performance's
// sake. Maybe you could limit sync to max rate of, say, once
// every few seconds by keeping track of last sync time, using PR_Now().
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
else {
// FUR - Try to avoid using NS_ERROR unless error is unrecoverable and serious
NS_ERROR("ERROR: Failed to put anEntry into db.\n") ;
return NS_ERROR_FAILURE ;
}
}
/*
* It's more important to remove the id->metadata entry first since
* key->id mapping is just a reference
*/
NS_IMETHODIMP
nsDBAccessor::Del(PRInt32 aID, void* anEntry, PRUint32 aLength)
{
NS_ASSERTION(mDB, "no database") ;
// FUR - no locks necessary
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key ;
// delete recordID->metadata
db_key.data = NS_REINTERPRET_CAST(void*, &aID) ;
db_key.size = sizeof(PRInt32) ;
PRInt32 status = -1 ;
status = (*mDB->del)(mDB, &db_key, 0) ;
if(-1 == status) {
// FUR - no printf's, use PR_LOG, NS_WARNING, or NS_ASSERTION, as the situation warrants
printf(" delete error\n") ;
return NS_ERROR_FAILURE ;
}
// delete key->recordID
db_key.data = anEntry ;
db_key.size = aLength ;
status = (*mDB->del)(mDB, &db_key, 0) ;
if(-1 == status) {
// FUR - no printf's
printf(" delete error\n") ;
return NS_ERROR_FAILURE ;
}
// FUR - Defer sync ? See above
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::GetID(const char* key, PRUint32 length, PRInt32* aID)
{
NS_ASSERTION(mDB, "no database") ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, key) ;
db_key.size = length ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == 0) {
// found recordID
*aID = *(NS_REINTERPRET_CAST(PRInt32*, db_data.data)) ;
return NS_OK ;
}
else if(status == 1) {
// create a new one
PRInt32 id = 0 ;
id = mSessionID << 16 | mSessionCntr++ ;
// add new id into mDB
db_data.data = NS_REINTERPRET_CAST(void*, &id) ;
db_data.size = sizeof(PRInt32) ;
status = (*mDB->put)(mDB, &db_key, &db_data, 0) ;
if(status != 0) {
NS_ERROR("updating db failure.") ;
return NS_ERROR_FAILURE ;
}
// FUR - defer sync ?
(*mDB->sync)(mDB, 0) ;
*aID = id ;
return NS_OK ;
}
else {
NS_ERROR("ERROR: keydb failure.") ;
return NS_ERROR_FAILURE ;
}
}
NS_IMETHODIMP
nsDBAccessor::EnumEntry(void** anEntry, PRUint32* aLength, PRBool bReset)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
NS_ASSERTION(mDB, "no database") ;
PRUint32 flag ;
if(bReset)
flag = R_FIRST ;
else
flag = R_NEXT ;
// Lock the db
nsAutoLock lock(m_Lock) ;
DBT db_key, db_data ;
// FUR - +1 unnecessary ?
PRUint32 len = PL_strlen(SessionKey)+1 ;
int status ;
do {
status = (*mDB->seq)(mDB, &db_key, &db_data, flag) ;
flag = R_NEXT ;
if(status == -1)
return NS_ERROR_FAILURE ;
// get next if it's a key->recordID
if(db_key.size > sizeof(PRInt32) && db_data.size == sizeof(PRInt32))
continue ;
// get next if it's a sessionID entry
if(db_key.size == len && db_data.size == sizeof(PRInt16))
continue ;
// recordID is always 32 bits long
if(db_key.size == sizeof(PRInt32))
break ;
} while(!status) ;
if (0 == status) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
}
return NS_OK ;
}

View File

@ -0,0 +1,68 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#ifndef _NSIDBACCESSOR_H_
#define _NSIDBACCESSOR_H_
#include "nsIDBAccessor.h"
#include "mcom_db.h"
// bogus string for the key of session id
// FUR - suggest "SK" instead of "^^"
static const char * const SessionKey = "^^" ;
// initial session id number
static const PRInt16 ini_sessionID = 0xff ;
class nsDBAccessor : public nsIDBAccessor
{
public:
NS_DECL_ISUPPORTS
nsDBAccessor() ;
virtual ~nsDBAccessor() ;
NS_IMETHOD Init(nsIFileSpec* dbfile) ;
NS_IMETHOD Shutdown(void) ;
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) ;
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) ;
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) ;
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) ;
protected:
private:
DB * mDB ;
PRInt16 mSessionID ;
PRInt16 mSessionCntr ;
PRLock * m_Lock ;
} ;
#endif // _NSIDBACCESSOR_H_

View File

@ -0,0 +1,97 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
nsDBEnumerator::nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) :
m_DB(aDB) ,
m_DiskCache(aCache) ,
tempEntry(0) ,
tempEntry_length(0) ,
m_CacheEntry(0) ,
bReset(PR_TRUE)
{
NS_INIT_REFCNT();
}
nsDBEnumerator::~nsDBEnumerator()
{
// printf(" ~nsDBEnumerator()\n") ;
NS_IF_RELEASE(m_CacheEntry) ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDBEnumerator, NS_GET_IID(nsIEnumerator))
/////////////////////////////////////////////////////////////////
// nsISimpleEnumerator methods
NS_IMETHODIMP
nsDBEnumerator::HasMoreElements(PRBool *_retval)
{
*_retval = PR_FALSE ;
m_DB->EnumEntry(&tempEntry, &tempEntry_length, bReset) ;
bReset = PR_FALSE ;
if(tempEntry && tempEntry_length != 0)
*_retval = PR_TRUE ;
return NS_OK ;
}
// this routine does not create a new item by itself
// Rather it reuses the item inside the object. So if you need to use the
// item later, you have to
// create a new item specifically, using copy constructor or some other dup
// function. And don't forget to release it after you're done
//
NS_IMETHODIMP
nsDBEnumerator::GetNext(nsISupports **_retval)
{
if(!m_CacheEntry) {
m_CacheEntry = new nsDiskCacheRecord(m_DB, m_DiskCache) ;
if(m_CacheEntry)
NS_ADDREF(m_CacheEntry) ;
else
return NS_ERROR_OUT_OF_MEMORY ;
}
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsresult rv = m_CacheEntry->RetrieveInfo(tempEntry, tempEntry_length) ;
if(NS_FAILED(rv))
return rv ;
*_retval = NS_STATIC_CAST(nsISupports*, m_CacheEntry) ;
NS_ADDREF(*_retval) ; // all good getter addref
return NS_OK ;
}

View File

@ -0,0 +1,61 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#ifndef _NS_DBENUMERATOR_H_
#define _NS_DBENUMERATOR_H_
#include "nsISimpleEnumerator.h"
#include "nsINetDataCacheRecord.h"
#include "nsIDBAccessor.h"
#include "nsCOMPtr.h"
#include "nsNetDiskCache.h"
#include "nsDiskCacheRecord.h"
class nsCachedDiskData ; /* forward decl */
class nsDBEnumerator : public nsISimpleEnumerator {
public:
NS_DECL_ISUPPORTS
// FUR can use NS_DECL_NSISIMPLEENUMERATOR here
/* boolean HasMoreElements (); */
NS_IMETHOD HasMoreElements(PRBool *_retval) ;
/* nsISupports GetNext (); */
NS_IMETHOD GetNext(nsISupports **_retval) ;
nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) ;
virtual ~nsDBEnumerator() ;
// FUR all members should be prefixed by 'm', e.g. mbReset
private:
nsCOMPtr<nsIDBAccessor> m_DB ;
nsCOMPtr<nsNetDiskCache> m_DiskCache ;
void * tempEntry ;
PRUint32 tempEntry_length ;
nsDiskCacheRecord* m_CacheEntry ;
PRBool bReset ;
};
#endif // _NS_DBENUMERATOR_H_

View File

@ -0,0 +1,451 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsDiskCacheRecord.h"
#include "nsINetDataDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsDiskCacheRecordChannel.h"
#include "nsFileStream.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIProtocolHandler.h"
#include "nsIIOService.h"
#include "nsIAllocator.h"
#include "plstr.h"
#include "prprf.h"
#include "prmem.h"
#include "prlog.h"
#include "prtypes.h"
#include "netCore.h"
#include "nsDBAccessor.h"
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
ERROR! Must have a byte order
#endif
#ifdef IS_LITTLE_ENDIAN
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
#else
#define COPY_INT32(_a,_b) /* swap */ \
do { \
((char *)(_a))[0] = ((char *)(_b))[3]; \
((char *)(_a))[1] = ((char *)(_b))[2]; \
((char *)(_a))[2] = ((char *)(_b))[1]; \
((char *)(_a))[3] = ((char *)(_b))[0]; \
} while(0)
#endif
nsDiskCacheRecord::nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) :
mKey(0) ,
mKeyLength(0) ,
mRecordID(0) ,
mMetaData(0) ,
mMetaDataLength(0) ,
mDB(db) ,
mInfo(0) ,
mInfoSize(0) ,
mNumChannels(0) ,
mDiskCache(aCache)
{
NS_INIT_REFCNT();
}
// mem alloced. so caller should do free() on key.
NS_IMETHODIMP
nsDiskCacheRecord::Init(const char* key, PRUint32 length)
{
NS_NewFileSpec(getter_AddRefs(mFile));
if(!mFile)
return NS_ERROR_OUT_OF_MEMORY ;
// copy key
mKeyLength = length ;
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!mKey)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mKey, key, length) ;
// get RecordID
// FUR!! Another disk access ? If called from GetCachedData, ID is already known
mDB->GetID(key, length, &mRecordID) ;
// FUR - check for GetID failure
// setup the file name
nsCOMPtr<nsIFileSpec> dbFolder ;
mDiskCache->GetDiskCacheFolder(getter_AddRefs(dbFolder)) ;
nsresult rv = mFile->FromFileSpec(dbFolder) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
// dir is a hash result of mRecordID%32, hope it's enough
char filename[9], dirName[3] ;
// FUR!! - should the format string be "%.02x". How does this work !?
PR_snprintf(dirName, 3, "%.2x", (((PRUint32)mRecordID) % 32)) ;
mFile->AppendRelativeUnixPath(dirName) ;
// FUR!! - should the format string be "%.08x". How does this work !?
PR_snprintf(filename, 9, "%.8x", mRecordID) ;
mFile->AppendRelativeUnixPath(filename) ;
return NS_OK ;
}
nsDiskCacheRecord::~nsDiskCacheRecord()
{
// printf(" ~nsDiskCacheRecord()\n") ;
if(mKey)
nsAllocator::Free(mKey) ;
if(mMetaData)
nsAllocator::Free(mMetaData) ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDiskCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
///////////////////////////////////////////////////////////////////////
// nsINetDataCacheRecord methods
// yes, mem alloced on *_retval.
NS_IMETHODIMP
nsDiskCacheRecord::GetKey(PRUint32 *length, char** _retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*length = mKeyLength ;
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!*_retval)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(*_retval, mKey, mKeyLength) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetRecordID(PRInt32* aRecordID)
{
*aRecordID = mRecordID ;
return NS_OK ;
}
// yes, mem alloced on *_retval.
NS_IMETHODIMP
nsDiskCacheRecord::GetMetaData(PRUint32 *length, char **_retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
// always null the return value first.
*_retval = nsnull ;
*length = mMetaDataLength ;
if(mMetaDataLength) {
*_retval = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!*_retval)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(*_retval, mMetaData, mMetaDataLength) ;
}
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::SetMetaData(PRUint32 length, const char* data)
{
// set the mMetaData
mMetaDataLength = length ;
if(mMetaData)
nsAllocator::Free(mMetaData) ;
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!mMetaData) {
return NS_ERROR_OUT_OF_MEMORY ;
}
memcpy(mMetaData, data, length) ;
// Generate mInfo
nsresult rv = GenInfo() ;
if(NS_FAILED(rv))
return rv ;
// write through into mDB
rv = mDB->Put(mRecordID, mInfo, mInfoSize) ;
// FUR - mInfo leaking ?
return rv ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
{
return mFile->GetFileSize(aStoredContentLength) ;
}
// untill nsIFileSpec::Truncate() is in, we have to do all this ugly stuff
NS_IMETHODIMP
nsDiskCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
{
PRUint32 len = 0 ;
nsresult rv = mFile->GetFileSize(&len) ;
if(NS_FAILED(rv))
return rv ;
if(len < aStoredContentLength)
{
NS_ERROR("Error: can not set filesize to something bigger than itself.\n") ;
return NS_ERROR_FAILURE ;
}
else
return mFile->Truncate(aStoredContentLength) ;
}
NS_IMETHODIMP
nsDiskCacheRecord::Delete(void)
{
if(mNumChannels)
return NS_ERROR_NOT_AVAILABLE ;
PRUint32 len ;
mFile->GetFileSize(&len) ;
nsFileSpec cache_file ;
nsresult rv = mFile->GetFileSpec(&cache_file) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
cache_file.Delete(PR_TRUE) ;
// updata the storage size
mDiskCache->m_StorageInUse -= len ;
rv = mDB->Del(mRecordID, mKey, mKeyLength) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
else
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::GetFilename(nsIFileSpec * *aFilename)
{
if(!aFilename)
return NS_ERROR_NULL_POINTER ;
*aFilename = mFile ;
NS_ADDREF(*aFilename) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecord::NewChannel(nsILoadGroup *loadGroup, nsIChannel **_retval)
{
nsDiskCacheRecordChannel* channel = new nsDiskCacheRecordChannel(this, loadGroup) ;
if(!channel)
return NS_ERROR_OUT_OF_MEMORY ;
nsresult rv = channel->Init() ;
if(NS_FAILED(rv))
return rv ;
NS_ADDREF(channel) ;
*_retval = NS_STATIC_CAST(nsIChannel*, channel) ;
return NS_OK ;
}
//////////////////////////////////////////////////////////////////////////
// nsDiskCacheRecord methods
// file name is represented by a url string. I hope this would be more
// generic
nsresult
nsDiskCacheRecord::GenInfo()
{
if(mInfo)
nsAllocator::Free(mInfo) ;
char* file_url=nsnull ;
PRUint32 name_len ;
mFile->GetURLString(&file_url) ;
name_len = PL_strlen(file_url)+1 ;
mInfoSize = sizeof(PRUint32) ; // checksum for mInfoSize
mInfoSize += sizeof(PRInt32) ; // RecordID
mInfoSize += sizeof(PRUint32) ; // key length
mInfoSize += mKeyLength ; // key
mInfoSize += sizeof(PRUint32) ; // metadata length
mInfoSize += mMetaDataLength ; // metadata
mInfoSize += sizeof(PRUint32) ; // filename length
mInfoSize += name_len ; // filename
void* newInfo = nsAllocator::Alloc(mInfoSize*sizeof(char)) ;
if(!newInfo) {
return NS_ERROR_OUT_OF_MEMORY ;
}
// copy the checksum mInfoSize
char* cur_ptr = NS_STATIC_CAST(char*, newInfo) ;
COPY_INT32(cur_ptr, &mInfoSize) ;
cur_ptr += sizeof(PRUint32) ;
// copy RecordID
COPY_INT32(cur_ptr, &mRecordID) ;
cur_ptr += sizeof(PRInt32) ;
// copy key length
COPY_INT32(cur_ptr, &mKeyLength) ;
cur_ptr += sizeof(PRUint32) ;
// copy key
memcpy(cur_ptr, mKey, mKeyLength) ;
cur_ptr += mKeyLength ;
// copy metadata length
COPY_INT32(cur_ptr, &mMetaDataLength) ;
cur_ptr += sizeof(PRUint32) ;
// copy metadata
memcpy(cur_ptr, mMetaData, mMetaDataLength) ;
cur_ptr += mMetaDataLength ;
// copy file name length
COPY_INT32(cur_ptr, &name_len) ;
cur_ptr += sizeof(PRUint32) ;
// copy file name
memcpy(cur_ptr, file_url, name_len) ;
cur_ptr += name_len ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, newInfo) + mInfoSize);
mInfo = newInfo ;
return NS_OK ;
}
/*
* This Method suppose to get all the info from the db record
* and set them to accroding members. the original values
* will all be overwritten. only minimal error checking is performed.
*/
NS_IMETHODIMP
nsDiskCacheRecord::RetrieveInfo(void* aInfo, PRUint32 aInfoLength)
{
// reset everything
if(mInfo) {
nsAllocator::Free(mInfo) ;
mInfo = nsnull ;
}
if(mKey) {
nsAllocator::Free(mKey) ;
mKey = nsnull ;
}
if(mMetaData) {
nsAllocator::Free(mMetaData) ;
mMetaData = nsnull ;
}
char * cur_ptr = NS_STATIC_CAST(char*, aInfo) ;
char* file_url ;
PRUint32 name_len ;
// set mInfoSize
COPY_INT32(&mInfoSize, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// check this at least
if(mInfoSize != aInfoLength)
return NS_ERROR_FAILURE ;
// set mRecordID
COPY_INT32(&mRecordID, cur_ptr) ;
cur_ptr += sizeof(PRInt32) ;
// set mKeyLength
COPY_INT32(&mKeyLength, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// set mKey
mKey = NS_STATIC_CAST(char*, nsAllocator::Alloc(mKeyLength*sizeof(char))) ;
if(!mKey)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mKey, cur_ptr, mKeyLength) ;
cur_ptr += mKeyLength ;
PRInt32 id ;
mDB->GetID(mKey, mKeyLength, &id) ;
NS_ASSERTION(id==mRecordID, "\t ++++++ bad record, somethings wrong\n") ;
// set mMetaDataLength
COPY_INT32(&mMetaDataLength, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// set mMetaData
mMetaData = NS_STATIC_CAST(char*, nsAllocator::Alloc(mMetaDataLength*sizeof(char))) ;
if(!mMetaData)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(mMetaData, cur_ptr, mMetaDataLength) ;
cur_ptr += mMetaDataLength ;
// get mFile name length
COPY_INT32(&name_len, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// get mFile native name
file_url = NS_STATIC_CAST(char*, nsAllocator::Alloc(name_len*sizeof(char))) ;
if(!file_url)
return NS_ERROR_OUT_OF_MEMORY ;
memcpy(file_url, cur_ptr, name_len) ;
cur_ptr += name_len ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, aInfo) + mInfoSize);
// create mFile if Init() isn't called
if(!mFile) {
NS_NewFileSpec(getter_AddRefs(mFile));
if(!mFile)
return NS_ERROR_OUT_OF_MEMORY ;
}
// setup mFile
mFile->SetURLString(file_url) ;
return NS_OK ;
}

View File

@ -0,0 +1,70 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _NET_CACHEDDISKDATA_H_
#define _NET_CACHEDDISKDATA_H_
#include "nsINetDataCacheRecord.h"
#include "nsCOMPtr.h"
#include "nsIDBAccessor.h"
#include "prtypes.h"
#include "nsILoadGroup.h"
#include "nsIFileChannel.h"
#include "nsNetDiskCache.h"
class nsDiskCacheRecord : public nsINetDataCacheRecord
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHERECORD
protected:
nsDiskCacheRecord(nsIDBAccessor* db, nsNetDiskCache* aCache) ;
virtual ~nsDiskCacheRecord() ;
NS_IMETHOD RetrieveInfo(void* aInfo, PRUint32 aInfoLength) ;
NS_IMETHOD Init(const char* key, PRUint32 length) ;
nsresult GenInfo(void) ;
private:
char* mKey ;
PRUint32 mKeyLength ;
PRInt32 mRecordID ;
char* mMetaData ;
PRUint32 mMetaDataLength ;
nsCOMPtr<nsIFileSpec> mFile ;
nsCOMPtr<nsIDBAccessor> mDB ;
void* mInfo ;
PRUint32 mInfoSize ;
PRUint32 mNumChannels ;
nsCOMPtr<nsNetDiskCache> mDiskCache ;
friend class nsDiskCacheRecordChannel ;
friend class nsDBEnumerator ;
friend class nsNetDiskCache ;
} ;
#endif // _NET_CACHEDDISKDATA_H_

View File

@ -0,0 +1,392 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsDiskCacheRecordChannel.h"
//#include "nsFileTransport.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIOutputStream.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
// This is copied from nsMemCacheChannel, We should consolidate these two.
class WriteStreamWrapper : public nsIOutputStream
{
public:
WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
nsIOutputStream *aBaseStream) ;
virtual ~WriteStreamWrapper() ;
static nsresult
Create(nsDiskCacheRecordChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) ;
NS_DECL_ISUPPORTS
NS_DECL_NSIBASESTREAM
NS_DECL_NSIOUTPUTSTREAM
private:
nsDiskCacheRecordChannel* mChannel;
nsCOMPtr<nsIOutputStream> mBaseStream;
} ;
// implement nsISupports
NS_IMPL_ISUPPORTS(WriteStreamWrapper, NS_GET_IID(nsIOutputStream))
WriteStreamWrapper::WriteStreamWrapper(nsDiskCacheRecordChannel* aChannel,
nsIOutputStream *aBaseStream)
: mChannel(aChannel), mBaseStream(aBaseStream)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
WriteStreamWrapper::~WriteStreamWrapper()
{
NS_RELEASE(mChannel);
}
nsresult
WriteStreamWrapper::Create(nsDiskCacheRecordChannel*aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* * aWrapper)
{
WriteStreamWrapper *wrapper = new WriteStreamWrapper(aChannel, aBaseStream);
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(wrapper);
*aWrapper = wrapper;
return NS_OK;
}
NS_IMETHODIMP
WriteStreamWrapper::Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten)
{
*aNumWritten = 0;
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
mChannel->NotifyStorageInUse(*aNumWritten);
return rv;
}
NS_IMETHODIMP
WriteStreamWrapper::Flush()
{
return mBaseStream->Flush();
}
NS_IMETHODIMP
WriteStreamWrapper::Close()
{
return mBaseStream->Close();
}
nsDiskCacheRecordChannel::nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord,
nsILoadGroup *aLoadGroup)
: mRecord(aRecord) ,
mLoadGroup(aLoadGroup)
{
NS_INIT_REFCNT() ;
mRecord->mNumChannels++ ;
}
nsDiskCacheRecordChannel::~nsDiskCacheRecordChannel()
{
mRecord->mNumChannels-- ;
}
// FUR!!
//
// I know that I gave conflicting advice on the issue of file
// transport versus file protocol handler, but I thought that the
// last word was that we would use the raw transport, when I wrote:
//
// > I just thought of an argument for the other side of the coin, i.e. the
// > benefit of *not* reusing the file protocol handler: On the Mac, it's
// > expensive to convert from a string URL to an nsFileSpec, because the Mac
// > is brain-dead and scans every directory on the path to the file. It's
// > cheaper to create a nsFileSpec for a cache file by combining a single,
// > static nsFileSpec that corresponds to the cache directory with the
// > relative path to the cache file (using nsFileSpec's operator +). This
// > operation is optimized on the Mac to avoid the scanning operation.
//
// The Mac guys will eat us alive if we do path string to nsFileSpec
// conversions for every cache file we open.
nsresult
nsDiskCacheRecordChannel::Init(void)
{
char* urlStr ;
mRecord->mFile->GetURLString(&urlStr) ;
nsresult rv ;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewChannel("load", // XXX what should this be?
urlStr,
nsnull, // no base uri
mLoadGroup,
nsnull, // no eventsink getter
0,
nsnull, // no original URI
0,
0,
getter_AddRefs(mFileTransport));
return rv ;
}
nsresult
nsDiskCacheRecordChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
{
return mRecord->mDiskCache->m_StorageInUse += aBytesUsed ;
}
// implement nsISupports
NS_IMPL_ISUPPORTS(nsDiskCacheRecordChannel, NS_GET_IID(nsIChannel))
// implement nsIRequest
NS_IMETHODIMP
nsDiskCacheRecordChannel::IsPending(PRBool *aIsPending)
{
*aIsPending = PR_FALSE ;
if(!mFileTransport)
return NS_OK ;
return mFileTransport->IsPending(aIsPending) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Cancel(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Cancel() ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Suspend(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Suspend() ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::Resume(void)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->Resume() ;
}
// implement nsIChannel
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetURI(nsIURI * *aURI)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetURI(aURI) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OpenInputStream(PRUint32 aStartPosition,
PRInt32 aReadCount,
nsIInputStream* *aResult)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->OpenInputStream(aStartPosition,
aReadCount,
aResult) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OpenOutputStream(PRUint32 startPosition,
nsIOutputStream* *aResult)
{
nsresult rv ;
NS_ENSURE_ARG(aResult) ;
nsCOMPtr<nsIOutputStream> outputStream ;
PRUint32 oldLength ;
mRecord->GetStoredContentLength(&oldLength) ;
if(startPosition < oldLength) {
NotifyStorageInUse(startPosition - oldLength) ;
// we should truncate the file at here.
rv = mRecord->SetStoredContentLength(startPosition) ;
if(NS_FAILED(rv)) {
printf(" failed to truncate\n") ;
return rv ;
}
}
rv = mFileTransport->OpenOutputStream(startPosition, getter_AddRefs(outputStream)) ;
if(NS_FAILED(rv)) return rv ;
return WriteStreamWrapper::Create(this, outputStream, aResult) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncOpen(nsIStreamObserver *observer,
nsISupports *ctxt)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->AsyncOpen(observer, ctxt) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncRead(PRUint32 aStartPosition,
PRInt32 aReadCount,
nsISupports *aContext,
nsIStreamListener *aListener)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->AsyncRead(aStartPosition ,
aReadCount ,
aContext ,
aListener) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncWrite(nsIInputStream *fromStream,
PRUint32 startPosition,
PRInt32 writeCount,
nsISupports *ctxt,
nsIStreamObserver *observer)
{
/*
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->AsyncWrite(fromStream,
startPosition,
writeCount,
ctxt,
observer) ;
*/
// I can't do this since the write is not monitored, and I won't be
// able to updata the storage.
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetLoadAttributes(aLoadAttributes) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->SetLoadAttributes(aLoadAttributes) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentType(char * *aContentType)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetContentType(aContentType) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentLength(PRInt32 *aContentLength)
{
if(!mFileTransport)
return NS_ERROR_FAILURE ;
return mFileTransport->GetContentLength(aContentLength) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get() ;
NS_IF_ADDREF(*aOwner) ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner ;
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetOriginalURI(nsIURI* *aURI)
{
// FUR - might need to implement this - not sure
return NS_ERROR_NOT_IMPLEMENTED ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_OK ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_OK;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -0,0 +1,65 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _ns_DiskCacheRecordChannel_h_
#define _ns_DiskCacheRecordChannel_h_
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsDiskCacheRecord.h"
/*
* This class is plagiarized from nsMemCacheChannel
*/
class nsDiskCacheRecordChannel : public nsIChannel
{
public:
nsDiskCacheRecordChannel(nsDiskCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
virtual ~nsDiskCacheRecordChannel() ;
// Declare nsISupports methods
NS_DECL_ISUPPORTS
// Declare nsIRequest methods
NS_DECL_NSIREQUEST
// Declare nsIChannel methods
NS_DECL_NSICHANNEL
nsresult Init(void) ;
private:
nsresult NotifyStorageInUse(PRInt32 aBytesUsed) ;
nsCOMPtr<nsDiskCacheRecord> mRecord ;
nsCOMPtr<nsILoadGroup> mLoadGroup ;
nsCOMPtr<nsISupports> mOwner ;
nsCOMPtr<nsIChannel> mFileTransport ;
friend class WriteStreamWrapper ;
} ;
#endif // _ns_DiskCacheRecordChannel_h_

View File

@ -0,0 +1,60 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _NS_IDBACCESSOR_H_
#define _NS_IDBACCESSOR_H_
#include "nsISupports.h"
#include "nsIFileSpec.h"
// nsIDBAccessorIID {6AADD4D0-7785-11d3-87FE-000629D01344}
#define NS_IDBACCESSOR_IID \
{ 0x6aadd4d0, 0x7785, 0x11d3, \
{0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44}}
// nsDBAccessorCID {6AADD4D1-7785-11d3-87FE-000629D01344}
#define NS_DBACCESSOR_CID \
{ 0x6aadd4d1, 0x7785, 0x11d3, \
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
class nsIDBAccessor : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IDBACCESSOR_IID)
NS_IMETHOD Init(nsIFileSpec* DBFile) = 0 ;
NS_IMETHOD Shutdown(void) = 0 ;
NS_IMETHOD Put(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
NS_IMETHOD Get(PRInt32 aID, void** anEntry, PRUint32 *aLength) = 0 ;
NS_IMETHOD Del(PRInt32 aID, void* anEntry, PRUint32 aLength) = 0 ;
NS_IMETHOD GetID(const char* key, PRUint32 length, PRInt32* aID) = 0 ;
NS_IMETHOD EnumEntry(void* *anEntry, PRUint32* aLength, PRBool bReset) = 0 ;
} ;
#endif // _NS_IDBACCESSOR_H_

View File

@ -0,0 +1,691 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#include "nsNetDiskCache.h"
#include "nscore.h"
#include "plstr.h"
#include "prprf.h"
#include "prtypes.h"
#include "prio.h"
#include "prsystem.h" // Directory Seperator
#include "plhash.h"
#include "prclist.h"
#include "prmem.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
#include "mcom_db.h"
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID) ;
static NS_DEFINE_CID(kDBAccessorCID, NS_DBACCESSOR_CID) ;
static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*1024*1024 ; // 5MB
static const char * const DISK_CACHE_PREF = "browser.cache.disk_cache_size";
static const char * const CACHE_DIR_PREF = "browser.cache.directory";
class nsDiskCacheRecord ;
nsNetDiskCache::nsNetDiskCache() :
m_Enabled(PR_TRUE) ,
m_NumEntries(0) ,
m_pNextCache(0) ,
m_pDiskCacheFolder(0) ,
m_StorageInUse(0) ,
m_DB(0) ,
m_BaseDirNum(32)
{
// set it to INF for now
m_MaxEntries = (PRUint32)-1 ;
NS_INIT_REFCNT();
}
nsNetDiskCache::~nsNetDiskCache()
{
printf("~nsNetDiskCache\n") ;
NS_IF_RELEASE(m_DB) ;
// FUR!!
// You shouldn't rely on the value of m_BaseDirNum to diagnose whether or not
// a cache corruption has occurred since it's possible that the app does not
// shut down cleanly and a corrupted cache has still not been cleaned up from
// a previous session. My suggestion is that you pick a different scheme for
// renaming the dirs, e.g. rename them as "trash*" and remove all directories
// with this name pattern on shutdown.
// FUR
// I think that, eventually, we also want a distinguished key in the DB which
// means "clean cache shutdown". You clear this flag when the db is first
// opened and set it just before the db is closed. If the db wasn't shutdown
// cleanly in a prior session, i.e. because the app crashed, on startup you
// scan all the individual files in directories and look for "orphans",
// i.e. cache files which don't have corresponding entries in the db. That's
// also when storage-in-use and number of entries would be recomputed.
//
// We don't necessarily need all this functionality immediately, though.
if(m_BaseDirNum > 32)
RemoveDirs(32) ;
}
NS_IMETHODIMP
nsNetDiskCache::Init(void)
{
nsresult rv ;
// FUR!!
// I really don't think prefs belong here, since that breaks modularity. It
// presupposes that the file cache code is embedded in the browser or some
// other application that uses the prefs, i.e. the code might be used in a
// standalone cache manipulation tool or, someday, in server code. Pref
// reading belongs at a higher level, either in the application itself or
// possibly the I/O manager.
// Also, Init() needs to be lazy, since folder name is not set on startup,
// i.e. need a call to MaybeInit() at the beginning of every public method
NS_WITH_SERVICE(nsIPref, pref, kPrefCID, &rv) ;
if (NS_FAILED(rv))
NS_ERROR("Failed to get globle preference!\n") ;
rv = NS_NewFileSpec(getter_AddRefs(m_pDiskCacheFolder));
if (!m_pDiskCacheFolder) {
NS_ERROR("ERROR: Could not make a file spec.\n") ;
return NS_ERROR_OUT_OF_MEMORY ;
}
char* tempPref = 0 ;
if(pref) {
PRInt32 nTemp = 0 ;
/*
rv = pref->CopyCharPref(CACHE_DIR_PREF, &tempPref) ;
if (NS_SUCCEEDED(rv)) {
printf("cache dir is %s\n", tempPref) ;
m_pDiskCacheFolder->SetUnixStyleFilePath(tempPref) ;
PR_Free(tempPref) ;
} else */
{
m_pDiskCacheFolder->SetUnixStyleFilePath("/tmp") ;
printf("using default folder, /tmp\n") ;
}
}
else {
// temp hack for now. change later for other platform
m_pDiskCacheFolder->SetUnixStyleFilePath("/tmp") ;
}
// FUR - suggest you use nsCOMPtr for m_DB - it will eliminate
// manual addref/release and reduce likelihood of bugs
NS_IF_RELEASE(m_DB) ;
m_DB = new nsDBAccessor() ;
if(!m_DB)
return NS_ERROR_OUT_OF_MEMORY ;
else
NS_ADDREF(m_DB) ;
rv = InitDB() ;
// try once for recovery
if(rv == NS_ERROR_FAILURE) {
rv = DBRecovery() ;
return rv ;
}
rv = UpdateInfo() ;
return rv ;
}
NS_IMETHODIMP
nsNetDiskCache::InitDB(void)
{
// create cache sub directories
nsresult rv ;
nsCOMPtr<nsIFileSpec> cacheSubDir;
rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
// FUR - any way to avoid doing this, if it's already been done ?
for (int i=0; i < 32; i++) {
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
char dirName[3];
PR_snprintf (dirName, 3, "%0.2x", i);
cacheSubDir->AppendRelativeUnixPath (dirName) ;
CreateDir(cacheSubDir);
}
NS_NewFileSpec(getter_AddRefs(m_DBFile)) ;
// FUR - check for NS_NewFileSpec failure
rv = m_DBFile->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
m_DBFile->AppendRelativeUnixPath("cache.db") ;
rv = m_DB->Init(m_DBFile) ;
return rv ;
}
//////////////////////////////////////////////////////////////////////////
// nsISupports methods
// FUR - Suggest you use NS_IMPL_ISUPPORTS3() macro instead
NS_IMETHODIMP
nsNetDiskCache::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_ASSERTION(aInstancePtr, "no instance pointer");
if(aIID.Equals(NS_GET_IID(nsINetDataDiskCache)) ||
aIID.Equals(NS_GET_IID(nsINetDataCache)) ||
aIID.Equals(NS_GET_IID(nsISupports))) {
*aInstancePtr = NS_STATIC_CAST(nsINetDataDiskCache*, this);
NS_ADDREF_THIS();
return NS_OK;
}
else
return NS_NOINTERFACE ;
}
NS_IMPL_ADDREF(nsNetDiskCache) ;
NS_IMPL_RELEASE(nsNetDiskCache) ;
///////////////////////////////////////////////////////////////////////////
// nsINetDataCache Method
NS_IMETHODIMP
nsNetDiskCache::GetDescription(PRUnichar* *aDescription)
{
nsAutoString description("Disk Cache") ;
*aDescription = description.ToNewUnicode() ;
if(!*aDescription)
return NS_ERROR_OUT_OF_MEMORY ;
return NS_OK ;
}
/* don't alloc mem for nsICachedNetData.
* RecordID is generated using the same scheme in nsCacheDiskData,
* see GetCachedNetData() for detail.
*/
NS_IMETHODIMP
nsNetDiskCache::Contains(const char* key, PRUint32 length, PRBool *_retval)
{
*_retval = PR_FALSE ;
NS_ASSERTION(m_DB, "no db.") ;
PRInt32 id = 0 ;
m_DB->GetID(key, length, &id) ;
// FUR - Check for GetID failure ?
void* info = 0 ;
PRUint32 info_size = 0 ;
nsresult rv = m_DB->Get(id, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info)
*_retval = PR_TRUE ;
return NS_OK ;
}
/* regardless if it's cached or not, a copy of nsNetDiskCache would
* always be returned. so release it appropriately.
* if mem alloced, updata m_NumEntries also.
* for now, the new nsCachedNetData is not written into db yet since
* we have nothing to write.
*/
NS_IMETHODIMP
nsNetDiskCache::GetCachedNetData(const char* key, PRUint32 length, nsINetDataCacheRecord **_retval)
{
NS_ASSERTION(m_DB, "no db.") ;
nsresult rv = 0 ;
if (!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
PRInt32 id = 0 ;
m_DB->GetID(key, length, &id) ;
// FUR - Check for GetID failure ?
// construct an empty record
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
if(!newRecord)
return NS_ERROR_OUT_OF_MEMORY ;
rv = newRecord->Init(key, length) ;
if(NS_FAILED(rv)) {
delete newRecord ;
return rv ;
}
NS_ADDREF(newRecord) ; // addref for _retval
*_retval = (nsINetDataCacheRecord*) newRecord ;
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(id, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info) {
nsresult r1 ;
r1 = newRecord->RetrieveInfo(info, info_size) ;
// FUR!! need to release and return error if RetrieveInfo() fails
if(NS_SUCCEEDED(rv))
return NS_OK ;
else
return r1;
} else if (NS_SUCCEEDED(rv) && !info) {
// this is a new record.
m_NumEntries ++ ;
return NS_OK ;
} else
return rv ;
}
/* get an nsICachedNetData, mem needs to be de-alloced if not found. */
NS_IMETHODIMP
nsNetDiskCache::GetCachedNetDataByID(PRInt32 RecordID, nsINetDataCacheRecord **_retval)
{
NS_ASSERTION(m_DB, "no db.") ;
if (!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsresult rv ;
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(RecordID, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info) {
// construct an empty record if only found in db
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
if(!newRecord)
return NS_ERROR_OUT_OF_MEMORY ;
NS_ADDREF(newRecord) ; // addref for _retval
rv = newRecord->RetrieveInfo(info, info_size) ;
if(NS_SUCCEEDED(rv)) {
*_retval = (nsINetDataCacheRecord*) newRecord ;
return NS_OK ;
}
else {
// bad record, I guess
NS_RELEASE(newRecord) ; // release if bad things happen
return rv ;
}
} else {
NS_ERROR("Error: RecordID not in DB\n") ;
return rv ;
}
}
NS_IMETHODIMP
nsNetDiskCache::GetEnabled(PRBool *aEnabled)
{
*aEnabled = m_Enabled ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetEnabled(PRBool aEnabled)
{
m_Enabled = aEnabled ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetFlags(PRUint32 *aFlags)
{
*aFlags = FILE_PER_URL_CACHE;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetNumEntries(PRUint32 *aNumEntries)
{
*aNumEntries = m_NumEntries ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::GetMaxEntries(PRUint32 *aMaxEntries)
{
*aMaxEntries = m_MaxEntries ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::NewCacheEntryIterator(nsISimpleEnumerator **_retval)
{
if(!_retval)
return NS_ERROR_NULL_POINTER ;
*_retval = nsnull ;
nsISimpleEnumerator* enumerator = new nsDBEnumerator(m_DB, this) ;
if(enumerator) {
NS_ADDREF(enumerator) ;
*_retval = enumerator ;
return NS_OK ;
}
else
return NS_ERROR_OUT_OF_MEMORY ;
}
NS_IMETHODIMP
nsNetDiskCache::GetNextCache(nsINetDataCache * *aNextCache)
{
if(!aNextCache)
return NS_ERROR_NULL_POINTER ;
*aNextCache = m_pNextCache ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetNextCache(nsINetDataCache *aNextCache)
{
m_pNextCache = aNextCache ;
return NS_OK ;
}
// db size can always be measured at the last minute. Since it's hard
// to know before hand.
NS_IMETHODIMP
nsNetDiskCache::GetStorageInUse(PRUint32 *aStorageInUse)
{
PRUint32 total_size = m_StorageInUse, len = 0 ;
// FUR!!
// GetStorageInUse() can be called hundreds of times per second, i.e. every
// time a buffer of data is written to the cache, so we can't afford to stat
// the db file on every call. I would suggest caching the size of the db and
// invalidating that cached value every time a record is written to the db,
// or even every ten written records.
// add the size of the db.
// m_DBFile->GetFileSize(&len) ;
// total_size += len ;
// we need size in kB
total_size = total_size >> 10 ;
*aStorageInUse = total_size ;
return NS_OK ;
}
/*
* The whole cache dirs can be whiped clean since all the cache
* files are resides in seperate hashed dirs. It's safe to do so.
*/
NS_IMETHODIMP
nsNetDiskCache::RemoveAll(void)
{
nsresult rv = RemoveDirs(0) ;
if(NS_FAILED(rv))
return rv ;
// don't forget the db file itself
m_DB->Shutdown() ;
nsFileSpec dbfile ;
m_DBFile->GetFileSpec(&dbfile) ;
dbfile.Delete(PR_TRUE) ;
// reinitilize
rv = InitDB() ;
if(NS_FAILED(rv))
return rv ;
rv = UpdateInfo() ;
return rv ;
}
//////////////////////////////////////////////////////////////////
// nsINetDataDiskCache methods
NS_IMETHODIMP
nsNetDiskCache::GetDiskCacheFolder(nsIFileSpec * *aDiskCacheFolder)
{
*aDiskCacheFolder = m_pDiskCacheFolder ;
NS_ADDREF(*aDiskCacheFolder) ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetDiskCacheFolder(nsIFileSpec * aDiskCacheFolder)
{
char *newfolder, *oldfolder ;
m_pDiskCacheFolder->GetNativePath(&oldfolder) ;
aDiskCacheFolder->GetNativePath(&newfolder) ;
if(PL_strcmp(newfolder, oldfolder) == 0) {
m_pDiskCacheFolder = aDiskCacheFolder ;
// should we do this?
// FUR - no
nsresult rv = RemoveAll() ;
return rv ;
}
else
// FUR
// Need to blow away old cache, build new one
return NS_OK ;
}
//////////////////////////////////////////////////////////////////
// nsNetDiskCache methods
// create a directory (recursively)
NS_IMETHODIMP
nsNetDiskCache::CreateDir(nsIFileSpec* dir_spec)
{
PRBool does_exist ;
nsCOMPtr<nsIFileSpec> p_spec ;
dir_spec->Exists(&does_exist) ;
if(does_exist)
return NS_OK ;
dir_spec->GetParent(getter_AddRefs(p_spec)) ;
// FUR - check return value
p_spec->Exists(&does_exist) ;
if(!does_exist) {
CreateDir(p_spec) ;
dir_spec->CreateDir() ;
// FUR - check return value
}
else {
dir_spec->CreateDir() ;
// FUR - check return value
}
return NS_OK ;
}
// FUR!!
// We can't afford to make a *separate* pass over the whole db on every
// startup, just to figure out m_NumEntries and m_StorageInUse. (This is a
// several second operation on a large db). We'll likely need to store
// distinguished keys in the db that contain these values and update them
// incrementally, except when failure to shut down the db cleanly is detected.
// this will walk through db and update m_NumEntries and m_StorageInUse
NS_IMETHODIMP
nsNetDiskCache::UpdateInfo(void)
{
// count num of entries in db
// NS_ADDREF(this) ; // addref before assign to a nsCOMPtr.
nsISimpleEnumerator* dbEnumerator = new nsDBEnumerator(m_DB, this) ;
if(dbEnumerator)
NS_ADDREF(dbEnumerator) ;
else
return NS_ERROR_FAILURE ;
PRUint32 numEntries = 0, storageInUse = 0, len = 0 ;
PRBool more = PR_FALSE ;
do {
dbEnumerator->HasMoreElements(&more) ;
if(more) {
// update entry number
numEntries++ ;
// update storage in use
nsINetDataCacheRecord* record ;
dbEnumerator->GetNext((nsISupports**)&record) ;
record->GetStoredContentLength(&len) ;
storageInUse += len ;
NS_IF_RELEASE(record) ;
}
} while (more) ;
NS_IF_RELEASE(dbEnumerator) ;
m_NumEntries = numEntries ;
m_StorageInUse = storageInUse ;
printf(" m_NumEntries = %d, size is %d.\n", m_NumEntries, m_StorageInUse) ;
return NS_OK ;
}
// this routine will add m_BaseDirNum to current CacheSubDir names.
// e.g. 00->20, 1f->5f. and update the m_BaseDirNum to another 32.
// the idea is as long as we remember the base number,
// we know how many dirs needs to be removed during shutdown period
// it will be from 0x20 to m_BaseDirNum.
// also, we assume that this operation will not be performed 3 times more
// within a single session. it is part of scavenging routine.
NS_IMETHODIMP
nsNetDiskCache::RenameCacheSubDirs(void)
{
nsCOMPtr<nsIFileSpec> cacheSubDir;
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir)) ;
for (int i=0; i < 32; i++) {
rv = cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
char dirName[3];
PR_snprintf(dirName, 3, "%0.2x", i) ;
cacheSubDir->AppendRelativeUnixPath(dirName) ;
// re-name the directory
PR_snprintf(dirName, 3, "%0.2x", i+m_BaseDirNum) ;
rv = cacheSubDir->Rename(dirName) ;
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
}
// update m_BaseDirNum
m_BaseDirNum += 32 ;
return NS_OK ;
}
// this routine will be called everytime we have a db corruption.
NS_IMETHODIMP
nsNetDiskCache::DBRecovery(void)
{
nsresult rv = RenameCacheSubDirs() ;
if(NS_FAILED(rv))
return rv ;
// remove corrupted db file
rv = m_DB->Shutdown() ;
// FUR!!
// You shouldn't return if this fails. Otherwise, it might prevent db deletion
if(NS_FAILED(rv))
return rv ;
nsFileSpec dbfile ;
m_DBFile->GetFileSpec(&dbfile) ;
dbfile.Delete(PR_TRUE) ;
// make sure it's not there any more
PRBool exists = dbfile.Exists() ;
if(exists) {
NS_ERROR("can't remove old db.") ;
return NS_ERROR_FAILURE ;
}
// reinitilize
rv = InitDB() ;
if(NS_FAILED(rv))
return rv ;
rv = UpdateInfo() ;
return rv ;
}
// this routine is used by dtor and RemoveAll() to clean up dirs.
// All directory named from aNum - m_BasedDirNum will be deleted.
NS_IMETHODIMP
nsNetDiskCache::RemoveDirs(PRUint32 aNum)
{
nsCOMPtr<nsIFileSpec> cacheSubDir;
nsresult rv = NS_NewFileSpec(getter_AddRefs(cacheSubDir));
if(NS_FAILED(rv))
return NS_ERROR_FAILURE ;
for (int i=aNum; i < m_BaseDirNum; i++) {
cacheSubDir->FromFileSpec(m_pDiskCacheFolder) ;
char dirName[3];
PR_snprintf (dirName, 3, "%0.2x", i);
cacheSubDir->AppendRelativeUnixPath (dirName) ;
nsFileSpec subdir ;
cacheSubDir->GetFileSpec(&subdir) ;
for(nsDirectoryIterator di(subdir, PR_FALSE); di.Exists(); di++) {
di.Spec().Delete(PR_TRUE) ;
}
subdir.Delete(PR_FALSE) ; // recursive delete
}
return NS_OK ;
}

View File

@ -0,0 +1,82 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
// FUR - Add overall description comment here
#ifndef __gen_nsNetDiskCache_h__
#define __gen_nsNetDiskCache_h__
#include "nsINetDataDiskCache.h"
#include "nsNetDiskCacheCID.h"
#include "nsCOMPtr.h"
#include "nsIPref.h"
#include "nsDBAccessor.h"
class nsIURI; /* forward decl */
class nsICachedNetData; /* forward decl */
class nsISimpleEnumerator; /* forward decl */
class nsIFileSpec; /* forward decl */
/* starting interface: nsNetDiskCache */
class nsNetDiskCache : public nsINetDataDiskCache {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHE
NS_DECL_NSINETDATADISKCACHE
NS_IMETHOD Init(void) ;
nsNetDiskCache() ;
virtual ~nsNetDiskCache() ;
protected:
NS_IMETHOD InitDB(void) ;
NS_IMETHOD CreateDir(nsIFileSpec* dir_spec) ;
NS_IMETHOD UpdateInfo(void) ;
NS_IMETHOD RenameCacheSubDirs(void) ;
NS_IMETHOD DBRecovery(void) ;
NS_IMETHOD RemoveDirs(PRUint32 aNum) ;
private:
PRBool m_Enabled ;
PRUint32 m_NumEntries ;
nsCOMPtr<nsINetDataCache> m_pNextCache ;
nsCOMPtr<nsIFileSpec> m_pDiskCacheFolder ;
nsCOMPtr<nsIFileSpec> m_DBFile ;
PRUint32 m_MaxEntries ;
PRUint32 m_StorageInUse ;
nsIDBAccessor* m_DB ;
// this is used to indicate a db corruption
PRInt32 m_BaseDirNum ;
friend class nsDiskCacheRecord ;
friend class nsDiskCacheRecordChannel ;
} ;
#endif /* __gen_nsNetDiskCache_h__ */

View File

@ -0,0 +1,32 @@
/*
* 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 Mozilla Communicator.
*
* The Initial Developer of the Original Code is Intel Corp.
* Portions created by Intel Corp. are
* Copyright (C) 1999, 1999 Intel Corp. All
* Rights Reserved.
*
* Contributor(s): Yixiong Zou <yixiong.zou@intel.com>
* Carl Wong <carl.wong@intel.com>
*/
#ifndef _nsNetDiskCacheCID_h_
#define _nsNetDiskCacheCID_h_
#define NS_NETDISKCACHE_CID_STR "ECFEEA00-7201-11d3-87FE-000629D01344"
#define NS_NETDISKCACHE_CID \
{ 0xecfeea00, 0x7201, 0x11d3, \
{ 0x87, 0xfe, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44 }}
#endif /* _nsNetDiskCacheCID_h_ */

View File

@ -0,0 +1,50 @@
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
REQUIRES = libreg xpcom
CPPSRCS = \
diskcache.cpp \
$(NULL)
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
ifdef NO_LD_ARCHIVE_FLAGS
LOST_SYM_LIBS = -lxpcomds_s -lxptinfo -lmozreg_s
endif
LIBS = \
-lmozjs \
-lxpcom \
-lmozdbm_s \
$(MOZ_NECKO_UTIL_LIBS) \
$(LOST_SYM_LIBS) \
$(NSPR_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = -I$(srcdir)/..
DEFINES += -DUSE_NSREG -DCACHE

View File

@ -0,0 +1,836 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsIStreamListener.h"
#include "nsIStreamObserver.h"
#include "nsIServiceManager.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIEventQueue.h"
#include "nsIEventQueueService.h"
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include <stdio.h>
#include <unistd.h>
#include "nsINetDataCache.h"
#include "nsINetDataCacheRecord.h"
//#include "nsMemCacheCID.h"
#include "nsNetDiskCache.h"
#include "nsIPref.h"
#include "prenv.h"
#include "nsIFileStream.h"
// Number of test entries to be placed in the cache
#define NUM_CACHE_ENTRIES 250
// Cache content stream length will have random length between zero and
// MAX_CONTENT_LENGTH bytes
#define MAX_CONTENT_LENGTH 20000
// Length of random-data cache entry key
#define CACHE_KEY_LENGTH 15
// Length of random-data cache entry meta-data
#define CACHE_METADATA_LENGTH 100
//static NS_DEFINE_CID(kMemCacheCID, NS_MEM_CACHE_FACTORY_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kDiskCacheCID, NS_NETDISKCACHE_CID) ;
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
static NS_DEFINE_IID(kIPrefIID, NS_IPREF_IID);
// Mapping from test case number to RecordID
static PRInt32 recordID[NUM_CACHE_ENTRIES];
static PRInt32
mapRecordIdToTestNum(PRInt32 aRecordID)
{
int i;
for (i = 0; i < NUM_CACHE_ENTRIES; i++) {
if (recordID[i] == aRecordID)
return i;
}
return -1;
}
// A supply of stream data to either store or compare with
class nsITestDataStream {
public:
virtual ~nsITestDataStream() {};
virtual PRUint32 Next() = 0;
virtual void Read(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
virtual void Skip(PRUint32 aCount) = 0;
};
// A reproducible stream of random data.
class RandomStream : public nsITestDataStream {
public:
RandomStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState = 1103515245 * mState + 12345;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)(Next() & 0xff))
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
while (aCount--)
Next();
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
// A stream of data that increments on each byte that is read, modulo 256
class CounterStream : public nsITestDataStream {
public:
CounterStream(PRUint32 aSeed) {
mStartSeed = mState = aSeed;
}
PRUint32 GetStartSeed() {
return mStartSeed;
}
PRUint32 Next() {
mState += 1;
mState &= 0xff;
return mState;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
PRBool
Match(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)Next())
return PR_FALSE;
}
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
mState += aCount;
mState &= 0xff;
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
static int gNumReaders = 0;
static PRUint32 gTotalBytesRead = 0;
static PRUint32 gTotalDuration = 0;
class nsReader : public nsIStreamListener {
public:
NS_DECL_ISUPPORTS
nsReader()
: mStartTime(0), mBytesRead(0)
{
NS_INIT_REFCNT();
gNumReaders++;
}
virtual ~nsReader() {
delete mTestDataStream;
gNumReaders--;
}
nsresult
Init(nsIChannel *aChannel, nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
mChannel = aChannel;
mTestDataStream = aRandomStream;
mExpectedStreamLength = aExpectedStreamLength;
mRefCnt = 1;
return NS_OK;
}
NS_IMETHOD OnStartRequest(nsIChannel* channel,
nsISupports* context) {
mStartTime = PR_IntervalNow();
return NS_OK;
}
NS_IMETHOD OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength) {
char buf[1025];
while (aLength > 0) {
PRUint32 amt;
PRBool match;
aIStream->Read(buf, sizeof buf, &amt);
if (amt == 0) break;
aLength -= amt;
mBytesRead += amt;
match = mTestDataStream->Match(buf, amt);
NS_ASSERTION(match, "Stored data was corrupted on read");
}
return NS_OK;
}
NS_IMETHOD OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg) {
PRIntervalTime endTime;
PRIntervalTime duration;
endTime = PR_IntervalNow();
duration = (endTime - mStartTime);
if (NS_FAILED(aStatus)) printf("channel failed.\n");
// printf("read %d bytes\n", mBytesRead);
NS_ASSERTION(mBytesRead == mExpectedStreamLength,
"Stream in cache is wrong length");
gTotalBytesRead += mBytesRead;
gTotalDuration += duration;
// Release channel
mChannel = 0;
return NS_OK;
}
protected:
PRIntervalTime mStartTime;
PRUint32 mBytesRead;
nsITestDataStream* mTestDataStream;
PRUint32 mExpectedStreamLength;
nsCOMPtr<nsIChannel> mChannel;
};
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
static nsIEventQueue* eventQueue;
nsresult
InitQueue() {
nsresult rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue service");
rv = eventQService->CreateThreadEventQueue();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create event queue");
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQueue);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get event queue for main thread");
return NS_OK;
}
// Process events until all streams are OnStopRequest'ed
nsresult
WaitForEvents() {
while (gNumReaders) {
eventQueue->ProcessPendingEvents();
}
return NS_OK;
}
// Read data for a single cache record and compare against testDataStream
nsresult
TestReadStream(nsINetDataCacheRecord *record, nsITestDataStream *testDataStream,
PRUint32 expectedStreamLength)
{
nsCOMPtr<nsIChannel> channel;
nsresult rv;
PRUint32 actualContentLength;
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = record->GetStoredContentLength(&actualContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(actualContentLength == expectedStreamLength,
"nsINetDataCacheRecord::GetContentLength() busted ?");
nsReader *reader = new nsReader;
reader->AddRef();
rv = reader->Init(channel, testDataStream, expectedStreamLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->AsyncRead(0, -1, 0, reader);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
reader->Release();
return NS_OK;
}
// Check that records can be retrieved using their record-ID, in addition
// to using the opaque key.
nsresult
TestRecordID(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetDataByID(recordID[testNum], getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain record using record ID");
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
return NS_OK;
}
// Check that all cache entries in the database are enumerated and that
// no duplicates appear.
nsresult
TestEnumeration(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsISupports> tempISupports;
nsCOMPtr<nsISimpleEnumerator> iterator;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData;
PRUint32 testNum;
PRBool match;
PRInt32 recID;
int numRecords = 0;
// Iterate over all records in the cache
rv = cache->NewCacheEntryIterator(getter_AddRefs(iterator));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create new cache entry iterator");
PRBool notDone;
while (1) {
// Done iterating ?
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
// Get next record in iteration
rv = iterator->GetNext(getter_AddRefs(tempISupports));
NS_ASSERTION(NS_SUCCEEDED(rv), "iterator bustage");
record = do_QueryInterface(tempISupports);
numRecords++;
// Get record ID
rv = record->GetRecordID(&recID);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
testNum = mapRecordIdToTestNum(recID);
NS_ASSERTION(testNum != -1, "Corrupted Record ID ?");
// Erase mapping from table, so that duplicate enumerations are detected
recordID[testNum] = -1;
// Make sure stream matches test data
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Match against previously stored meta-data
rv = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get record meta-data");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
delete randomStream;
}
NS_ASSERTION(numRecords == NUM_CACHE_ENTRIES, "Iteration bug");
return NS_OK;
}
// Read the test data that was written in FillCache(), checking for
// corruption, truncation.
nsresult
TestRead(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char *metaData, *storedCacheKey;
PRUint32 testNum, storedCacheKeyLength;
PRBool match;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// Ensure that entry is in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// Match against previously stored meta-data
match = record->GetMetaData(&metaDataLength, &metaData);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
match = randomStream->Match(metaData, metaDataLength);
NS_ASSERTION(match, "Meta-data corrupted or incorrect");
nsAllocator::Free(metaData);
// Test GetKey() method
rv = record->GetKey(&storedCacheKeyLength, &storedCacheKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
(storedCacheKeyLength == sizeof cacheKey) &&
!memcmp(storedCacheKey, &cacheKey[0], sizeof cacheKey),
"nsINetDataCacheRecord::GetKey failed");
nsAllocator::Free(storedCacheKey);
PRUint32 expectedStreamLength = randomStream->Next() & 0xffff;
TestReadStream(record, randomStream, expectedStreamLength);
}
WaitForEvents();
// Compute rate in MB/s
double rate = gTotalBytesRead / PR_IntervalToMilliseconds(gTotalDuration);
rate *= NUM_CACHE_ENTRIES;
rate *= 1000;
rate /= (1024 * 1024);
printf("Read %d bytes at a rate of %5.1f MB per second \n",
gTotalBytesRead, rate);
return NS_OK;
}
// Repeatedly call SetStoredContentLength() on a cache entry and make
// read the stream's data to ensure that it's not corrupted by the effect
nsresult
TestTruncation(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
RandomStream *randomStream;
char cacheKey[CACHE_KEY_LENGTH];
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
randomStream->Skip(CACHE_METADATA_LENGTH);
PRUint32 initialStreamLength = randomStream->Next() & 0xffff;
delete randomStream;
PRUint32 i;
PRUint32 delta = initialStreamLength / 64;
for (i = initialStreamLength; i >= delta; i -= delta) {
PRUint32 expectedStreamLength = i;
// Do the truncation
record->SetStoredContentLength(expectedStreamLength);
randomStream = new RandomStream(0);
randomStream->Skip(CACHE_KEY_LENGTH + CACHE_METADATA_LENGTH + 1);
TestReadStream(record, randomStream, expectedStreamLength);
WaitForEvents();
}
return NS_OK;
}
// Write known data to random offsets in a single cache entry and test
// resulting stream for correctness.
nsresult
TestOffsetWrites(nsINetDataCache *cache)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[512];
char cacheKey[CACHE_KEY_LENGTH];
RandomStream *randomStream;
randomStream = new RandomStream(0);
randomStream->Read(cacheKey, sizeof cacheKey);
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
nsCOMPtr<nsIFileSpec> file ;
record->GetFilename(getter_AddRefs(file)) ;
char* name ;
file->GetUnixStyleFilePath(&name) ;
printf(" file name is %s \n", name) ;
// Write buffer-fulls of data at random offsets into the cache entry.
// Data written is (offset % 0xff)
PRUint32 startingOffset;
PRUint32 streamLength = 0;
PRUint32 len = 0 ;
CounterStream *counterStream;
int i = 0;
for (i = 0; i < 257; i++) {
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
startingOffset = streamLength ? streamLength - (randomStream->Next() % sizeof buf): 0;
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
truncate(name, startingOffset) ;
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
nsresult status ;
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
if (NS_FAILED(status)) {
// mState = END_WRITE;
return NS_ERROR_FAILURE;
}
PRIntn offset ;
ras->Tell(&offset) ;
// printf(" offset is %d \n", offset) ;
PRUint32 numWritten;
rv = outStream->Write(buf, sizeof buf, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
streamLength = startingOffset + sizeof buf;
rv = outStream->Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
delete counterStream;
record->GetStoredContentLength(&len) ;
if(len != streamLength)
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
}
/*
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
startingOffset = 208;
rv = channel->OpenOutputStream(startingOffset, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
nsresult status ;
nsCOMPtr<nsIRandomAccessStore> ras = do_QueryInterface(outStream, &status);
if (NS_FAILED(status)) {
// mState = END_WRITE;
return NS_ERROR_FAILURE;
}
PRIntn offset = 0 ;
ras->Tell(&offset) ;
printf(" offset is %d \n", offset) ;
PRUint32 numWritten;
rv = outStream->Write(buf, sizeof buf, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == sizeof buf, "Write() bug?");
streamLength = startingOffset + sizeof buf;
rv = outStream->Close();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't close channel");
delete counterStream;
record->GetStoredContentLength(&len) ;
if(len != streamLength)
printf(" offset = %d is wrong, filesize = %d\n", startingOffset, len) ;
*/
delete randomStream;
counterStream = new CounterStream(0);
TestReadStream(record, counterStream, streamLength);
WaitForEvents();
return NS_OK;
}
// Create entries in the network data cache, using random data for the
// key, the meta-data and the stored content data.
nsresult
FillCache(nsINetDataCache *cache)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
char buf[1000];
PRUint32 metaDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char metaData[CACHE_METADATA_LENGTH];
PRUint32 testNum;
char *data;
RandomStream *randomStream;
PRIntervalTime startTime = PR_IntervalNow();
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->Read(cacheKey, sizeof cacheKey);
// No entry should be in cache until we add it
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(!inCache, "nsINetDataCache::Contains error");
rv = cache->GetCachedNetData(cacheKey, sizeof cacheKey, getter_AddRefs(record));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access record via opaque cache key");
// Test nsINetDataCacheRecord::GetRecordID()
rv = record->GetRecordID(&recordID[testNum]);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get Record ID");
// Test nsINetDataCache::GetNumEntries()
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == testNum + 1, "GetNumEntries failure");
// Record meta-data should be initially empty
rv = record->GetMetaData(&metaDataLength, &data);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
if ((metaDataLength != 0) || (data != 0))
return NS_ERROR_FAILURE;
// Store random data as meta-data
randomStream->Read(metaData, sizeof metaData);
record->SetMetaData(sizeof metaData, metaData);
rv = record->NewChannel(0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
PRUint32 beforeOccupancy;
rv = cache->GetStorageInUse(&beforeOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
int streamLength = randomStream->Next() & 0xffff;
int remaining = streamLength;
while (remaining) {
PRUint32 numWritten;
int amount = PR_MIN(sizeof buf, remaining);
randomStream->Read(buf, amount);
rv = outStream->Write(buf, amount, &numWritten);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(numWritten == (PRUint32)amount, "Write() bug?");
remaining -= amount;
}
outStream->Close();
PRUint32 afterOccupancy;
rv = cache->GetStorageInUse(&afterOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 streamLengthInKB = streamLength >> 10;
NS_ASSERTION((afterOccupancy - beforeOccupancy) >= streamLengthInKB,
"nsINetDataCache::GetStorageInUse() is busted");
// *Now* there should be an entry in the cache
rv = cache->Contains(cacheKey, sizeof cacheKey, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCache::Contains error");
delete randomStream;
}
PRIntervalTime endTime = PR_IntervalNow();
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
NULL /* default */);
return rv;
}
PRBool initPref ()
{
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefPtr, kPrefCID, &rv);
if (NS_FAILED(rv))
return false;
nsCOMPtr<nsIFileSpec> fileSpec;
rv = NS_NewFileSpec (getter_AddRefs(fileSpec));
if (NS_FAILED(rv))
return false;
nsCString defaultPrefFile = PR_GetEnv ("MOZILLA_FIVE_HOME");
if (defaultPrefFile.Length())
defaultPrefFile += "/";
else
defaultPrefFile = "./";
defaultPrefFile += "default_prefs.js";
fileSpec->SetUnixStyleFilePath (defaultPrefFile.GetBuffer());
PRBool exists = false;
fileSpec->Exists(&exists);
if (exists)
prefPtr->ReadUserPrefsFrom(fileSpec);
else
return false;
return true;
}
int
main(int argc, char* argv[])
{
initPref() ;
nsresult rv;
nsCOMPtr<nsINetDataCache> cache;
rv = NS_AutoregisterComponents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(cache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
InitQueue();
PRUnichar* description;
rv = cache->GetDescription(&description);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache description");
nsCAutoString descStr(description);
printf("Testing: %s\n", descStr.GetBuffer());
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
PRUint32 startOccupancy;
rv = cache->GetStorageInUse(&startOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
PRUint32 numEntries = (PRUint32)-1;
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
rv = FillCache(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
rv = TestRead(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
rv = TestRecordID(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't index records using record ID");
rv = TestEnumeration(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully enumerate records");
rv = TestTruncation(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully truncate records");
rv = TestOffsetWrites(cache);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't successfully write to records using non-zero offsets");
rv = cache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
rv = cache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
PRUint32 endOccupancy;
rv = cache->GetStorageInUse(&endOccupancy);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get cache occupancy");
NS_ASSERTION(startOccupancy == endOccupancy, "Cache occupancy not correctly computed ?");
return 0;
}

View File

@ -1,67 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* This is a super cool class that does the background thread magic using
* NSPR Threads. This class is used to maintain odd tasks in the background
* like like updating, expiration, validation and garbage collection.
*
* Note that this is a noop active when the cache manager is offline.
*
* In PRThread terms, this is a PR_USER_THREAD with local scope.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsBkgThread_h__
#define nsBkgThread_h__
//#include "nsISupports.h"
#include "prthread.h"
#include "prinrval.h"
class nsBkgThread//: public nsISupports
{
public:
nsBkgThread(PRIntervalTime iSleepTime, PRBool bStart=PR_TRUE);
virtual ~nsBkgThread();
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
void Process(void);
virtual void Run(void) = 0;
void Stop(void);
protected:
PRThread* m_pThread;
PRBool m_bContinue;
PRIntervalTime m_SleepTime;
private:
nsBkgThread(const nsBkgThread& o);
nsBkgThread& operator=(const nsBkgThread& o);
};
#endif // nsBkgThread_h__

View File

@ -1,56 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* This class is the actual implementation of the original class nsBkgThread,
* but I am too lazy to move the comments from nsBkgThread's
* header file to here. :-)
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsCacheBkgThd_h__
#define nsCacheBkgThd_h__
#include "nsBkgThread.h"
class nsCacheBkgThd: public nsBkgThread
{
public:
nsCacheBkgThd(PRIntervalTime iSleepTime);
virtual ~nsCacheBkgThd();
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
void Run(void);
protected:
private:
nsCacheBkgThd(const nsCacheBkgThd& o);
nsCacheBkgThd& operator=(const nsCacheBkgThd& o);
};
#endif // nsCacheBkgThd_h__

View File

@ -1,89 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* A simple cache iterator for cache architecture. This is a temporary class
* which will be (should be) replaced by more professional quality code, or
* at least moved to a more common area later on.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsCacheIterator_h__
#define nsCacheIterator_h__
#include "nsIterator.h"
#include "prtypes.h"
#include "nsICacheModule.h"
#include "nsICacheObject.h"
class nsCacheIterator: public nsIterator
{
public:
nsCacheIterator(nsICacheModule* i_pModule);
virtual ~nsCacheIterator();
virtual PRBool IsDone(void) const;
virtual nsICacheObject* Current(void) const;
private:
nsCacheIterator(const nsCacheIterator& o);
nsCacheIterator& operator=(const nsCacheIterator& o);
nsICacheModule* m_pModule;
};
inline
nsCacheIterator::nsCacheIterator(nsICacheModule* i_pModule): m_pModule(i_pModule)
{
}
inline
nsCacheIterator::~nsCacheIterator()
{
}
inline
PRBool nsCacheIterator::IsDone(void) const
{
/*
if (m_pModule)
{
return m_pModule->Entries() <= m_Index;
}
else
return PR_FALSE;
*/
}
inline
nsICacheObject* nsCacheIterator::Current(void) const
{
nsICacheObject* pObj ;
if (m_pModule)
{
m_pModule->GetObjectByIndex(m_Index, &pObj);
return pObj ;
}
return 0;
}
#endif // nsCacheIterator_h__

View File

@ -1,212 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsCacheManager- The boss of cache architecture. Contains all "external"
* functions for use by people who don't care/want to know the internals
* of the cache architecture.
*
* - Gagan Saksena 09/15/98
*
* Design and original implementation by Gagan Saksena 02/02/98
*
*/
#ifndef _CacheManager_H_
#define _CacheManager_H_
#include "nsISupports.h"
#include "nsIFactory.h"
#include "nsICacheManager.h"
#include "prlog.h"
#include "nsMonitorable.h"
#include "nsICacheModule.h"
#include "nsICacheObject.h"
#include "nsCacheBkgThd.h"
#include <stdio.h>
// class nsMemModule;
// class nsDiskModule;
// class nsCachePref;
// class nsCacheBkgThd;
class nsCacheManager : public nsICacheManager , public nsMonitorable
{
public:
nsCacheManager();
virtual ~nsCacheManager();
NS_DECL_ISUPPORTS
NS_IMETHOD Contains(const char* i_url ) const;
// PRBool Contains(const char* i_url) const ;
/* Number of modules in the cache manager */
NS_IMETHOD Entries(PRInt16 * n_Entries) const;
// PRInt16 Entries( ) const ;
NS_IMETHOD AddModule(PRInt16 * n_Index, nsICacheModule* pModule);
// InsertModule
NS_IMETHOD GetModule (PRInt16 i_index, nsICacheModule** pmodule) const ;
// nsCacheModule* GetModule(PRInt16 i_index) const;
NS_IMETHOD GetDiskModule(nsICacheModule** pmodule) const ;
// nsDiskModule* GetDiskModule() const;
NS_IMETHOD GetMemModule(nsICacheModule** pmodule) const ;
// nsMemModule* GetMemModule() const;
NS_IMETHOD GetPrefs(nsICachePref** pPref) const ;
// nsCachePref* GetPrefs(void) const;
NS_IMETHOD GetObj(const char* i_url, void ** o_pObject) const;
NS_IMETHOD InfoAsHTML(char** o_Buffer) const;
NS_IMETHOD IsOffline(PRBool *bOffline) const;
NS_IMETHOD Offline(PRBool bSet);
NS_IMETHOD Remove(const char* i_url);
/* Performance measure- microseconds */
NS_IMETHOD WorstCaseTime(PRUint32 * o_Time) const;
/* Singleton */
static nsCacheManager* GetInstance();
// Initialize the cache manager. Constructor doesn't call this.
// So you must specify this separately.
// GetInstance will call it automatically. - yixiong
void Init();
// const char* Trace() const;
protected:
NS_IMETHOD ContainsExactly(const char* i_url, PRBool * bContain) const;
nsICacheModule* LastModule() const;
//PRBool Lock(void);
//void Unlock(void);
/*
class MgrMonitor
{
public:
MgrMonitor() { nsCacheManager::GetInstance()->Lock();}
~MgrMonitor() { nsCacheManager::GetInstance()->Unlock();}
};
friend MgrMonitor;
*/
private:
nsCacheBkgThd* m_pBkgThd;
nsICacheModule* m_pFirstModule;
PRMonitor* m_pMonitor;
PRBool m_bOffline;
nsICachePref* m_pPrefs;
nsCacheManager(const nsCacheManager& cm);
nsCacheManager& operator=(const nsCacheManager& cm);
static nsCacheManager * gInstance ;
};
class nsCacheManagerFactory : public nsIFactory
{
public:
nsCacheManagerFactory( ) ;
virtual ~nsCacheManagerFactory( ) ;
NS_DECL_ISUPPORTS
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult) ;
NS_IMETHOD LockFactory(PRBool aLock) ;
} ;
inline NS_IMETHODIMP
nsCacheManager::GetDiskModule( nsICacheModule ** pModule) const
{
PR_ASSERT(m_pFirstModule);
nsresult rv ;
*pModule = nsnull ;
// return (m_pFirstModule) ? (nsDiskModule*) m_pFirstModule->NextModule() : NULL;
if (m_pFirstModule) {
rv = m_pFirstModule->GetNextModule(pModule) ;
if (NS_SUCCEEDED(rv) && *pModule){
return NS_OK ;
}
// else
// return NS_ERROR_FAILURE ;
}
return NS_ERROR_FAILURE ;
}
inline NS_IMETHODIMP
nsCacheManager::GetMemModule(nsICacheModule ** pModule ) const
{
PR_ASSERT(m_pFirstModule);
*pModule = m_pFirstModule;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheManager::GetPrefs(nsICachePref ** pPref) const
{
PR_ASSERT(m_pPrefs);
*pPref = m_pPrefs;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheManager::IsOffline(PRBool * bOffline) const
{
*bOffline = m_bOffline;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheManager::Offline(PRBool i_bSet)
{
m_bOffline = i_bSet;
return NS_OK ;
}
#endif

View File

@ -1,469 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsCacheObject is the class that holds the basic definition of the
* cache object. A lot of changes are likely to occur before this
* goes on stage.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsCacheObject_h__
#define nsCacheObject_h__
// #if 0
#include "nsISupports.h"
// #endif
#include "pratom.h"
#include "nscore.h"
#include "nsIFactory.h"
#include "nsRepository.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsStream.h"
#include "prtypes.h"
#include "prinrval.h"
#include "nsICacheObject.h"
static const PRUint32 kCACHE_VERSION = 5;
// class nsStream;
class nsCacheObject : public nsICacheObject
{
public:
enum state_flags
{
INIT=0,
PARTIAL=1,
COMPLETE=2,
ABORTED=3,
EXPIRED=4,
CORRUPT=5
};
nsCacheObject();
nsCacheObject(const nsCacheObject& another);
nsCacheObject(const char* i_url);
virtual ~nsCacheObject();
NS_DECL_ISUPPORTS
/* public interface */
// NS_IMETHOD Create(const char * i_url, void * aObj) = 0 ;
// NS_IMETHOD Destroy(void * pThis) = 0 ;
NS_IMETHOD GetAddress(char ** Addr) const ;
NS_IMETHOD SetAddress(const char* i_Address) ;
NS_IMETHOD GetCharset(char ** CSet) const ;
NS_IMETHOD SetCharset(const char* i_CharSet) ;
NS_IMETHOD GetContentEncoding(char ** Encoding) const ;
NS_IMETHOD SetContentEncoding(const char* i_Encoding) ;
NS_IMETHOD GetContentLength(PRUint32 * CLeng) const ;
NS_IMETHOD SetContentLength(PRUint32 i_Len) ;
NS_IMETHOD GetContentType(char ** CType) const ;
NS_IMETHOD SetContentType(const char* i_Type) ;
NS_IMETHOD GetEtag(char ** Etag) const ;
NS_IMETHOD SetEtag(const char* i_Etag) ;
NS_IMETHOD GetExpires(PRIntervalTime * iTime) const ;
NS_IMETHOD SetExpires(const PRIntervalTime i_Time) ;
NS_IMETHOD GetFilename(char ** Filename) const ;
NS_IMETHOD SetFilename(const char* i_Filename) ;
NS_IMETHOD GetIsCompleted(PRBool *bComplete) const ;
NS_IMETHOD SetIsCompleted(PRBool bComplete) ;
NS_IMETHOD GetLastAccessed(PRIntervalTime * iTime) const ;
NS_IMETHOD GetLastModified(PRIntervalTime * iTime) const ;
NS_IMETHOD SetLastModified(const PRIntervalTime i_Time) ;
NS_IMETHOD GetModuleIndex(PRInt16 * m_index) const ;
NS_IMETHOD SetModuleIndex(const PRUint16 m_index) ;
NS_IMETHOD GetPageServicesURL(char ** o_url) const ;
NS_IMETHOD SetPageServicesURL(const char* i_Url) ;
NS_IMETHOD GetPostData(char ** pData) const ;
NS_IMETHOD SetPostData(const char* i_PostData, const PRUint32 i_Len) ;
NS_IMETHOD GetPostDataLen(PRUint32 * dLeng) const ;
/* Accessor functions for the size of the cache object */
NS_IMETHOD GetSize(PRUint32 * pSize) const ;
NS_IMETHOD SetSize(const PRUint32 i_Size) ;
/* Accessor functions for the state of the cache object.
* Some states are changed internally.
*/
NS_IMETHOD GetState(PRUint32 * pState) const ;
NS_IMETHOD SetState(const PRUint32 i_State) ;
NS_IMETHOD GetStream(nsStream ** pStream) const ;
// NS_IMETHOD MakeStream(void) ;
NS_IMETHOD Hits(PRUint32 * pHits) const ;
NS_IMETHOD IsExpired(PRBool *bGet) const ;
NS_IMETHOD IsPartial(PRBool *bGet) const ;
NS_IMETHOD Read(char* o_Destination, PRUint32 i_Len,
PRUint32 * pLeng) ;
/* Reset the streams/state, read/write locks, etc. */
NS_IMETHOD Reset(void) ;
// NS_IMETHOD Synch(void) = 0 ;
NS_IMETHOD Write(const char* i_buffer, const PRUint32 i_length,
PRUint32 * oLeng) ;
// NS_IMETHOD InitUrl(const char* i_url) ;
/* Read and write info about this cache object */
NS_IMETHOD GetInfo(void** o_info) ;
NS_IMETHOD SetInfo(void* i_info /*, PRUint32 len */);
NS_IMETHOD GetInfoSize(PRUint32* o_size) ;
/* end public interface */
const char* Trace() const;
protected:
void Init();
char* m_Charset;
char* m_ContentEncoding;
PRUint32 m_ContentLength;
char* m_ContentType;
char* m_Etag;
PRIntervalTime m_Expires;
char* m_Filename;
PRUint32 m_State;
PRUint16 m_Hits;
PRUint32 m_info_size;
PRBool m_bIsCompleted; /* Marked when the stream complete is called */
PRIntervalTime m_LastAccessed, m_LastModified;
PRInt16 m_Module;
void* m_pInfo;
char* m_PageServicesURL;
char* m_PostData;
PRUint32 m_PostDataLen;
PRUint32 m_Size;
nsStream* m_pStream;
char* m_URL;
private:
nsCacheObject& operator=(const nsCacheObject& x);
};
inline NS_IMETHODIMP
nsCacheObject::GetAddress(char ** Addr) const
{
if (!Addr)
return NS_ERROR_NULL_POINTER;
*Addr = m_URL ;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetCharset(char ** CSet) const
{
if (!CSet)
return NS_ERROR_NULL_POINTER;
*CSet = m_Charset;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::GetContentEncoding(char ** Encoding) const
{
if (!Encoding)
return NS_ERROR_NULL_POINTER;
*Encoding=m_ContentEncoding;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::GetContentLength(PRUint32 * CLeng) const
{
if (!CLeng)
return NS_ERROR_NULL_POINTER;
*CLeng = m_ContentLength;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::SetContentLength(PRUint32 i_Size)
{
m_ContentLength = i_Size;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetContentType(char ** CType) const
{
if (!CType)
return NS_ERROR_NULL_POINTER;
*CType = m_ContentType;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetEtag(char ** Etag) const
{
if (!Etag)
return NS_ERROR_NULL_POINTER;
*Etag = m_Etag;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetExpires(PRIntervalTime * iTime) const
{
if (!iTime)
return NS_ERROR_NULL_POINTER;
*iTime = m_Expires;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::SetExpires(PRIntervalTime i_Expires)
{
m_Expires = i_Expires;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetFilename(char ** Filename) const
{
if (!Filename)
return NS_ERROR_NULL_POINTER;
*Filename = m_Filename;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::Hits(PRUint32 * pHits) const
{
*pHits = m_Hits;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetIsCompleted(PRBool *bComplete) const
{
if (m_bIsCompleted) {
*bComplete=PR_TRUE ;
}
else {
*bComplete=PR_FALSE ;
}
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::SetIsCompleted(PRBool bComplete)
{
m_bIsCompleted = bComplete;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::IsExpired(PRBool *bExpired) const
{
if (nsCacheObject::EXPIRED==m_State)
*bExpired = PR_TRUE ;
if (m_Expires <= PR_IntervalNow()) {
((nsCacheObject*)this)->m_State = nsCacheObject::EXPIRED;
*bExpired = PR_TRUE ;
}
else
*bExpired = PR_FALSE ;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::IsPartial(PRBool *bPartial) const
{
if (m_ContentLength != m_Size)
*bPartial = PR_TRUE ;
else
*bPartial = PR_FALSE ;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetLastAccessed(PRIntervalTime * iTime) const
{
*iTime = m_LastAccessed;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetLastModified(PRIntervalTime * iTime) const
{
*iTime = m_LastModified;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::SetLastModified(const PRIntervalTime i_LastModified)
{
m_LastModified = i_LastModified;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetModuleIndex(PRInt16 * m_index) const
{
*m_index = m_Module;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::SetModuleIndex(PRUint16 m_index)
{
m_Module = m_index;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetPageServicesURL(char ** o_url) const
{
if (!o_url)
return NS_ERROR_NULL_POINTER;
*o_url = m_PageServicesURL;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::GetPostData(char ** pData) const
{
if (!pData)
return NS_ERROR_NULL_POINTER;
*pData = m_PostData;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::GetPostDataLen(PRUint32 * dLeng) const
{
if (!dLeng)
return NS_ERROR_NULL_POINTER;
*dLeng = m_PostDataLen;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCacheObject::GetSize(PRUint32 * pSize) const
{
if (!pSize)
return NS_ERROR_NULL_POINTER;
*pSize = m_Size;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::SetSize(PRUint32 i_Size)
{
m_Size = i_Size;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetState(PRUint32 * pState) const
{
if (!pState)
return NS_ERROR_NULL_POINTER;
*pState = m_State;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::SetState(PRUint32 i_State)
{
m_State = i_State;
return NS_OK ;
};
inline NS_IMETHODIMP
nsCacheObject::GetStream(nsStream** pStream) const
{
if (!pStream)
return NS_ERROR_NULL_POINTER;
*pStream = m_pStream;
return NS_OK ;
}
/////////////////////////////////////////////////////////////////////
// nsCacheObjectFactory
class nsCacheObjectFactory : public nsIFactory {
public:
nsCacheObjectFactory();
virtual ~nsCacheObjectFactory();
NS_DECL_ISUPPORTS
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
} ;
#endif // nsCacheObject_h__

View File

@ -1,199 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsCachePref. A class to separate the preference related code to
* one place. This is an incomplete implementation, I need to access
* the libprefs directly, but that would add another dependency. And
* libpref comes with a JS dependency... so holding this off for the
* moment.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsCachePref_h__
#define nsCachePref_h__
#include "nsICachePref.h"
#include "nsIFactory.h"
#include "prtypes.h"
#include "prlog.h"
class nsCachePref : public nsICachePref
{
public:
nsCachePref(void);
virtual ~nsCachePref();
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
NS_DECL_ISUPPORTS
/*
enum Refresh
{
ONCE,
ALWAYS,
NEVER
};
*/
NS_IMETHOD GetBkgSleepTime (PRUint32* o_time) ;
NS_IMETHOD GetDiskCacheDBFilename (char** o_name) ; /* like Fat.db */
NS_IMETHOD GetDiskCacheFolder (char** o_folder) ; /* Cache dir */
NS_IMETHOD GetDiskCacheSSL (PRBool* o_bSet) ;
NS_IMETHOD SetDiskCacheSSL (PRBool i_bSet) ;
NS_IMETHOD GetDiskCacheSize (PRUint32* o_size) ;
NS_IMETHOD SetDiskCacheSize (const PRUint32 i_size) ;
NS_IMETHOD GetMemCacheSize (PRUint32 * o_size) ;
NS_IMETHOD SetMemCacheSize (const PRUint32 i_size) ;
NS_IMETHOD GetFrequency (nsICachePref::Refresh* o_frequency) ;
/* Revalidating in background, makes IMS calls in the bkg thread to
update cache entries. TODO, this should be at a bigger time period
than the cache cleanup routine */
NS_IMETHOD RevalidateInBkg (PRBool* i_bRevalidateInBkg) ;
/* Setup all prefs */
NS_IMETHOD SetupPrefs(const char* i_Pref) ;
static nsICachePref* GetInstance(void);
private:
nsCachePref(const nsCachePref& o);
nsCachePref& operator=(const nsCachePref& o);
PRBool m_bRevalidateInBkg;
PRBool m_bDiskCacheSSL;
nsICachePref::Refresh m_RefreshFreq;
PRUint32 m_MemCacheSize;
PRUint32 m_DiskCacheSize;
char* m_DiskCacheDBFilename;
char* m_DiskCacheFolder;
PRUint32 m_BkgSleepTime;
};
inline NS_IMETHODIMP
nsCachePref::GetDiskCacheSize(PRUint32* o_size)
{
if (!o_size)
return NS_ERROR_NULL_POINTER ;
*o_size = m_DiskCacheSize;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::SetDiskCacheSize(const PRUint32 i_Size)
{
m_DiskCacheSize = i_Size;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::GetDiskCacheSSL(PRBool* o_bSet)
{
if (!o_bSet)
return NS_ERROR_NULL_POINTER ;
*o_bSet = m_bDiskCacheSSL;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::SetDiskCacheSSL(PRBool bSet)
{
m_bDiskCacheSSL = bSet;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::GetDiskCacheFolder(char** o_folder)
{
if (!o_folder)
return NS_ERROR_NULL_POINTER ;
PR_ASSERT(m_DiskCacheFolder);
*o_folder = m_DiskCacheFolder ;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::GetMemCacheSize(PRUint32 * o_size)
{
if (!o_size)
return NS_ERROR_NULL_POINTER ;
*o_size = m_MemCacheSize;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::SetMemCacheSize(const PRUint32 i_Size)
{
m_MemCacheSize = i_Size;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::RevalidateInBkg(PRBool* o_RevalidateInBkg)
{
if (!o_RevalidateInBkg)
return NS_ERROR_NULL_POINTER ;
*o_RevalidateInBkg = m_bRevalidateInBkg;
return NS_OK ;
}
inline NS_IMETHODIMP
nsCachePref::GetFrequency (nsICachePref::Refresh* o_frequency)
{
if (!o_frequency)
return NS_ERROR_NULL_POINTER ;
*o_frequency = m_RefreshFreq ;
return NS_OK ;
}
/////////////////////////////////////////////////////////////////////
// nsCacheObjectFactory
class nsCachePrefFactory : public nsIFactory {
public:
nsCachePrefFactory();
virtual ~nsCachePrefFactory();
NS_DECL_ISUPPORTS
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
} ;
#endif // nsCachePref_h__

View File

@ -1,136 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsDiskModule. The disk cache module that stores the cache objects
* on the disk.
*
* Gagan Saksena 02/03/98
*
*/
#ifndef _nsDiskModule_H_
#define _nsDiskModule_H_
#include "nsICacheModule.h"
#include "nsIterator.h"
#include "nsCacheIterator.h"
#include "nsEnumeration.h"
#include "nsCachePref.h"
#include "nsMonitorable.h"
#include "mcom_db.h"
class nsDiskModule : public nsMonitorable, public nsICacheModule
{
public:
NS_DECL_ISUPPORTS
//////////////////////////////////////////////////////////////////////////
// nsICacheModule Methods:
NS_IMETHOD AddObject(nsICacheObject* i_pObject);
NS_IMETHOD ContainsURL(const char* i_url, PRBool* o_bContain);
NS_IMETHOD ContainsCacheObj(nsICacheObject* i_pObject, PRBool* o_bContain) ;
NS_IMETHOD Enable (PRBool i_Enable);
NS_IMETHOD GetNumOfEntries (PRUint32* o_entry);
NS_IMETHOD GetEnumerator (nsEnumeration** o_enum);
/* Enumerations with a function pointer - TODO */
//TODO move to own interface for both Garbage Collection and Revalidation
NS_IMETHOD GarbageCollect (void);
NS_IMETHOD GetObjectByURL (const char* i_url, nsICacheObject** o_pObj);
NS_IMETHOD GetObjectByIndex (const PRUint32 i_index, nsICacheObject** o_pObj);
NS_IMETHOD GetStreamFor (const nsICacheObject* i_pObject, nsStream** o_pStream);
NS_IMETHOD IsEnabled (PRBool* o_bEnabled);
/* Can't do additions, deletions, validations, expirations */
NS_IMETHOD IsReadOnly (PRBool* o_bReadOnly);
NS_IMETHOD GetNextModule (nsICacheModule** o_pCacheModule);
NS_IMETHOD SetNextModule (nsICacheModule* i_pCacheModule);
NS_IMETHOD RemoveByURL (const char* i_url);
NS_IMETHOD RemoveByIndex (const PRUint32 i_index);
NS_IMETHOD RemoveByObject (nsICacheObject* i_pObject);
NS_IMETHOD RemoveAll (void);
NS_IMETHOD Revalidate (void);
NS_IMETHOD ReduceSizeTo (const PRUint32 i_newsize);
NS_IMETHOD GetSize (PRUint32* o_size);
NS_IMETHOD SetSize (const PRUint32 i_size);
NS_IMETHOD GetSizeInUse (PRUint32* o_size);
/////////////////////////////////////////////////////////////////////////
// nsDiskModule Methods
nsDiskModule();
nsDiskModule(const PRUint32 size);
virtual ~nsDiskModule();
PRUint32 AverageSize(void) const;
static NS_METHOD
Create (nsISupports *aOuter, REFNSIID aIID, void** aResult);
private:
enum sync_frequency
{
EVERYTIME,
IDLE,
NEVER
} m_Sync;
PRBool InitDB(void);
nsDiskModule(const nsDiskModule& dm);
nsDiskModule& operator=(const nsDiskModule& dm);
PRUint32 m_Entries;
PRUint32 m_Size;
PRUint32 m_SizeInUse;
PRBool m_Enabled;
nsEnumeration* m_pEnumeration;
nsCacheIterator* m_pIterator;
nsICacheModule* m_pNext;
DB* m_pDB;
};
#endif

View File

@ -1,101 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Another temporary class that needs to be replaced by a commonly
* used one, or made a commonly used one.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsEnumeration_h__
#define nsEnumeration_h__
//#include "nsISupports.h"
#include "nsIterator.h"
#include "prlog.h"
class nsEnumeration //: public nsISupports
{
public:
nsEnumeration(nsIterator* iter);
virtual ~nsEnumeration();
PRBool HasMoreElements(void);
void* NextElement(void);
void Reset(void);
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
protected:
nsIterator* m_pIter;
private:
nsEnumeration(const nsEnumeration& o);
nsEnumeration& operator=(const nsEnumeration& o);
};
inline
nsEnumeration::nsEnumeration(nsIterator* iter):m_pIter(iter)
{
PR_ASSERT(iter);
if (m_pIter)
m_pIter->First();
}
inline
nsEnumeration::~nsEnumeration()
{
}
inline
PRBool nsEnumeration::HasMoreElements(void)
{
if (m_pIter) //remove this check for optimization?
return m_pIter->IsDone() ? PR_FALSE : PR_TRUE;
return PR_FALSE;
}
inline
void* nsEnumeration::NextElement(void)
{
if (m_pIter)
{
void* pTemp = m_pIter->CurrentItem();
m_pIter->Next();
return pTemp;
}
return 0;
}
inline
void nsEnumeration::Reset(void)
{
if (m_pIter)
{
m_pIter->First();
}
}
#endif // nsEnumeration_h__

View File

@ -1,71 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsFileStream. The file/disk based implementation of the nsStream class.
* It basically maps the read write functions to the file equivalents.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsFileStream_h__
#define nsFileStream_h__
//#include "nsISupports.h"
#include "nsStream.h"
#include "prio.h" // PRFileDesc
class nsFileStream: public nsStream
{
public:
nsFileStream(const char* i_Filename);
virtual ~nsFileStream();
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
PRFileDesc* FileDesc(void);
PRInt32 Read(void* o_Buffer, PRUint32 i_Len);
void Reset(void);
PRInt32 Write(const void* i_Buffer, PRUint32 i_Len);
protected:
PRBool Open(void);
private:
nsFileStream(const nsFileStream& o);
nsFileStream& operator=(const nsFileStream& o);
PRFileDesc* m_pFile;
char* m_pFilename;
};
inline
PRFileDesc* nsFileStream::FileDesc(void)
{
return m_pFile;
}
#endif // nsFileStream_h__

View File

@ -1,74 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* Another common class that needs to be replaced/removed/recycled.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsIterator_h__
#define nsIterator_h__
//#include "nsISupports.h"
#include "prtypes.h"
class nsIterator //:public nsISupports
{
public:
virtual void First(void);
virtual PRBool IsDone(void) const = 0;
virtual void Next(void);
virtual void* CurrentItem(void) const;
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
protected:
nsIterator() {m_Index = 0;};
PRUint32 m_Index;
};
inline
void nsIterator::First(void)
{
m_Index = 0;
}
inline
void nsIterator::Next(void)
{
++m_Index;
}
inline
void* nsIterator::CurrentItem(void) const
{
return 0;
}
#endif // nsIterator_h__

View File

@ -1,162 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsMemModule. The memory based cache module.
*
* Gagan Saksena
* 02/03/98
*
*/
#ifndef _nsMemModule_H_
#define _nsMemModule_H_
#include "nsICacheModule.h"
#include "nsMemCacheObject.h"
#include "nsCachePref.h"
#include "nsCacheIterator.h"
#include "nsMonitorable.h"
//#include "nsHash.h" // TODO - replace with nsHashtable when the XPCOM_BRANCH merges
//#include "nsHashtable.h"
class nsMemModule : public nsMonitorable, public nsICacheModule
{
public:
NS_DECL_ISUPPORTS
//////////////////////////////////////////////////////////////////////////
// nsICacheModule Methods:
NS_IMETHOD AddObject(nsICacheObject* i_pObject);
NS_IMETHOD ContainsURL(const char* i_url, PRBool* o_bContain);
NS_IMETHOD ContainsCacheObj(nsICacheObject* i_pObject, PRBool* o_bContain) ;
NS_IMETHOD Enable (PRBool i_Enable);
NS_IMETHOD GetNumOfEntries (PRUint32* o_entry);
NS_IMETHOD GetEnumerator (nsEnumeration** o_enum);
/* Enumerations with a function pointer - TODO */
//TODO move to own interface for both Garbage Collection and Revalidation
NS_IMETHOD GarbageCollect (void);
NS_IMETHOD GetObjectByURL (const char* i_url, nsICacheObject** o_pObj);
NS_IMETHOD GetObjectByIndex (const PRUint32 i_index, nsICacheObject** o_pObj);
NS_IMETHOD GetStreamFor (const nsICacheObject* i_pObject, nsStream** o_pStream);
NS_IMETHOD IsEnabled (PRBool* o_bEnabled);
/* Can't do additions, deletions, validations, expirations */
NS_IMETHOD IsReadOnly (PRBool* o_bReadOnly);
NS_IMETHOD GetNextModule (nsICacheModule** o_pCacheModule);
NS_IMETHOD SetNextModule (nsICacheModule* i_pCacheModule);
NS_IMETHOD RemoveByURL (const char* i_url);
NS_IMETHOD RemoveByIndex (const PRUint32 i_index);
NS_IMETHOD RemoveByObject (nsICacheObject* i_pObject);
NS_IMETHOD RemoveAll (void);
NS_IMETHOD Revalidate (void);
NS_IMETHOD ReduceSizeTo (const PRUint32 i_newsize);
NS_IMETHOD GetSize (PRUint32* o_size);
NS_IMETHOD SetSize (const PRUint32 i_size);
NS_IMETHOD GetSizeInUse (PRUint32* o_size);
///////////////////////////////////////////////////////////////////////////
// Start of nsMemModule specific stuff...
// Here is a sample implementation using linked list
nsMemModule();
nsMemModule(const PRUint32 size);
virtual ~nsMemModule();
static NS_METHOD
Create (nsISupports *aOuter, REFNSIID aIID, void **aResult);
protected:
nsMemCacheObject* LastObject(void) const;
private:
nsMemCacheObject* m_pFirstObject;
//nsHash m_ht; //TODO replace with nsHashtable
//Optimization
nsMemCacheObject* m_pLastObject;
nsMemModule(const nsMemModule& mm);
nsMemModule& operator=(const nsMemModule& mm);
/*
class nsMemKey : public nsHashKey
{
public:
nsMemKey();
~nsMemKey();
PRUint32 HashValue();
PRBool Equals(nsHashKey *aKey);
nsHashKey* Clone();
};
*/
PRUint32 m_Entries;
PRUint32 m_Size;
PRUint32 m_SizeInUse;
PRBool m_Enabled;
nsEnumeration* m_pEnumeration;
nsCacheIterator* m_pIterator;
nsICacheModule* m_pNext;
};
inline
NS_IMETHODIMP nsMemModule::Revalidate(void)
{
// Mem module elements are never revalidated.
// It is a no-op.
return NS_OK;
}
#endif

View File

@ -1,63 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsMemStream. A memory based stream for use with memory objects
*
* -Gagan Saksena 09/15/98.
*/
#ifndef nsMemStream_h__
#define nsMemStream_h__
//#include "nsISupports.h"
#include "nsStream.h"
class nsMemStream: public nsStream
{
public:
nsMemStream();
virtual ~nsMemStream();
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
PRInt32 Read(void* o_Buffer, PRUint32 i_Len);
void Reset(void);
PRInt32 Write(const void* i_Buffer, PRUint32 i_Len);
protected:
private:
nsMemStream(const nsMemStream& o);
nsMemStream& operator=(const nsMemStream& o);
PRUint32 m_AllocSize;
PRUint32 m_ReadOffset;
PRUint32 m_WriteOffset;
void* m_pStart;
PRUint32 m_Size;
};
#endif // nsMemStream_h__

View File

@ -1,109 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsMonitorable. This is a cool class too. Its an easy of adding monitors
* actually PRMonitor behaviour to existing classes. The nsMonitorLocker is
* an excursion class that locks the scope in which is declared (on stack).
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsMonitorable_h__
#define nsMonitorable_h__
//#include "nsISupports.h"
#include "prmon.h"
#include "prlog.h"
class nsMonitorable//: public nsISupports
{
public:
nsMonitorable();
virtual ~nsMonitorable();
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
PRBool Lock(void);
void Unlock(void);
protected:
class MonitorLocker
{
public:
MonitorLocker(nsMonitorable* i_pThis);
~MonitorLocker();
private:
nsMonitorable* m_pMonitorable;
};
PRMonitor* m_pMonitor;
private:
nsMonitorable(const nsMonitorable& o);
nsMonitorable& operator=(const nsMonitorable& o);
};
inline
nsMonitorable::nsMonitorable(void):m_pMonitor(PR_NewMonitor())
{
}
inline
nsMonitorable::~nsMonitorable()
{
if (m_pMonitor)
{
PR_DestroyMonitor(m_pMonitor);
m_pMonitor = 0;
}
}
inline
PRBool nsMonitorable::Lock(void)
{
if (!m_pMonitor)
{
m_pMonitor = PR_NewMonitor();
if (!m_pMonitor)
return PR_FALSE;
}
PR_EnterMonitor(m_pMonitor);
return PR_TRUE;
}
inline
void nsMonitorable::Unlock(void)
{
PR_ASSERT(m_pMonitor);
if (m_pMonitor)
PR_ExitMonitor(m_pMonitor);
}
#endif // nsMonitorable_h__

View File

@ -1,74 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* A placeholder for the actual professional strength streams class. Works
* ok for me for now.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsStream_h__
#define nsStream_h__
//#include "nsISupports.h"
#include "prtypes.h"
class nsStream//: public nsISupports
{
public:
nsStream();
virtual ~nsStream();
/*
NS_IMETHOD QueryInterface(const nsIID& aIID,
void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
*/
virtual
PRInt32 Read(void* o_Buffer, PRUint32 i_Len) = 0;
virtual
void Reset(void) = 0;
virtual
PRInt32 Write(const void* i_Buffer, PRUint32 i_Len) = 0;
protected:
private:
nsStream(const nsStream& o);
nsStream& operator=(const nsStream& o);
};
inline
nsStream::nsStream(void)
{
//noop
}
inline
nsStream::~nsStream()
{
//noop
}
#endif // nsStream_h__

View File

@ -0,0 +1,46 @@
# Generated automatically from Makefile.in by configure.
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
VPATH = @srcdir@
srcdir = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcache
LIBRARY_NAME = nkmemcache_s
REQUIRES = nspr dbm
EXPORTS=nsMemCacheCID.h
CPPSRCS = \
nsMemCache.cpp \
nsMemCacheRecord.cpp \
nsMemCacheChannel.cpp \
$(NULL)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,42 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public License
# Version 1.0 (the "NPL"); you may not use this file except in
# compliance with the NPL. You may obtain a copy of the NPL at
# http://www.mozilla.org/NPL/
#
# Software distributed under the NPL is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
# for the specific language governing rights and limitations under the
# NPL.
#
# The Initial Developer of this code under the NPL is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = nkcache
LIBRARY_NAME = nkmemcache_s
CPP_OBJS = \
.\$(OBJDIR)\nsMemCache.obj \
.\$(OBJDIR)\nsMemCacheRecord.obj \
.\$(OBJDIR)\nsMemCacheChannel.obj \
$(NULL)
EXPORTS=nsMemCacheCID.h
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -rf $(OBJDIR)
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@ -0,0 +1,334 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
/**
* nsMemCache is the implementation of an in-memory network-data
* cache, used to cache the responses to network retrieval commands.
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by
* two different keys: a record id number and an opaque key, which is
* created by the cache manager by combining the URI with a "secondary
* key", e.g. HTTP post data.
*/
#include "nsMemCache.h"
#include "nsMemCacheRecord.h"
#include "nsIGenericFactory.h"
#include "nsString.h"
#include "nsHashtable.h"
#include "nsHashtableEnumerator.h"
#include "nsEnumeratorUtils.h"
PRInt32 nsMemCache::gRecordSerialNumber = 0;
nsMemCache::nsMemCache()
: mNumEntries(0), mOccupancy(0), mEnabled(PR_TRUE),
mHashTable(0)
{
NS_INIT_REFCNT();
}
nsMemCache::~nsMemCache()
{
nsresult rv;
rv = RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv) && (mNumEntries == 0),
"Failure to shut down memory cache. "
"Somewhere, someone is holding references to at least one cache record");
delete mHashTable;
}
nsresult
nsMemCache::Init()
{
mHashTable = new nsHashtable(256);
if (!mHashTable)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsMemCache, NS_GET_IID(nsINetDataCache))
NS_IMETHODIMP
nsMemCache::GetDescription(PRUnichar * *aDescription)
{
nsAutoString description("Memory Cache");
*aDescription = description.ToNewUnicode();
if (!*aDescription)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::Contains(const char *aKey, PRUint32 aKeyLength, PRBool *aFound)
{
nsOpaqueKey *opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
if (!opaqueKey)
return NS_ERROR_OUT_OF_MEMORY;
*aFound = mHashTable->Exists(opaqueKey);
delete opaqueKey;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetCachedNetData(const char *aKey, PRUint32 aKeyLength,
nsINetDataCacheRecord* *aRecord)
{
nsresult rv;
nsMemCacheRecord* record = 0;
nsOpaqueKey *opaqueKey2 = 0;
nsOpaqueKey *opaqueKey3 = 0;
nsOpaqueKey *opaqueKey;
opaqueKey = new nsOpaqueKey(aKey, aKeyLength);
if (!opaqueKey)
goto out_of_memory;
record = (nsMemCacheRecord*)mHashTable->Get(opaqueKey);
delete opaqueKey;
// No existing cache database entry was found. Create a new one.
// This requires two mappings in the hash table:
// Record ID ==> record
// Opaque key ==> record
if (!record) {
record = new nsMemCacheRecord;
if (!record)
goto out_of_memory;
rv = record->Init(aKey, aKeyLength, ++gRecordSerialNumber, this);
if (NS_FAILED(rv)) goto out_of_memory;
// Index the record by opaque key
opaqueKey2 = new nsOpaqueKey(record->mKey, record->mKeyLength);
if (!opaqueKey2) goto out_of_memory;
mHashTable->Put(opaqueKey2, record);
// Index the record by it's record ID
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &record->mRecordID);
opaqueKey3 = new nsOpaqueKey(recordIDbytes,
sizeof record->mRecordID);
if (!opaqueKey3) {
// Clean up the first record from the hash table
mHashTable->Remove(opaqueKey);
goto out_of_memory;
}
mHashTable->Put(opaqueKey3, record);
// The hash table holds on to the record
record->AddRef();
delete opaqueKey2;
delete opaqueKey3;
mNumEntries++;
}
record->AddRef();
*aRecord = record;
return NS_OK;
out_of_memory:
delete opaqueKey2;
delete opaqueKey3;
delete record;
return NS_ERROR_OUT_OF_MEMORY;
}
NS_IMETHODIMP
nsMemCache::GetCachedNetDataByID(PRInt32 RecordID,
nsINetDataCacheRecord* *aRecord)
{
nsOpaqueKey opaqueKey(NS_REINTERPRET_CAST(const char *, &RecordID),
sizeof RecordID);
*aRecord = (nsINetDataCacheRecord*)mHashTable->Get(&opaqueKey);
if (*aRecord) {
NS_ADDREF(*aRecord);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_METHOD
nsMemCache::Delete(nsMemCacheRecord* aRecord)
{
nsMemCacheRecord *removedRecord;
char *recordIDbytes = NS_REINTERPRET_CAST(char *, &aRecord->mRecordID);
nsOpaqueKey opaqueRecordIDKey(recordIDbytes,
sizeof aRecord->mRecordID);
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueRecordIDKey);
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
nsOpaqueKey opaqueKey(aRecord->mKey, aRecord->mKeyLength);
removedRecord = (nsMemCacheRecord*)mHashTable->Remove(&opaqueKey);
NS_ASSERTION(removedRecord == aRecord, "memory cache database inconsistent");
aRecord->Release();
mNumEntries--;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetEnabled(PRBool *aEnabled)
{
NS_ENSURE_ARG(aEnabled);
*aEnabled = mEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::SetEnabled(PRBool aEnabled)
{
mEnabled = aEnabled;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetFlags(PRUint32 *aFlags)
{
NS_ENSURE_ARG(aFlags);
*aFlags = MEMORY_CACHE;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetNumEntries(PRUint32 *aNumEntries)
{
NS_ENSURE_ARG(aNumEntries);
*aNumEntries = mNumEntries;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetMaxEntries(PRUint32 *aMaxEntries)
{
NS_ENSURE_ARG(aMaxEntries);
*aMaxEntries = MEM_CACHE_MAX_ENTRIES;
return NS_OK;
}
static NS_METHOD
HashEntryConverter(nsHashKey *aKey, void *aValue,
void *unused, nsISupports **retval)
{
nsMemCacheRecord *record;
nsOpaqueKey *opaqueKey;
record = (nsMemCacheRecord*)aValue;
opaqueKey = (nsOpaqueKey*)aKey;
// Hash table keys that index cache entries by their record ID
// shouldn't be enumerated.
if ((opaqueKey->GetKeyLength() == sizeof(PRInt32))) {
#ifdef DEBUG
PRInt32 recordID;
record->GetRecordID(&recordID);
NS_ASSERTION(*((PRInt32*)opaqueKey->GetKey()) == recordID,
"Key has incorrect key length");
#endif
return NS_ERROR_FAILURE;
}
NS_IF_ADDREF(record);
*retval = NS_STATIC_CAST(nsISupports*, record);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::NewCacheEntryIterator(nsISimpleEnumerator* *aIterator)
{
nsCOMPtr<nsIEnumerator> iterator;
NS_ENSURE_ARG(aIterator);
NS_NewHashtableEnumerator(mHashTable, HashEntryConverter,
mHashTable, getter_AddRefs(iterator));
return NS_NewAdapterEnumerator(aIterator, iterator);
}
NS_IMETHODIMP
nsMemCache::GetNextCache(nsINetDataCache* *aNextCache)
{
NS_ENSURE_ARG(aNextCache);
*aNextCache = mNextCache;
NS_ADDREF(*aNextCache);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::SetNextCache(nsINetDataCache* aNextCache)
{
mNextCache = aNextCache;
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::GetStorageInUse(PRUint32 *aStorageInUse)
{
NS_ENSURE_ARG(aStorageInUse);
// Convert from bytes to KB
*aStorageInUse = (mOccupancy >> 10);
return NS_OK;
}
NS_IMETHODIMP
nsMemCache::RemoveAll(void)
{
PRBool failed;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> recordSupports;
nsCOMPtr<nsINetDataCacheRecord> record;
nsresult rv;
failed = PR_FALSE;
rv = NewCacheEntryIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv))
return rv;
PRBool notDone;
while (1) {
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(recordSupports));
record = do_QueryInterface(recordSupports);
recordSupports = 0;
PRUint32 bytesUsed;
record->GetStoredContentLength(&bytesUsed);
rv = record->Delete();
if (NS_FAILED(rv)) {
failed = PR_TRUE;
continue;
}
mOccupancy -= bytesUsed;
}
if (failed)
return NS_ERROR_FAILURE;
return NS_OK;
}

View File

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
/**
* nsMemCache is the implementation of an in-memory network-data
* cache, used to cache the responses to network retrieval commands.
* Each cache entry may contain both content, e.g. GIF image data, and
* associated metadata, e.g. HTTP headers. Each entry is indexed by
* two different keys: a record id number and an opaque key, which is
* created by the cache manager by combining the URI with a "secondary
* key", e.g. HTTP post data.
*/
#ifndef _nsMemCache_h_
#define _nsMemCache_h_
#include "nsINetDataCache.h"
// Maximum number of URIs that may be resident in the cache
#define MEM_CACHE_MAX_ENTRIES 1000
#define MEM_CACHE_SEGMENT_SIZE (1 << 12)
#define MEM_CACHE_MAX_ENTRY_SIZE (1 << 20)
class nsHashtable;
class nsMemCacheRecord;
class nsMemCache : public nsINetDataCache
{
public:
nsMemCache();
virtual ~nsMemCache();
nsresult Init();
// nsISupports methods
NS_DECL_ISUPPORTS
// nsINetDataCache methods
NS_DECL_NSINETDATACACHE
// Factory
static NS_METHOD nsMemCacheConstructor(nsISupports *aOuter, REFNSIID aIID,
void **aResult);
protected:
PRUint32 mNumEntries;
PRUint32 mOccupancy; // Memory used, in bytes
PRBool mEnabled; // If false, bypass mem cache
nsINetDataCache* mNextCache;
// Mapping from either opaque key or record ID to nsMemCacheRecord
nsHashtable* mHashTable;
// Used to assign record ID's
static PRInt32 gRecordSerialNumber;
NS_METHOD Delete(nsMemCacheRecord* aRecord);
friend class nsMemCacheRecord;
friend class nsMemCacheChannel;
};
#endif // _nsMemCache_h_

View File

@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
// XPCOM Class ID for the network data in-memory cache
#ifndef nsMEMCACHECID_h__
#define nsMEMCACHECID_h__
// {e4710560-7de2-11d3-90cb-0040056a906e}
#define NS_MEM_CACHE_FACTORY_CID \
{ \
0xe4710560, \
0x7de2, \
0x11d3, \
{0x90, 0xcb, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
}
#endif // nsMEMCACHECID_h__

View File

@ -0,0 +1,464 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsMemCache.h"
#include "nsMemCacheChannel.h"
#include "nsIStreamListener.h"
#include "nsIChannel.h"
#include "nsIStorageStream.h"
#include "nsIOutputStream.h"
#include "nsIServiceManager.h"
#include "nsIEventQueueService.h"
#include "nsNetUtil.h"
#include "nsILoadGroup.h"
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kEventQueueService, NS_EVENTQUEUESERVICE_CID);
NS_IMPL_ISUPPORTS(nsMemCacheChannel, NS_GET_IID(nsIChannel))
void
nsMemCacheChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
{
mRecord->mCache->mOccupancy += aBytesUsed;
}
/**
* This class acts as an adaptor around a synchronous input stream to add async
* read capabilities. It adds methods for initiating, suspending, resuming and
* cancelling async reads.
*/
class AsyncReadStreamAdaptor : public nsIInputStream {
public:
AsyncReadStreamAdaptor(nsMemCacheChannel* aChannel, nsIInputStream *aSyncStream):
mSyncStream(aSyncStream), mDataAvailCursor(0),
mRemaining(0), mChannel(aChannel), mAvailable(0), mAborted(false), mSuspended(false)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
virtual ~AsyncReadStreamAdaptor() {
mChannel->mAsyncReadStream = 0;
NS_RELEASE(mChannel);
}
NS_DECL_ISUPPORTS
nsresult
IsPending(PRBool* aIsPending) {
*aIsPending = (mRemaining != 0) && !mAborted;
return NS_OK;
}
nsresult
Cancel(void) {
mAborted = true;
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_ABORTED, nsnull);
}
nsresult
Suspend(void) { mSuspended = true; return NS_OK; }
nsresult
Resume(void) {
if (!mSuspended)
return NS_ERROR_FAILURE;
mSuspended = false;
return NextListenerEvent();
}
NS_IMETHOD
Available(PRUint32 *aNumBytes) { return mAvailable; }
NS_IMETHOD
Read(char* aBuf, PRUint32 aCount, PRUint32 *aBytesRead) {
if (mAborted)
return NS_ERROR_ABORT;
*aBytesRead = 0;
aCount = PR_MIN(aCount, mAvailable);
nsresult rv = mSyncStream->Read(aBuf, aCount, aBytesRead);
mAvailable -= *aBytesRead;
if (NS_FAILED(rv) && (rv != NS_BASE_STREAM_WOULD_BLOCK)) {
Fail();
return rv;
}
if (!mSuspended && !mAvailable) {
rv = NextListenerEvent();
if (NS_FAILED(rv)) {
Fail();
return rv;
}
}
return NS_OK;
}
NS_IMETHOD
Close() {
nsresult rv = mSyncStream->Close();
mSyncStream = 0;
mContext = 0;
mStreamListener = 0;
return rv;
}
nsresult
AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports* aContext, nsIStreamListener* aListener) {
nsresult rv;
nsIEventQueue *eventQ;
mContext = aContext;
mStreamListener = aListener;
mRemaining = aReadCount;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueService, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->GetThreadEventQueue(PR_CurrentThread(), &eventQ);
if (NS_FAILED(rv)) return rv;
rv = NS_NewAsyncStreamListener(aListener, eventQ,
getter_AddRefs(mStreamListener));
NS_RELEASE(eventQ);
if (NS_FAILED(rv)) return rv;
rv = mStreamListener->OnStartRequest(mChannel, aContext);
if (NS_FAILED(rv)) return rv;
return NextListenerEvent();
}
protected:
nsresult
Fail(void) {
mAborted = true;
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_FAILED, nsnull);
}
nsresult
NextListenerEvent() {
PRUint32 available;
nsresult rv = mSyncStream->Available(&available);
if (NS_FAILED(rv)) return rv;
available -= mAvailable;
available = PR_MIN(available, mRemaining);
if (available) {
PRUint32 size = PR_MIN(available, MEM_CACHE_SEGMENT_SIZE);
rv = mStreamListener->OnDataAvailable(mChannel, mContext, this,
mDataAvailCursor, size);
mDataAvailCursor += size;
mRemaining -= size;
mAvailable += size;
return rv;
} else {
rv = mStreamListener->OnStopRequest(mChannel, mContext, NS_OK, nsnull);
AsyncReadStreamAdaptor* thisAlias = this;
NS_RELEASE(thisAlias);
return rv;
}
}
private:
nsCOMPtr<nsISupports> mContext; // Opaque context passed to AsyncRead()
nsCOMPtr<nsIStreamListener> mStreamListener; // Stream listener that has been proxied
nsCOMPtr<nsIInputStream> mSyncStream; // Underlying synchronous stream that is
// being converted to an async stream
PRUint32 mDataAvailCursor;
PRUint32 mRemaining; // Size of AsyncRead request less bytes for
// consumer OnDataAvailable's that were fired
PRUint32 mAvailable; // Number of bytes for which OnDataAvailable fired
nsMemCacheChannel* mChannel; // Associated memory cache channel, strong link
// but can not use nsCOMPtr
bool mAborted; // Abort() has been called
bool mSuspended; // Suspend() has been called
};
NS_IMPL_ISUPPORTS(AsyncReadStreamAdaptor, NS_GET_IID(nsIInputStream))
// The only purpose of this output stream wrapper is to adjust the cache's
// overall occupancy as new data flows into the cache entry.
class MemCacheWriteStreamWrapper : public nsIOutputStream {
public:
MemCacheWriteStreamWrapper(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream):
mBaseStream(aBaseStream), mChannel(aChannel)
{
NS_INIT_REFCNT();
NS_ADDREF(mChannel);
}
virtual ~MemCacheWriteStreamWrapper() { NS_RELEASE(mChannel); };
static nsresult
Create(nsMemCacheChannel* aChannel, nsIOutputStream *aBaseStream, nsIOutputStream* *aWrapper) {
MemCacheWriteStreamWrapper *wrapper =
new MemCacheWriteStreamWrapper(aChannel, aBaseStream);
if (!wrapper) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(wrapper);
*aWrapper = wrapper;
return NS_OK;
}
NS_DECL_ISUPPORTS
NS_IMETHOD
Write(const char *aBuffer, PRUint32 aCount, PRUint32 *aNumWritten) {
*aNumWritten = 0;
nsresult rv = mBaseStream->Write(aBuffer, aCount, aNumWritten);
mChannel->NotifyStorageInUse(*aNumWritten);
return rv;
}
NS_IMETHOD
Flush() { return mBaseStream->Flush(); }
NS_IMETHOD
Close() { return mBaseStream->Close(); }
private:
nsCOMPtr<nsIOutputStream> mBaseStream;
nsMemCacheChannel* mChannel;
};
NS_IMPL_ISUPPORTS(MemCacheWriteStreamWrapper, NS_GET_IID(nsIOutputStream))
nsMemCacheChannel::nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup)
: mRecord(aRecord)
{
NS_INIT_REFCNT();
mRecord->mNumChannels++;
}
nsMemCacheChannel::~nsMemCacheChannel()
{
mRecord->mNumChannels--;
}
NS_IMETHODIMP
nsMemCacheChannel::IsPending(PRBool* aIsPending)
{
*aIsPending = PR_FALSE;
if (!mAsyncReadStream)
return NS_OK;
return mAsyncReadStream->IsPending(aIsPending);
}
NS_IMETHODIMP
nsMemCacheChannel::Cancel(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Cancel();
}
NS_IMETHODIMP
nsMemCacheChannel::Suspend(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Suspend();
}
NS_IMETHODIMP
nsMemCacheChannel::Resume(void)
{
if (!mAsyncReadStream)
return NS_ERROR_FAILURE;
return mAsyncReadStream->Resume();
}
NS_IMETHODIMP
nsMemCacheChannel::GetOriginalURI(nsIURI * *aURI)
{
// Not required
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetURI(nsIURI * *aURI)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aResult)
{
nsresult rv;
NS_ENSURE_ARG(aResult);
if (mInputStream)
return NS_ERROR_NOT_AVAILABLE;
rv = mRecord->mStorageStream->NewInputStream(aStartPosition, getter_AddRefs(mInputStream));
*aResult = mInputStream;
NS_ADDREF(*aResult);
return rv;
}
NS_IMETHODIMP
nsMemCacheChannel::OpenOutputStream(PRUint32 startPosition, nsIOutputStream* *aResult)
{
nsresult rv;
NS_ENSURE_ARG(aResult);
nsCOMPtr<nsIOutputStream> outputStream;
PRUint32 oldLength;
mRecord->mStorageStream->GetLength(&oldLength);
rv = mRecord->mStorageStream->GetOutputStream(startPosition, getter_AddRefs(outputStream));
if (NS_FAILED(rv)) return rv;
if (startPosition < oldLength)
NotifyStorageInUse(startPosition - oldLength);
return MemCacheWriteStreamWrapper::Create(this, outputStream, aResult);
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncOpen(nsIStreamObserver *observer, nsISupports *ctxt)
{
// Not required
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener)
{
nsCOMPtr<nsIInputStream> inputStream;
nsresult rv = OpenInputStream(aStartPosition, aReadCount, getter_AddRefs(inputStream));
if (NS_FAILED(rv)) return rv;
AsyncReadStreamAdaptor *asyncReadStreamAdaptor;
asyncReadStreamAdaptor = new AsyncReadStreamAdaptor(this, inputStream);
if (!asyncReadStreamAdaptor)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(asyncReadStreamAdaptor);
mAsyncReadStream = asyncReadStreamAdaptor;
rv = asyncReadStreamAdaptor->AsyncRead(aStartPosition, aReadCount, aContext, aListener);
if (NS_FAILED(rv))
delete asyncReadStreamAdaptor;
return rv;
}
NS_IMETHODIMP
nsMemCacheChannel::AsyncWrite(nsIInputStream *fromStream, PRUint32 startPosition,
PRInt32 writeCount, nsISupports *ctxt,
nsIStreamObserver *observer)
{
// Not required to be implemented
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetContentType(char* *aContentType)
{
// Not required to be implemented, since it is implemented by cache manager
// NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
// FIXME - lying for the purpose of testing
*aContentType = strdup("text/html");
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::GetContentLength(PRInt32 *aContentLength)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::SetOwner(nsISupports* aOwner)
{
// Not required to be implemented, since it is implemented by cache manager
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsMemCacheChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#ifndef _nsMemCacheChannel_h_
#define _nsMemCacheChannel_h_
#include "nsMemCacheRecord.h"
#include "nsIChannel.h"
#include "nsIInputStream.h"
#include "nsCOMPtr.h"
class AsyncReadStreamAdaptor;
class nsMemCacheChannel : public nsIChannel
{
public:
// Constructors and Destructor
nsMemCacheChannel(nsMemCacheRecord *aRecord, nsILoadGroup *aLoadGroup);
virtual ~nsMemCacheChannel();
// Declare nsISupports methods
NS_DECL_ISUPPORTS
// Declare nsIRequest methods
NS_DECL_NSIREQUEST
// Declare nsIChannel methods
NS_DECL_NSICHANNEL
protected:
void NotifyStorageInUse(PRInt32 aBytesUsed);
nsCOMPtr<nsMemCacheRecord> mRecord;
nsCOMPtr<nsIInputStream> mInputStream;
nsCOMPtr<nsISupports> mOwner;
AsyncReadStreamAdaptor* mAsyncReadStream; // non-owning pointer
friend class MemCacheWriteStreamWrapper;
friend class AsyncReadStreamAdaptor;
};
#endif // _nsMemCacheChannel_h_

View File

@ -0,0 +1,164 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#include "nsMemCache.h"
#include "nsMemCacheRecord.h"
#include "nsMemCacheChannel.h"
#include "nsIAllocator.h"
#include "nsStorageStream.h"
static NS_DEFINE_IID(kINetDataCacheRecord, NS_INETDATACACHERECORD_IID);
nsMemCacheRecord::nsMemCacheRecord()
: mKey(0), mKeyLength(0), mMetaData(0), mMetaDataLength(0), mNumChannels(0)
{
NS_INIT_REFCNT();
}
nsMemCacheRecord::~nsMemCacheRecord()
{
if (mMetaData)
delete[] mMetaData;
if (mKey)
delete[] mKey;
}
NS_IMPL_ISUPPORTS(nsMemCacheRecord, NS_GET_IID(nsINetDataCacheRecord))
NS_IMETHODIMP
nsMemCacheRecord::GetKey(PRUint32 *aLength, char **aResult)
{
NS_ENSURE_ARG(aResult);
*aResult = (char *)nsAllocator::Alloc(mKeyLength);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(*aResult, mKey, mKeyLength);
*aLength = mKeyLength;
return NS_OK;
}
nsresult
nsMemCacheRecord::Init(const char *aKey, PRUint32 aKeyLength,
PRUint32 aRecordID, nsMemCache *aCache)
{
nsresult rv;
NS_ASSERTION(!mKey, "Memory cache record key set multiple times");
rv = NS_NewStorageStream(MEM_CACHE_SEGMENT_SIZE, MEM_CACHE_MAX_ENTRY_SIZE,
getter_AddRefs(mStorageStream));
if (NS_FAILED(rv)) return rv;
mKey = new char[aKeyLength];
if (!mKey)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(mKey, aKey, aKeyLength);
mKeyLength = aKeyLength;
mRecordID = aRecordID;
mCache = aCache;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetRecordID(PRInt32 *aRecordID)
{
NS_ENSURE_ARG(aRecordID);
*aRecordID = mRecordID;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetMetaData(PRUint32 *aLength, char **aResult)
{
NS_ENSURE_ARG(aResult);
*aResult = 0;
if (mMetaDataLength) {
*aResult = (char*)nsAllocator::Alloc(mMetaDataLength);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(*aResult, mMetaData, mMetaDataLength);
}
*aLength = mMetaDataLength;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::SetMetaData(PRUint32 aLength, const char *aData)
{
if (mMetaData)
delete[] mMetaData;
mMetaData = new char[aLength];
if (!mMetaData)
return NS_ERROR_OUT_OF_MEMORY;
memcpy(mMetaData, aData, aLength);
mMetaDataLength = aLength;
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::GetStoredContentLength(PRUint32 *aStoredContentLength)
{
NS_ENSURE_ARG(aStoredContentLength);
return mStorageStream->GetLength(aStoredContentLength);
}
NS_IMETHODIMP
nsMemCacheRecord::SetStoredContentLength(PRUint32 aStoredContentLength)
{
PRUint32 before, after;
mStorageStream->GetLength(&before);
nsresult rv = mStorageStream->SetLength(aStoredContentLength);
if (NS_FAILED(rv)) return rv;
mStorageStream->GetLength(&after);
mCache->mOccupancy -= (before - after);
return NS_OK;
}
NS_IMETHODIMP
nsMemCacheRecord::Delete(void)
{
if (mNumChannels)
return NS_ERROR_NOT_AVAILABLE;
return mCache->Delete(this);
}
NS_IMETHODIMP
nsMemCacheRecord::GetFilename(nsIFileSpec* *aFilename)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemCacheRecord::NewChannel(nsILoadGroup *aLoadGroup, nsIChannel* *aResult)
{
NS_ENSURE_ARG(aResult);
nsMemCacheChannel* channel = new nsMemCacheChannel(this, aLoadGroup);
if (!channel)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(channel);
*aResult = NS_STATIC_CAST(nsIChannel*, channel);
return NS_OK;
}

View File

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
*/
#ifndef _nsMemCacheRecord_h_
#define _nsMemCacheRecord_h_
#include "nsINetDataCacheRecord.h"
#include "nsCOMPtr.h"
class nsMemCache;
class nsIStorageStream;
class nsMemCacheRecord : public nsINetDataCacheRecord
{
public:
// Declare interface methods
NS_DECL_ISUPPORTS
NS_DECL_NSINETDATACACHERECORD
protected:
// Constructors and Destructor
nsMemCacheRecord();
virtual ~nsMemCacheRecord();
nsresult Init(const char *aKey, PRUint32 aKeyLength,
PRUint32 aRecordID, nsMemCache *aCache);
char* mKey; // opaque database key for this record
PRUint32 mKeyLength; // length, in bytes, of mKey
PRInt32 mRecordID; // An alternate key for this record
char* mMetaData; // opaque URI metadata
PRUint32 mMetaDataLength; // length, in bytes, of mMetaData
nsMemCache* mCache; // weak pointer to the cache database
// that this record inhabits
nsCOMPtr<nsIStorageStream> mStorageStream;
PRUint32 mNumChannels; // Count un-Release'ed nsIChannels
friend class nsMemCache;
friend class nsMemCacheChannel;
};
#endif // _nsMemCacheRecord_h_

View File

@ -26,22 +26,26 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = cachemgr
LIBRARY_NAME = cachemgr
IS_COMPONENT = 1
MODULE = nkcache
LIBRARY_NAME = nkcachemgr_s
REQUIRES = nspr
CPPSRCS = \
nsCacheManager.cpp \
nsMonitorable.cpp \
nsCacheBkgThd.cpp \
nsBkgThread.cpp \
nsCacheManager.cpp \
nsCachedNetData.cpp \
nsReplacementPolicy.cpp \
nsCacheEntryChannel.cpp \
$(NULL)
LOCAL_INCLUDES = -I$(srcdir)/../public -I$(srcdir)/../include
EXTRA_LIBS = $(NSPR_LIBS)
# we don't want the shared lib, but we want to force the creation of a
# static lib.
override NO_SHARED_LIB=1
override NO_STATIC_LIB=
include $(topsrcdir)/config/rules.mk

View File

@ -20,44 +20,26 @@
# Contributor(s):
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE=cachemgr
MODULE = nkcache
IS_COMPONENT=1
MAKE_OBJ_TYPE=DLL
DLLNAME=cachemgr
DLL=.\$(OBJDIR)\$(DLLNAME).dll
LIBRARY_NAME = nkcachemgr_s
LLIBS= $(LLIBS) \
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
CPP_OBJS = \
.\$(OBJDIR)\nsCacheManager.obj \
.\$(OBJDIR)\nsCachedNetData.obj \
.\$(OBJDIR)\nsReplacementPolicy.obj \
.\$(OBJDIR)\nsCacheEntryChannel.obj \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsCacheManager.obj \
.\$(OBJDIR)\nsMonitorable.obj \
.\$(OBJDIR)\nsCacheBkgThd.obj \
.\$(OBJDIR)\nsBkgThread.obj \
$(NULL)
LOCAL_INCLUDES= -I. \
-I..\public \
-I..\include \
INCLUDES = $(LOCAL_INCLUDES)
REQUIRES = nspr
INCS = $(INCS) \
-I..\include \
-I..\public \
-I$(DEPTH)\dist\include \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) $(DLL) $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -rf $(OBJDIR)
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@ -1,96 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsBkgThread.h"
#include "prlog.h"
static void PR_CALLBACK RunFunction(void* arg);
static void PR_CALLBACK RunFunction(void* arg)
{
nsBkgThread* pBT = (nsBkgThread*) arg;
if (pBT)
{
pBT->Process();
}
}
nsBkgThread::nsBkgThread(PRIntervalTime iSleepTime, PRBool bStart /* =PR_TRUE */)
{
m_SleepTime = iSleepTime;
m_bContinue = bStart;
m_pThread = PR_CreateThread(
PR_USER_THREAD,
RunFunction,
this,
PR_PRIORITY_NORMAL,
PR_LOCAL_THREAD,
PR_JOINABLE_THREAD,
0);
PR_ASSERT(NULL != m_pThread);
}
nsBkgThread::~nsBkgThread()
{
m_bContinue = PR_FALSE;
if (m_pThread != NULL)
{
Stop();
}
}
/*
nsrefcnt nsBkgThread::AddRef(void)
{
return ++m_RefCnt;
}
nsrefcnt nsBkgThread::Release(void)
{
if (--m_RefCnt == 0)
{
delete this;
return 0;
}
return m_RefCnt;
}
nsresult nsBkgThread::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
return NS_OK;
}
*/
void nsBkgThread::Process(void)
{
while (m_bContinue)
{
PR_Sleep(m_SleepTime);
Run();
}
}
void nsBkgThread::Stop(void)
{
m_bContinue = PR_FALSE;
PRStatus status = PR_Interrupt(m_pThread);
PR_ASSERT(PR_SUCCESS == status);
}

View File

@ -1,106 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "prlog.h"
#include "nsCacheBkgThd.h"
#include "nsIServiceManager.h"
#include "nsCacheManager.h"
//#include "nsCacheModule.h"
#include "nsCachePref.h"
static NS_DEFINE_IID(kICachePrefIID, NS_ICACHEPREF_IID) ;
static NS_DEFINE_IID(kCachePrefCID, NS_CACHEPREF_CID) ;
nsCacheBkgThd::nsCacheBkgThd(PRIntervalTime iSleepTime):
nsBkgThread(iSleepTime)
{
}
nsCacheBkgThd::~nsCacheBkgThd()
{
}
/*
nsrefcnt nsCacheBkgThd::AddRef(void)
{
return ++m_RefCnt;
}
nsrefcnt nsCacheBkgThd::Release(void)
{
if (--m_RefCnt == 0)
{
delete this;
return 0;
}
return m_RefCnt;
}
nsresult nsCacheBkgThd::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
return NS_OK;
}
*/
void nsCacheBkgThd::Run(void)
{
/* Step thru all the modules and call cleanup on each */
nsCacheManager* pCM = nsCacheManager::GetInstance();
nsICachePref* pref ;
nsServiceManager::GetService(kCachePrefCID,
kICachePrefIID,
(nsISupports **)&pref) ;
PRBool offline ;
PR_ASSERT(pCM);
pCM->IsOffline(&offline) ;
if (offline)
return; /* Dont update entries if offline */
PRInt16 i ;
pCM->Entries(&i);
while (i>0)
{
nsICacheModule* pModule ;
pCM->GetModule(--i, &pModule);
PR_ASSERT(pModule);
/* TODO change this based on if it supports garbage cleaning */
PRBool ro, revalidate ;
pModule->IsReadOnly(&ro) ;
if (!ro)
{
pModule->GarbageCollect();
pref->RevalidateInBkg(&revalidate) ;
if (revalidate)
{
pModule->Revalidate();
}
}
}
}

View File

@ -0,0 +1,260 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsCacheManager.h"
#include "nsCacheEntryChannel.h"
#include "nsIOutputStream.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
nsCacheEntryChannel::nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel,
nsILoadGroup* aLoadGroup):
nsChannelProxy(aChannel), mCacheEntry(aCacheEntry), mLoadGroup(aLoadGroup), mLoadAttributes(0)
{
NS_ASSERTION(aCacheEntry->mChannelCount < 0xFF, "Overflowed channel counter");
mCacheEntry->mChannelCount++;
NS_INIT_REFCNT();
}
nsCacheEntryChannel::~nsCacheEntryChannel()
{
mCacheEntry->mChannelCount--;
}
NS_IMPL_ISUPPORTS3(nsCacheEntryChannel, nsISupports, nsIChannel, nsIRequest)
// A proxy for nsIOutputStream
class CacheOutputStream : public nsIOutputStream {
public:
CacheOutputStream(nsIOutputStream *aOutputStream, nsCachedNetData *aCacheEntry):
mOutputStream(aOutputStream), mCacheEntry(aCacheEntry), mStartTime(PR_Now())
{ NS_INIT_REFCNT(); }
virtual ~CacheOutputStream() {}
NS_DECL_ISUPPORTS
NS_IMETHOD Close() {
mCacheEntry->NoteDownloadTime(mStartTime, PR_Now());
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
return mOutputStream->Close();
}
NS_IMETHOD Flush() { return mOutputStream->Flush(); }
NS_IMETHOD
Write(const char *aBuf, PRUint32 aCount, PRUint32 *aActualBytes) {
nsresult rv;
*aActualBytes = 0;
rv = mOutputStream->Write(aBuf, aCount, aActualBytes);
mCacheEntry->mLogicalLength += *aActualBytes;
if (NS_FAILED(rv)) return rv;
nsCacheManager::LimitCacheSize();
return rv;
}
protected:
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsCachedNetData> mCacheEntry;
// Time at which stream was opened
PRTime mStartTime;
};
NS_IMPL_ISUPPORTS(CacheOutputStream, NS_GET_IID(nsIOutputStream))
NS_IMETHODIMP
nsCacheEntryChannel::OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream)
{
nsresult rv;
nsCOMPtr<nsIOutputStream> baseOutputStream;
rv = mChannel->OpenOutputStream(aStartPosition, getter_AddRefs(baseOutputStream));
if (NS_FAILED(rv)) return rv;
mCacheEntry->NoteUpdate();
mCacheEntry->NoteAccess();
mCacheEntry->mLogicalLength = aStartPosition;
*aOutputStream = new CacheOutputStream(baseOutputStream, mCacheEntry);
if (!*aOutputStream)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aOutputStream);
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aInputStream)
{
mCacheEntry->NoteAccess();
return mChannel->OpenInputStream(aStartPosition, aReadCount, aInputStream);
}
class CacheManagerStreamListener: public nsIStreamListener {
public:
CacheManagerStreamListener(nsIStreamListener *aListener,
nsILoadGroup *aLoadGroup, nsIChannel *aChannel):
mListener(aListener), mLoadGroup(aLoadGroup), mChannel(aChannel)
{ NS_INIT_REFCNT(); }
virtual ~CacheManagerStreamListener() {}
private:
NS_DECL_ISUPPORTS
NS_IMETHOD
OnDataAvailable(nsIChannel *channel, nsISupports *aContext,
nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) {
return mListener->OnDataAvailable(mChannel, aContext, inStr, sourceOffset, count);
}
NS_IMETHOD
OnStartRequest(nsIChannel *channel, nsISupports *aContext) {
if (mLoadGroup)
mLoadGroup->AddChannel(mChannel, aContext);
return mListener->OnStartRequest(mChannel, aContext);
}
NS_IMETHOD
OnStopRequest(nsIChannel *channel, nsISupports *aContext,
nsresult status, const PRUnichar *errorMsg) {
nsresult rv;
rv = mListener->OnStopRequest(mChannel, aContext, status, errorMsg);
if (mLoadGroup)
mLoadGroup->RemoveChannel(mChannel, aContext, status, errorMsg);
return rv;
}
private:
nsCOMPtr<nsIStreamListener> mListener;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIChannel> mChannel;
};
NS_IMPL_ISUPPORTS2(CacheManagerStreamListener, nsIStreamListener, nsIStreamObserver)
NS_IMETHODIMP
nsCacheEntryChannel::AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener)
{
nsresult rv;
mCacheEntry->NoteAccess();
nsCOMPtr<nsIStreamListener> headListener;
if (mLoadGroup) {
mLoadGroup->GetDefaultLoadAttributes(&mLoadAttributes);
// Create a load group "proxy" listener...
nsCOMPtr<nsILoadGroupListenerFactory> factory;
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
if (NS_SUCCEEDED(rv) && factory) {
rv = factory->CreateLoadGroupListener(aListener,
getter_AddRefs(headListener));
if (NS_FAILED(rv)) return rv;
}
} else {
headListener = aListener;
}
CacheManagerStreamListener* cacheManagerStreamListener;
nsIChannel *channelForListener;
channelForListener = mProxyChannel ? mProxyChannel : this;
cacheManagerStreamListener =
new CacheManagerStreamListener(headListener, mLoadGroup, channelForListener);
if (!cacheManagerStreamListener) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(cacheManagerStreamListener);
rv = mChannel->AsyncRead(aStartPosition, aReadCount, aContext,
cacheManagerStreamListener);
NS_RELEASE(cacheManagerStreamListener);
return rv;
}
// No async writes allowed to the cache yet
NS_IMETHODIMP
nsCacheEntryChannel::AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
PRInt32 aWriteCount, nsISupports *aContext,
nsIStreamObserver *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP
nsCacheEntryChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
NS_IMETHODIMP
nsCacheEntryChannel::GetURI(nsIURI * *aURI)
{
char* spec;
nsresult rv;
rv = mCacheEntry->GetUriSpec(&spec);
if (NS_FAILED(rv)) return rv;
NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = serv->NewURI(spec, 0, aURI);
nsAllocator::Free(spec);
return rv;
}
NS_IMETHODIMP
nsCacheEntryChannel::GetOriginalURI(nsIURI * *aURI)
{
// FIXME - should return original URI passed into NewChannel() ?
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCacheEntryChannel_h_
#define _nsCacheEntryChannel_h_
#include "nsCOMPtr.h"
#include "nsIChannel.h"
#include "nsCachedNetData.h"
#include "nsILoadGroup.h"
class nsIStreamListener;
// A proxy for an nsIChannel, useful when only a few nsIChannel
// methods must be overridden
class nsChannelProxy : public nsIChannel {
public:
NS_FORWARD_NSICHANNEL(mChannel->)
NS_FORWARD_NSIREQUEST(mChannel->)
protected:
nsChannelProxy(nsIChannel* aChannel):mChannel(aChannel) {};
virtual ~nsChannelProxy() {};
nsCOMPtr<nsIChannel> mChannel;
};
// Override several nsIChannel methods so that they interact with the cache manager
class nsCacheEntryChannel : public nsChannelProxy {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD OpenOutputStream(PRUint32 aStartPosition, nsIOutputStream* *aOutputStream);
NS_IMETHOD OpenInputStream(PRUint32 aStartPosition, PRInt32 aReadCount,
nsIInputStream* *aInputStream);
NS_IMETHOD AsyncRead(PRUint32 aStartPosition, PRInt32 aReadCount,
nsISupports *aContext, nsIStreamListener *aListener);
NS_IMETHOD AsyncWrite(nsIInputStream *aFromStream, PRUint32 aStartPosition,
PRInt32 aWriteCount, nsISupports *aContext,
nsIStreamObserver *aObserver);
NS_IMETHOD GetLoadAttributes(nsLoadFlags *aLoadAttributes);
NS_IMETHOD SetLoadAttributes(nsLoadFlags aLoadAttributes);
NS_IMETHOD GetLoadGroup(nsILoadGroup* *aLoadGroup);
NS_IMETHOD GetURI(nsIURI * *aURI);
NS_IMETHOD GetOriginalURI(nsIURI * *aURI);
protected:
nsCacheEntryChannel(nsCachedNetData* aCacheEntry, nsIChannel* aChannel, nsILoadGroup* aLoadGroup);
virtual ~nsCacheEntryChannel();
friend class nsCachedNetData;
private:
nsCOMPtr<nsCachedNetData> mCacheEntry;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIChannel> mProxyChannel;
nsLoadFlags mLoadAttributes;
};
#endif // _nsCacheEntryChannel_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,99 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCacheManager_h_
#define _nsCacheManager_h_
// 2030f0b0-9567-11d3-90d3-0040056a906e
#define NS_CACHE_MANAGER_CID \
{ \
0x2030f0b0, \
0x9567, \
0x11d3, \
{0x90, 0xd3, 0x00, 0x40, 0x05, 0x6a, 0x90, 0x6e} \
}
#include "nsINetDataCacheManager.h"
#include "nsCOMPtr.h"
class nsHashtable;
class nsReplacementPolicy;
class nsCachedNetData;
class nsCacheManager : public nsINetDataCacheManager {
public:
nsCacheManager();
virtual ~nsCacheManager();
NS_METHOD Init();
// nsISupports methods
NS_DECL_ISUPPORTS
// nsINetDataCacheManager methods
NS_DECL_NSINETDATACACHEMANAGER
private:
// Mapping from cache key to nsCachedNetData, but only for those cache
// entries with external references, i.e. those referred to outside the
// cache manager
nsHashtable* mActiveCacheRecords;
// Memory cache
nsCOMPtr<nsINetDataCache> mMemCache;
// Flat-file database cache; All content aggregated into single disk file
nsCOMPtr<nsINetDataCache> mFlatCache;
// stream-as-file cache
nsCOMPtr<nsINetDataCache> mFileCache;
// Unified replacement policy for flat-cache and file-cache
nsReplacementPolicy* mDiskSpaceManager;
// Replacement policy for memory cache
nsReplacementPolicy* mMemSpaceManager;
// List of caches in search order
nsINetDataCache* mCacheSearchChain;
// Combined file/flat cache capacity, in KB
PRUint32 mDiskCacheCapacity;
// Memory cache capacity, in KB
PRUint32 mMemCacheCapacity;
protected:
static nsresult NoteDormant(nsCachedNetData* aEntry);
static nsresult LimitCacheSize();
static nsresult LimitMemCacheSize();
static nsresult LimitDiskCacheSize();
friend class nsCachedNetData;
friend class CacheOutputStream;
};
#endif // _nsCacheManager_h_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,242 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#ifndef _nsCachedNetData_h_
#define _nsCachedNetData_h_
#include "nsICachedNetData.h"
#include "nsCOMPtr.h"
#include "nsINetDataCacheRecord.h"
class nsINetDataCache;
class nsIStreamAsFileObserver;
class nsIStreamAsFile;
class nsIArena;
class StreamAsFileObserverClosure;
class CacheMetaData;
// Number of recent access times recorded
#define MAX_K 3
/**
* FIXME - add comment. There are a lot of these data structures resident in
* memory, so be careful about adding members unnecessarily.
*/
class nsCachedNetData : public nsICachedNetData {
public:
NS_DECL_ISUPPORTS
// nsICachedNetData methods
NS_DECL_NSICACHEDNETDATA
NS_METHOD Init(nsINetDataCacheRecord *aRecord, nsINetDataCache *aCache);
protected:
// Bits for mFlags, below
typedef enum {
DIRTY = 1 << 0, // Cache entry data needs to be flushed to database
// ==== Flags that can be set by the protocol handler ====
ALLOW_PARTIAL = 1 << 1, // Protocol handler supports partial fetching
UPDATE_IN_PROGRESS = 1 << 2, // Protocol handler now modifying cache data
// ==== Cache-entry state flags. At most one of these flags can be set ====
TRUNCATED_CONTENT = 1 << 4, // Entry contains valid content, but it has
// been truncated by cache manager
// A previously-used cache entry, which has been purged of all cached
// content and protocol-private data. This cache entry can be refilled
// with new content or it may be retained in this vestigial state
// because the usage statistics it contains will be used by the
// replacement policy if the same URI is ever cached again.
VESTIGIAL = 1 << 5,
// ==== Memory usage status bits. At most one of these flags can be set ====
RECYCLED = 1 << 8, // Previously associated database record has
// been deleted; This cache entry is available
// for recycling.
DORMANT = 1 << 9, // No references to this cache entry, except by
// the cache manager itself
// ==== Setter bits ====
LAST_MODIFIED_KNOWN = 1 <<12, // Protocol handler called SetLastModifiedTime()
EXPIRATION_KNOWN = 1 <<13, // Protocol handler called SetExpirationTime()
STALE_TIME_KNOWN = 1 <<14, // Protocol handler called SetStaleTime()
// ==== Useful flag combinations ====
// Cache entry not eligible for eviction
UNEVICTABLE = VESTIGIAL | RECYCLED | UPDATE_IN_PROGRESS,
// State flags that are in-memory only, i.e. not persistent
TRANSIENT_FLAGS = DIRTY | RECYCLED | DORMANT
} Flag;
PRBool GetFlag(Flag aFlag) { return (mFlags & aFlag) != 0; }
nsresult GetFlag(PRBool *aResult, Flag aFlag) { *aResult = GetFlag(aFlag); return NS_OK; }
// Set a boolean flag for the cache entry
nsresult SetFlag(PRBool aValue, Flag aFlag);
nsresult SetFlag(Flag aFlag) { return SetFlag(PR_TRUE, aFlag); }
nsresult ClearFlag(Flag aFlag) { return SetFlag(PR_FALSE, aFlag); }
void ComputeProfit(PRUint32 aCurrentTime);
static int Compare(const void *a, const void *b, void *unused);
void NoteAccess();
void NoteUpdate();
// Get underlying raw cache database record.
nsresult GetRecord(nsINetDataCacheRecord* *aRecord);
nsresult GetRecordID(PRInt32 *aRecordID);
nsresult Evict(PRUint32 aTruncatedContentLength);
nsresult GetFileSpec(nsIFileSpec* *aFileSpec);
void NoteDownloadTime(PRTime start, PRTime end);
// placement new for arena-allocation
void *operator new (size_t aSize, nsIArena *aArena);
friend class nsReplacementPolicy;
friend class nsCacheManager;
friend class StreamAsFile;
friend class nsCacheEntryChannel;
friend class CacheOutputStream;
friend class InterceptStreamListener;
private:
nsCachedNetData() {};
virtual ~nsCachedNetData() {};
// Initialize internal fields of this nsCachedNetData instance from the
// underlying raw cache database record.
nsresult Deserialize(bool aDeserializeFlags);
// Notify stream-as-file observers about change in cache entry status
nsresult Notify(PRUint32 aMessage, nsresult aError);
// Add/Remove stream-as-file observers
nsresult AddObserver(nsIStreamAsFile *aStreamAsFile, nsIStreamAsFileObserver* aObserver);
nsresult RemoveObserver(nsIStreamAsFileObserver* aObserver);
// Mark cache entry to indicate a write out to the cache database is required
void SetDirty() { mFlags |= DIRTY; }
nsresult Resurrect(nsINetDataCacheRecord *aRecord);
nsresult CommitFlags();
CacheMetaData* FindTaggedMetaData(const char* aTag, PRBool aCreate);
private:
// List of nsIStreamAsFileObserver's that will receive notification events
// when the cache manager or a client desires to delete/truncate a cache
// entry file.
StreamAsFileObserverClosure* mObservers;
// Protocol-specific meta-data, opaque to the cache manager
CacheMetaData *mMetaData;
// Next in chain for a single bucket in the replacement policy hash table
// that maps from record ID to nsCachedNetData
nsCachedNetData* mNext;
// See flag bits, above
// NOTE: 16 bit member is combined with members below for
// struct packing efficiency. Do not change order of members!
PRUint16 mFlags;
protected:
// Number of nsCacheEntryChannels referring to this record
PRUint8 mChannelCount;
// Below members are statistics kept per cache-entry, used to decide how
// profitable it will be to evict a record from the cache relative to other
// existing records. Note: times are measured in *seconds* since the
// 1/1/70 epoch, same as a unix time_t.
// Number of accesses for this cache record
// NOTE: 8 bit member is combined with members above for
// struct packing efficiency. Do not change order of members!
PRUint8 mNumAccesses;
// A reference to the underlying, raw cache database record, either as a
// pointer to an in-memory object or as a database record identifier
union {
nsINetDataCacheRecord* mRecord;
// Database record ID of associated cache record. See
// nsINetDataCache::GetRecordByID().
PRInt32 mRecordID;
};
// Weak link to parent cache
nsINetDataCache* mCache;
// Length of stored content, which may be less than storage consumed if
// compression is used
PRUint32 mLogicalLength;
// Most recent cache entry access times, used to compute access frequency
PRUint32 mAccessTime[MAX_K];
// We use modification time of the original document for replacement policy
// computations, i.e. to compute a document's age, but if we don't know it,
// we use the time that the document was last written to the cache.
union {
// Document modification time, if known.
PRUint32 mLastModifiedTime;
// Time of last cache update for this doc
PRUint32 mLastUpdateTime;
};
union {
// Time until which document is fresh, i.e. does not have to be validated
// with server and, therefore, data in cache is guaranteed usable
PRUint32 mExpirationTime;
// Heuristic time at which cached document is likely to be out-of-date
// with respect to canonical copy on server. Used for cache replacement
// policy, not for validation.
PRUint32 mStaleTime;
};
// Download time per byte, measure roughly in units of KB/s
float mDownloadRate;
// Heuristic estimate of cache entry future benefits, based on above values
float mProfit;
};
#endif // _nsCachedNetData_h_

View File

@ -1,41 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* This is the implementation of the nsMonitorable::MonitorLocker class.
* Although the inlines work ok elsewhere, IRIX chokes on these. Hence
* moving these to a cpp.
* -Gagan Saksena 09/15/98
*/
#include "nsMonitorable.h"
nsMonitorable::MonitorLocker::MonitorLocker(nsMonitorable* i_pThis):
m_pMonitorable(i_pThis)
{
if (m_pMonitorable) m_pMonitorable->Lock();
}
nsMonitorable::MonitorLocker::~MonitorLocker()
{
if (m_pMonitorable) m_pMonitorable->Unlock();
}

View File

@ -0,0 +1,658 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
#include "nsReplacementPolicy.h"
#include "nsCachedNetData.h"
#include "nsQuickSort.h"
#include "nsIAllocator.h"
#include "nsIEnumerator.h"
#include "prtime.h"
#include "prbit.h"
#include "nsCOMPtr.h"
#include <math.h>
// Constant used to estimate frequency of access to a document based on size
#define CACHE_CONST_B 1.35
// A cache whose space is managed by this replacement policy
class nsReplacementPolicy::CacheInfo {
public:
CacheInfo(nsINetDataCache* aCache):mCache(aCache),mNext(0) {}
nsINetDataCache* mCache;
CacheInfo* mNext;
};
nsReplacementPolicy::nsReplacementPolicy()
: mRankedEntries(0), mCaches(0), mRecordsRemovedSinceLastRanking(0),
mNumEntries(0), mCapacityRankedEntriesArray(0), mLastRankTime(0) {}
nsReplacementPolicy::~nsReplacementPolicy()
{
if (mRankedEntries)
nsAllocator::Free(mRankedEntries);
if (mMapRecordIdToEntry)
nsAllocator::Free(mMapRecordIdToEntry);
}
nsresult
nsReplacementPolicy::Init(PRUint32 aMaxCacheEntries)
{
nsresult rv;
rv = NS_NewHeapArena(getter_AddRefs(mArena), sizeof(nsCachedNetData) * 32);
if (NS_FAILED(rv)) return rv;
mMaxEntries = aMaxCacheEntries;
mHashArrayLength = PR_CeilingLog2(aMaxCacheEntries) >> 3;
size_t numBytes = mHashArrayLength * sizeof(*mMapRecordIdToEntry);
mMapRecordIdToEntry = (nsCachedNetData**)nsAllocator::Alloc(numBytes);
if (!mMapRecordIdToEntry)
return NS_ERROR_OUT_OF_MEMORY;
nsCRT::zero(mMapRecordIdToEntry, numBytes);
return NS_OK;
}
nsresult
nsReplacementPolicy::AddCache(nsINetDataCache *aCache)
{
CacheInfo *cacheInfo = new CacheInfo(aCache);
if (!cacheInfo)
return NS_ERROR_OUT_OF_MEMORY;
cacheInfo->mNext = mCaches;
mCaches = cacheInfo;
return NS_OK;
}
PRUint32
nsReplacementPolicy::HashRecordID(PRInt32 aRecordID)
{
return ((aRecordID >> 16) ^ aRecordID) & (mHashArrayLength - 1);
}
nsCachedNetData*
nsReplacementPolicy::FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache)
{
nsresult rv;
nsCachedNetData* cacheEntry;
PRUint32 bucket = HashRecordID(aRecordID);
cacheEntry = mMapRecordIdToEntry[bucket];
for (;cacheEntry; cacheEntry = cacheEntry->mNext) {
PRInt32 recordID;
rv = cacheEntry->GetRecordID(&recordID);
if (NS_FAILED(rv))
continue;
if ((recordID == aRecordID) && (cacheEntry->mCache == aCache))
return cacheEntry;
}
return 0;
}
// Add a cache entry to the hash table that maps record ID to entries
void
nsReplacementPolicy::AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID)
{
nsCachedNetData** cacheEntryp;
PRUint32 bucket = HashRecordID(aRecordID);
cacheEntryp = &mMapRecordIdToEntry[bucket];
while (*cacheEntryp)
cacheEntryp = &(*cacheEntryp)->mNext;
*cacheEntryp = aCacheEntry;
aCacheEntry->mNext = 0;
}
// Delete a cache entry from the hash table that maps record ID to entries
nsresult
nsReplacementPolicy::DeleteCacheEntry(nsCachedNetData* aCacheEntry)
{
nsresult rv;
PRInt32 recordID;
rv = aCacheEntry->GetRecordID(&recordID);
if (NS_FAILED(rv)) return rv;
PRUint32 bucket = HashRecordID(recordID);
nsCachedNetData** cacheEntryp;
cacheEntryp = &mMapRecordIdToEntry[bucket];
while (*cacheEntryp) {
if (*cacheEntryp == aCacheEntry) {
*cacheEntryp = aCacheEntry->mNext;
return NS_OK;
}
cacheEntryp = &(*cacheEntryp)->mNext;
}
NS_ASSERTION(0, "hash table inconsistency");
return NS_ERROR_FAILURE;
}
nsresult
nsReplacementPolicy::AddAllRecordsInCache(nsINetDataCache *aCache)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> iSupports;
nsCOMPtr<nsINetDataCacheRecord> record;
rv = aCache->NewCacheEntryIterator(getter_AddRefs(iterator));
if (!NS_SUCCEEDED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
rv = iterator->GetNext(getter_AddRefs(iSupports));
if (!NS_SUCCEEDED(rv)) return rv;
record = do_QueryInterface(iSupports);
rv = AssociateCacheEntryWithRecord(record, aCache, 0);
if (!NS_SUCCEEDED(rv)) return rv;
}
return NS_OK;
}
// Get current time and convert to seconds since the epoch
static PRUint32
now32()
{
double nowFP;
PRInt64 now64 = PR_Now();
LL_L2D(nowFP, now64);
PRUint32 now = (PRUint32)(nowFP * 1e-6);
return now;
}
void
nsCachedNetData::NoteDownloadTime(PRTime start, PRTime end)
{
double startFP, endFP, rate, duration;
LL_L2D(startFP, start);
LL_L2D(endFP, end);
duration = endFP - startFP;
// Sanity-check
if (!duration)
return;
// Compute download rate in kB/s
rate = mLogicalLength / (duration * (1e-6 /1024.0));
// Exponentially smooth download rate
const double alpha = 0.5;
mDownloadRate = (float)(mDownloadRate * alpha + rate * (1.0 - alpha));
}
// 1 hour
#define MIN_HALFLIFE (60 * 60)
// 1 week
#define TYPICAL_HALFLIFE (7 * 24 * 60 * 60)
/**
* Estimate the profit that would be lost if the given cache entry was evicted
* from the cache. Profit is defined as the future expected download delay per
* byte of cached content. The profit computation is made based on projected
* frequency of access, prior download performance and a heuristic staleness
* criteria. The technique used is a variation of that described in the
* following paper:
*
* "A Case for Delay-Conscious Caching of Web Documents"
* http://www.bell-labs.com/user/rvingral/www97.html
*
* Briefly, expected profit is:
*
* (projected frequency of access) * (download time per byte) * (probability freshness)
*/
void
nsCachedNetData::ComputeProfit(PRUint32 aNow)
{
PRUint32 K, now;
if (aNow)
now = aNow;
else
now = now32();
K = PR_MIN(MAX_K, mNumAccesses);
if (!K) {
mProfit = 0;
return;
}
// Compute time, in seconds, since k'th most recent access
double timeSinceKthAccess = now - mAccessTime[K - 1];
if (timeSinceKthAccess <= 0.0) // Sanity check
timeSinceKthAccess = 1.0;
// Estimate frequency of future document access based on past
// access frequency
double frequencyAccess = K / timeSinceKthAccess;
// If we don't have much historical data on access frequency
// use a heuristic based on document size as an estimate
if (mLogicalLength) {
if (K == 1) {
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B);
} else if (K == 2) {
frequencyAccess /= pow(mLogicalLength, CACHE_CONST_B / 2);
}
}
// Estimate likelihood that data in cache is fresh, i.e.
// that it corresponds to the document on the server
double probabilityFreshness;
PRInt32 halfLife, age, docTime;
bool potentiallyStale;
docTime = GetFlag(LAST_MODIFIED_KNOWN) ? mLastModifiedTime : mLastUpdateTime;
age = now - docTime;
probabilityFreshness = 1.0; // Optimistic
if (GetFlag(EXPIRATION_KNOWN)) {
potentiallyStale = now > mExpirationTime;
halfLife = mExpirationTime - mLastModifiedTime;
} else if (GetFlag(STALE_TIME_KNOWN)) {
potentiallyStale = true;
halfLife = mStaleTime - docTime;
} else {
potentiallyStale = true;
halfLife = TYPICAL_HALFLIFE;
}
if (potentiallyStale) {
if (halfLife < MIN_HALFLIFE)
halfLife = MIN_HALFLIFE;
probabilityFreshness = pow(0.5, (double)age / (double)halfLife);
}
mProfit = (float)(frequencyAccess * probabilityFreshness * mDownloadRate);
}
// Number of entries to grow mRankedEntries array when it's full
#define STATS_GROWTH_INCREMENT 256
// Sorting predicate for NS_Quicksort
int
nsCachedNetData::Compare(const void *a, const void *b, void *unused)
{
nsCachedNetData* entryA = (nsCachedNetData*)a;
nsCachedNetData* entryB = (nsCachedNetData*)b;
// Percolate deleted or empty entries to the end of the mRankedEntries
// array, so that they can be recycled.
if (!entryA || entryA->GetFlag(RECYCLED)) {
if (!entryB || entryB->GetFlag(RECYCLED))
return 0;
else
return +1;
}
if (!entryB || entryB->GetFlag(RECYCLED))
return -1;
// Evicted entries (those with no content data) and active entries (those
// currently being updated) are collected towards the end of the sorted
// array just prior to the deleted cache entries, since evicted entries
// can't be re-evicted.
if (entryA->GetFlag(UPDATE_IN_PROGRESS)) {
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
return 0;
else
return +1;
}
if (entryB->GetFlag(UPDATE_IN_PROGRESS))
return -1;
PRUint16 Ka = PR_MIN(MAX_K, entryA->mNumAccesses);
PRUint16 Kb = PR_MIN(MAX_K, entryB->mNumAccesses);
// Order cache entries by the number of times they've been accessed
if (Ka < Kb)
return -1;
if (Ka > Kb)
return +1;
/*
* Among records that have been accessed an equal number of times, order
* them by profit.
*/
if (entryA->mProfit > entryB->mProfit)
return +1;
if (entryA->mProfit < entryB->mProfit)
return -1;
return 0;
}
/**
* Rank cache entries in terms of their elegibility for eviction.
*/
nsresult
nsReplacementPolicy::RankRecords()
{
PRUint32 i, now;
// Add all cache records if this is the first ranking
if (!mLastRankTime) {
nsresult rv;
CacheInfo *cacheInfo;
cacheInfo = mCaches;
while (cacheInfo) {
rv = AddAllRecordsInCache(cacheInfo->mCache);
if (NS_FAILED(rv)) return rv;
cacheInfo = cacheInfo->mNext;
}
}
// Get current time and convert to seconds since the epoch
now = now32();
// Recompute profit for every known cache record, except deleted ones
for (i = 0; i < mNumEntries; i++) {
nsCachedNetData* entry = mRankedEntries[i];
if (entry && !entry->GetFlag(nsCachedNetData::RECYCLED))
entry->ComputeProfit(now);
}
NS_QuickSort(mRankedEntries, mNumEntries, sizeof *mRankedEntries,
nsCachedNetData::Compare, 0);
mNumEntries -= mRecordsRemovedSinceLastRanking;
mRecordsRemovedSinceLastRanking = 0;
mLastRankTime = now;
return NS_OK;
}
// A heuristic policy to avoid the cost of re-ranking cache records by
// profitability every single time space must be made available in the cache.
void
nsReplacementPolicy::MaybeRerankRecords()
{
// Rank at most once per minute
PRUint32 now = now32();
if ((now - mLastRankTime) >= 60)
RankRecords();
}
void
nsReplacementPolicy::CompactRankedEntriesArray()
{
if (mRecordsRemovedSinceLastRanking || !mLastRankTime)
RankRecords();
}
nsresult
nsReplacementPolicy::CheckForTooManyCacheEntries()
{
if (mCapacityRankedEntriesArray == mMaxEntries) {
return DeleteOneEntry(0);
} else {
nsresult rv;
CacheInfo *cacheInfo;
cacheInfo = mCaches;
while (cacheInfo) {
PRUint32 numEntries, maxEntries;
rv = cacheInfo->mCache->GetNumEntries(&numEntries);
if (NS_FAILED(rv)) return rv;
rv = cacheInfo->mCache->GetMaxEntries(&maxEntries);
if (NS_FAILED(rv)) return rv;
if (numEntries == maxEntries)
return DeleteOneEntry(cacheInfo->mCache);
cacheInfo = cacheInfo->mNext;
}
}
return NS_OK;
}
/**
* Create a new association between a low-level cache database record and a
* cache entry. Add the entry to the set of entries eligible for eviction from
* the cache. This would typically be done when the cache entry is created.
*/
nsresult
nsReplacementPolicy::AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
nsINetDataCache* aCache,
nsCachedNetData** aResult)
{
nsCachedNetData* cacheEntry;
nsresult rv;
// First, see if the record is already known to the replacement policy
PRInt32 recordID;
rv = aRecord->GetRecordID(&recordID);
if (NS_FAILED(rv)) return rv;
cacheEntry = FindCacheEntryByRecordID(recordID, aCache);
if (cacheEntry) {
if (aResult) {
if (cacheEntry->GetFlag(nsCachedNetData::DORMANT))
cacheEntry->Resurrect(aRecord);
NS_ADDREF(cacheEntry);
*aResult = cacheEntry;
}
return NS_OK;
}
// Compact the array of cache entry statistics, so that free entries appear
// at the end, for possible reuse.
if (mNumEntries && (mNumEntries == mCapacityRankedEntriesArray))
CompactRankedEntriesArray();
// If compaction doesn't yield available entries in the
// mRankedEntries array, then extend the array.
if (mNumEntries == mCapacityRankedEntriesArray) {
PRUint32 newCapacity;
rv = CheckForTooManyCacheEntries();
if (NS_FAILED(rv)) return rv;
newCapacity = mCapacityRankedEntriesArray + STATS_GROWTH_INCREMENT;
if (newCapacity > mMaxEntries)
newCapacity = mMaxEntries;
nsCachedNetData** newRankedEntriesArray;
PRUint32 numBytes = sizeof(nsCachedNetData*) * newCapacity;
newRankedEntriesArray =
(nsCachedNetData**)nsAllocator::Realloc(mRankedEntries, numBytes);
if (!newRankedEntriesArray)
return NS_ERROR_OUT_OF_MEMORY;
mRankedEntries = newRankedEntriesArray;
mCapacityRankedEntriesArray = newCapacity;
PRUint32 i;
for (i = mNumEntries; i < newCapacity; i++)
mRankedEntries[i] = 0;
}
// Recycle the record after the last in-use record in the array
nsCachedNetData *entry = mRankedEntries[mNumEntries];
NS_ASSERTION(!entry || !entry->GetFlag(nsCachedNetData::RECYCLED),
"Only deleted cache entries should appear at end of array");
if (!entry) {
entry = new(mArena) nsCachedNetData;
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
mRankedEntries[mNumEntries] = entry;
} else {
// Clear out recycled data structure
nsCRT::zero(entry, sizeof(*entry));
}
entry->Init(aRecord, aCache);
AddCacheEntry(entry, recordID);
// Add one reference to the cache entry from the cache manager
NS_ADDREF(entry);
if (aResult) {
// And one reference from our caller
NS_ADDREF(entry);
*aResult = entry;
}
mNumEntries++;
return NS_OK;
}
nsresult
nsReplacementPolicy::GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
nsINetDataCache* aCache,
nsCachedNetData** aResult)
{
nsresult rv;
nsCOMPtr<nsINetDataCacheRecord> record;
rv = aCache->GetCachedNetData(cacheKey, cacheKeyLength,
getter_AddRefs(record));
if (NS_FAILED(rv)) return rv;
return AssociateCacheEntryWithRecord(record, aCache, aResult);
}
/**
* Delete the least desirable record from the cache database. This is used
* when the addition of another record would exceed either the cache manager or
* the cache's maximum permitted number of records.
*/
nsresult
nsReplacementPolicy::DeleteOneEntry(nsINetDataCache *aCache)
{
PRUint32 i;
nsresult rv;
nsCachedNetData *entry;
i = 0;
while (1) {
MaybeRerankRecords();
for (; i < mNumEntries; i++) {
entry = mRankedEntries[i];
if (!entry || entry->GetFlag(nsCachedNetData::RECYCLED))
continue;
if (!aCache || (entry->mCache == aCache))
break;
}
// Report error if no record found to delete
if (i == mNumEntries)
return NS_ERROR_FAILURE;
rv = entry->Delete();
if (NS_SUCCEEDED(rv)) {
rv = DeleteCacheEntry(entry);
return rv;
}
}
}
nsresult
nsReplacementPolicy::GetStorageInUse(PRUint32* aStorageInUse)
{
nsresult rv;
CacheInfo *cacheInfo;
*aStorageInUse = 0;
cacheInfo = mCaches;
while (cacheInfo) {
PRUint32 cacheStorage;
rv = cacheInfo->mCache->GetStorageInUse(&cacheStorage);
if (NS_FAILED(rv)) return rv;
*aStorageInUse += cacheStorage;
cacheInfo = cacheInfo->mNext;
}
return NS_OK;
}
/**
* Delete the least desirable records from the cache until the occupancy of the
* cache has been reduced by the given number of KB. This is used when the
* addition of more cache data would exceed the cache's capacity.
*/
nsresult
nsReplacementPolicy::Evict(PRUint32 aTargetOccupancy)
{
PRUint32 i;
nsCachedNetData *entry;
nsresult rv;
PRUint32 occupancy;
PRInt32 truncatedLength;
nsCOMPtr<nsINetDataCacheRecord> record;
MaybeRerankRecords();
for (i = 0; i < mNumEntries; i++) {
rv = GetStorageInUse(&occupancy);
if (!NS_SUCCEEDED(rv)) return rv;
if (occupancy <= aTargetOccupancy)
return NS_OK;
entry = mRankedEntries[i];
// Skip deleted/empty cache entries and ones that have already been evicted
if (!entry || entry->GetFlag(nsCachedNetData::UNEVICTABLE))
continue;
if (entry->GetFlag(nsCachedNetData::ALLOW_PARTIAL)) {
rv = entry->GetRecord(getter_AddRefs(record));
if (NS_FAILED(rv))
continue;
PRUint32 contentLength;
rv = record->GetStoredContentLength(&contentLength);
if (NS_FAILED(rv))
continue;
// Additional cache storage required, in KB
PRUint32 storageToReclaim = (occupancy - aTargetOccupancy) << 10;
truncatedLength = (PRInt32)(contentLength - storageToReclaim);
if (truncatedLength < 0)
truncatedLength = 0;
} else {
truncatedLength = 0;
}
rv = entry->Evict(truncatedLength);
}
return NS_ERROR_FAILURE;
}

View File

@ -0,0 +1,136 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott Furman, fur@netscape.com
*/
/**
* This class manages one or more caches that share a storage resource, e.g. a
* file cache and a flat-database cache might each occupy space on the disk and
* they would share a single instance of nsReplacementPolicy. The replacement
* policy heuristically chooses which cache entries to evict when storage is
* required to accommodate incoming cache data.
*/
#ifndef _nsReplacementPolicy_h_
#define _nsReplacementPolicy_h_
#include "nscore.h"
#include "nsISupportsUtils.h"
#include "nsINetDataCache.h"
#include "nsICachedNetData.h"
#include "nsIArena.h"
#include "nsCOMPtr.h"
#include "nsHashtable.h"
class nsCachedNetData;
struct PL_HashTable;
/**
* This private class is responsible for implementing the network data cache's
* replacement policy, i.e. it decides which cache data should be evicted to
* make room for new incoming data.
*/
class nsReplacementPolicy {
public:
nsReplacementPolicy();
~nsReplacementPolicy();
protected:
nsresult Init(PRUint32 aMaxCacheEntries);
nsresult AddCache(nsINetDataCache *aCache);
nsresult GetCachedNetData(const char* cacheKey, PRUint32 cacheKeyLength,
nsINetDataCache* aCache,
nsCachedNetData** aResult);
nsresult GetStorageInUse(PRUint32* aNumKBytes);
friend class nsCacheManager;
private:
nsresult RankRecords();
void MaybeRerankRecords();
void CompactRankedEntriesArray();
nsresult DeleteOneEntry(nsINetDataCache* aCache);
nsresult Evict(PRUint32 aTargetOccupancy);
nsCachedNetData* FindCacheEntryByRecordID(PRInt32 aRecordID, nsINetDataCache *aCache);
void AddCacheEntry(nsCachedNetData* aCacheEntry, PRInt32 aRecordID);
nsresult DeleteCacheEntry(nsCachedNetData* aCacheEntry);
PRUint32 HashRecordID(PRInt32 aRecordID);
nsresult AssociateCacheEntryWithRecord(nsINetDataCacheRecord *aRecord,
nsINetDataCache* aCache,
nsCachedNetData** aResult);
nsresult AddAllRecordsInCache(nsINetDataCache *aCache);
nsresult CheckForTooManyCacheEntries();
class CacheInfo;
private:
// Growable array of pointers to individual cache entries; It is sorted by
// profitability, such that low-numbered array indices refer to cache
// entries that are the least profitable to retain. New cache entries are
// added to the end of the array. Deleted cache entries are specially
// marked and percolate to the end of the array for recycling whenever
// mRankedEntries is sorted. Evicted cache entries (those with no
// associated content data) are retained for the purpose of improving the
// replacement policy efficacy, and are percolated towards the end of the
// array, just prior to the deleted cache entries.
//
// The array is not in sorted order 100% of the time; For efficiency
// reasons, sorting is only done when heuristically deemed necessary.
nsCachedNetData** mRankedEntries;
// Hash table buckets to map Record ID to cache entry. We use this instead
// of a PL_HashTable to reduce storage requirements
nsCachedNetData** mMapRecordIdToEntry;
// Length of mMapRecordIdToEntry array
PRUint32 mHashArrayLength;
// Linked list of caches that share this replacement policy
CacheInfo* mCaches;
// Allocation area for cache entry (nsCachedNetData) instances
nsCOMPtr<nsIArena> mArena;
// Bookkeeping
PRUint32 mRecordsRemovedSinceLastRanking;
// Maximum permitted length of mRankedEntries array
PRUint32 mMaxEntries;
// Number of occupied slots in mRankedEntries array
PRUint32 mNumEntries;
// Capacity of mRankedEntries array
PRUint32 mCapacityRankedEntriesArray;
// Time at which cache entries were last ranked by profitability
PRUint32 mLastRankTime;
};
#endif // _nsReplacementPolicy_h_

View File

@ -1,32 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = disk memory
include $(topsrcdir)/config/rules.mk

View File

@ -1,29 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
DIRS= \
disk \
memory \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@ -1,45 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = diskcache
LIBRARY_NAME = diskcache
IS_COMPONENT = 1
CPPSRCS = \
nsDiskModule.cpp \
nsMonitorable.cpp \
nsFileStream.cpp \
nsDiskModuleFactory.cpp \
$(NULL)
LOCAL_INCLUDES = -I../../public -I../../include -I..
include $(topsrcdir)/config/rules.mk
DSO_LDOPTS += -ldb

View File

@ -1,65 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE=diskcache
IS_COMPONENT=1
MAKE_OBJ_TYPE=DLL
DLLNAME=diskcache
DLL=.\$(OBJDIR)\$(DLLNAME).dll
LLIBS= $(LLIBS) \
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\dbm32.lib \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsDiskModule.obj \
.\$(OBJDIR)\nsMonitorable.obj \
.\$(OBJDIR)\nsFileStream.obj \
.\$(OBJDIR)\nsDiskModuleFactory.obj \
$(NULL)
LOCAL_INCLUDES= -I. \
-I..\..\public \
-I..\..\include \
INCLUDES = $(LOCAL_INCLUDES)
REQUIRES = nspr
INCS = -I..\..\public \
-I..\..\include \
$(INCS) \
-I$(DEPTH)\dist\include \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) $(DLL) $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@ -1,102 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsCacheModule.h"
#include "nsCacheTrace.h"
#include "nsCacheIterator.h"
/*
* nsCacheModule
*
* Gagan Saksena 02/02/98
*
*/
#define DEFAULT_SIZE 10*0x100000L
nsCacheModule::nsCacheModule(const PRUint32 i_size=DEFAULT_SIZE):
m_Size(i_size),
m_SizeInUse(0),
m_pEnumeration(0),
m_pNext(0),
m_Entries(0)
{
m_pIterator = new nsCacheIterator(this);
}
nsCacheModule::~nsCacheModule()
{
if (m_pNext)
{
delete m_pNext;
m_pNext = 0;
}
if (m_pIterator)
{
delete m_pIterator;
m_pIterator = 0;
}
if (m_pEnumeration)
{
delete m_pEnumeration;
m_pEnumeration = 0;
}
}
void nsCacheModule::GarbageCollect(void)
{
}
PRBool nsCacheModule::ReduceSizeTo(const PRUint32 i_NewSize)
{
MonitorLocker ml(this);
//TODO
return PR_TRUE;
}
PRBool nsCacheModule::RemoveAll(void)
{
MonitorLocker ml(this);
PRBool status = PR_TRUE;
while (m_Entries > 0)
{
status &= Remove(--m_Entries);
}
return status;
}
#if 0
// Caller must free this
const char* nsCacheModule::Trace() const
{
char linebuffer[128];
char* total;
PR_sprintf(linebuffer, "nsCacheModule: Objects = %d\n", Entries());
total = new char[PR_strlen(linebuffer) + 1];
strcpy(total, linebuffer);
return total;
}
#endif

View File

@ -1,843 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsDiskModule
*
* Gagan Saksena 02/02/98
*
*/
#include "prtypes.h"
#include "prmem.h"
#include "plstr.h"
#include "prlog.h"
#include "prclist.h"
#include "prio.h"
#include "prsystem.h" // Directory Separator
#include "nsDiskModule.h"
#include "nsICacheObject.h"
#include "nsCacheObject.h"
#include "nsCacheManager.h"
#include "nsFileStream.h"
#include "nsCachePref.h"
#include "nsRepository.h"
#include "mcom_db.h"
#define ENSURE_INIT \
if (!m_pDB) \
{ \
nsDiskModule* pThis = (nsDiskModule*) this; \
PRBool res = pThis->InitDB(); \
PR_ASSERT(res); \
}
struct recentlyUsedObject {
PRCList link;
nsICacheObject* cacheObject;
};
/* Find pointer to recentlyUsedObject struct
* from the list linkaged embedded in it
*/
#define OBJECT_PTR(_link) \
((recentlyUsedObject*) ((char*) (_link) - offsetof(recentlyUsedObject,link)))
//File static list of recently used cache objects
static PRCList g_RecentlyUsedList;
static nsICacheObject* g_pTempObj=0;
static char* g_FullFilename=0;
const static int MAX_FILENAME_LEN = 512;
const static int MAX_OBJECTS_IN_RECENTLY_USED_LIST = 20; // change later TODO.
// Every time we cleanup we cleanup to 75% of the max available size.
// This should ideally change to a more const number than a percentage.
// Since someone may have a bigger cache size, so we don't really want to
// be cleaning up 5 megs if some one has a 20 megs cache size.
// I will revisit this issue once the basic architecture is up and running.
#define CLEANUP_FACTOR 0.75
//Returns the full filename including the cache directory.
static char* FullFilename(const char* i_Filename);
//Returns the Least Recently Used object in the database
static nsICacheObject* LRUObject(DB* pDB);
static NS_DEFINE_IID (kICacheObjectIID, NS_ICACHEOBJECT_IID);
static NS_DEFINE_IID (kCacheObjectCID, NS_CACHEOBJECT_CID);
static NS_DEFINE_IID (kICacheManagerIID, NS_ICACHEMANAGER_IID);
static NS_DEFINE_IID (kCacheManagerCID, NS_CACHEMANAGER_CID);
static nsICachePref*
GetPrefsInstance ()
{
nsICacheManager* pICacheMgr = nsnull;
nsServiceManager::GetService (kCacheManagerCID, kICacheManagerIID,
(nsISupports **) &pICacheMgr);
if (!pICacheMgr)
return nsnull;
nsICachePref* pICachePref = nsnull;
pICacheMgr->GetPrefs (&pICachePref);
return pICachePref;
}
//
// Constructors: nsDiskModule
//
nsDiskModule::nsDiskModule():
m_SizeInUse(0),
m_pEnumeration(0),
m_pNext(0),
m_pDB(0)
{
nsICachePref* pICachePref = GetPrefsInstance();
PR_ASSERT (pICachePref);
pICachePref->GetDiskCacheSize (&m_Size);
PR_INIT_CLIST(&g_RecentlyUsedList);
}
nsDiskModule::nsDiskModule(const PRUint32 size):
m_Size (size),
m_SizeInUse(0),
m_pEnumeration(0),
m_pNext(0),
m_pDB(0)
{
PR_INIT_CLIST(&g_RecentlyUsedList);
}
nsDiskModule::~nsDiskModule()
{
//This will free up any operational "over the limit" cache objects.
GarbageCollect();
if (m_pDB)
{
(*m_pDB->sync)(m_pDB, 0);
(*m_pDB->close)(m_pDB);
m_pDB = 0;
}
/* Clean up the recently used list */
recentlyUsedObject* obj;
while (!PR_CLIST_IS_EMPTY(&g_RecentlyUsedList))
{
obj = (recentlyUsedObject*) PR_LIST_HEAD(&g_RecentlyUsedList);
if (obj->cacheObject)
delete obj->cacheObject;
PR_REMOVE_LINK(&obj->link);
}
PR_ASSERT(PR_CLIST_IS_EMPTY(&g_RecentlyUsedList));
if (g_FullFilename)
{
delete[] g_FullFilename;
g_FullFilename = 0;
}
if (g_pTempObj)
{
delete g_pTempObj;
g_pTempObj = 0;
}
}
NS_IMETHODIMP
nsDiskModule::AddObject(nsICacheObject* io_pObject)
{
ENSURE_INIT;
if (!m_pDB || !io_pObject)
{
// Set some error state TODO
return NS_ERROR_FAILURE;
}
char *url = nsnull;
nsresult r = io_pObject->GetAddress (&url);
if (r == NS_OK && url)
{
MonitorLocker ml(this);
//Remove the earliar copy- silently handles if not found
RemoveByURL(url);
// TODO optimize these further- make static - Gagan
DBT* key = PR_NEW(DBT);
DBT* data = PR_NEW(DBT);
//Set the module
io_pObject->SetModuleIndex (nsCacheManager::DISK);
//Close the corresponding file
nsStream* pStream = (nsStream *) nsnull;
r = io_pObject->GetStream (&pStream);
if (pStream)
PR_Close(((nsFileStream*)pStream)->FileDesc());
key->data = (void*)url;
/* Later on change this to include post data- io_pObject->KeyData() */
key->size = PL_strlen(url);
io_pObject->GetInfo ((void **) &data->data);
io_pObject->GetInfoSize (&data->size);
int status = (*m_pDB->put)(m_pDB, key, data, 0);
if (status == 0)
{
// if (m_Sync == EVERYTIME)
status = (*m_pDB->sync)(m_pDB, 0);
m_Entries++;
PRUint32 size;
io_pObject->GetSize(&size);
m_SizeInUse += size;
}
PR_Free(key);
PR_Free(data);
return ((status == 0) ? NS_OK : NS_ERROR_FAILURE);
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDiskModule::ContainsCacheObj(nsICacheObject* io_pObject, PRBool* o_bContain)
{
ENSURE_INIT;
*o_bContain = PR_FALSE;
if (!m_pDB || !io_pObject)
return NS_OK;
char *url;
if (io_pObject->GetAddress (&url) != NS_OK)
return NS_OK;
nsICacheObject* pTemp = 0;
if (GetObjectByURL(url, &pTemp) != NS_OK)
return NS_OK;
if (pTemp)
{
//PR_ASSERT(io_pObject == pTemp);
// until I do a copyFrom function
*o_bContain = PR_TRUE;
}
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::ContainsURL(const char* i_url, PRBool* o_bContain)
{
ENSURE_INIT;
*o_bContain = PR_FALSE;
if (!m_pDB || !i_url || !*i_url)
return NS_OK;
DBT key, data;
key.data = (void*) i_url;
key.size = PL_strlen(i_url);
int status = (*m_pDB->get)(m_pDB, &key, &data, 0);
*o_bContain = (status == 0)? PR_TRUE : PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GarbageCollect(void)
{
MonitorLocker ml(this);
ReduceSizeTo((PRUint32)(CLEANUP_FACTOR*m_Size));
// if the recentlyusedlist has grown too big, trim some objects from there as well
// Count how many are there
int count=0;
if (!PR_CLIST_IS_EMPTY(&g_RecentlyUsedList))
{
PRCList* list = g_RecentlyUsedList.next;
while (list != &g_RecentlyUsedList)
{
count++;
list = list->next;
}
}
// Then trim the extra ones.
int extra = count-MAX_OBJECTS_IN_RECENTLY_USED_LIST;
while (extra>0)
{
recentlyUsedObject* obj = (recentlyUsedObject*) PR_LIST_HEAD(&g_RecentlyUsedList);
if (obj->cacheObject)
delete obj->cacheObject;
PR_REMOVE_LINK(&obj->link);
extra--;
}
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GetObjectByIndex(const PRUint32 i_index,
nsICacheObject** ppICacheObject)
{
ENSURE_INIT;
if (!ppICacheObject)
return NS_ERROR_NULL_POINTER;
*ppICacheObject = (nsICacheObject *) nsnull;
if (!m_pDB)
return NS_OK;
//todo
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskModule::GetObjectByURL(const char* i_url, nsICacheObject** ppICacheObject)
{
ENSURE_INIT;
MonitorLocker ml((nsDiskModule*)this);
if (!ppICacheObject)
return NS_ERROR_NULL_POINTER;
*ppICacheObject = (nsICacheObject *) nsnull;
if (!m_pDB || !i_url || !*i_url)
return NS_OK;
/* Check amongst recently used objects */
recentlyUsedObject* obj;
PRCList* list = &g_RecentlyUsedList;
if (!PR_CLIST_IS_EMPTY(&g_RecentlyUsedList))
{
list = g_RecentlyUsedList.next;
nsICacheObject* pObj;
while (list != &g_RecentlyUsedList)
{
obj = OBJECT_PTR(list);
pObj = obj->cacheObject;
char *addr;
nsresult r = pObj->GetAddress (&addr);
if (r != NS_OK)
return r;
if (0 == PL_strcasecmp(i_url, addr)) //todo also validate
{
*ppICacheObject = pObj;
return NS_OK;
}
list = list->next;
}
}
DBT key, data;
key.data = (void*) i_url;
key.size = PL_strlen(i_url);
if (0 == (*m_pDB->get)(m_pDB, &key, &data, 0))
{
nsICacheObject* pTemp;
nsresult rv = nsComponentManager::CreateInstance(kCacheObjectCID,
nsnull,
kICacheObjectIID,
(void**) &pTemp);
PR_ASSERT(rv == NS_OK);
pTemp->SetInfo(data.data);
recentlyUsedObject* pNode = PR_NEWZAP(recentlyUsedObject);
PR_APPEND_LINK(&pNode->link, &g_RecentlyUsedList);
pNode->cacheObject = pTemp;
*ppICacheObject = pTemp;
}
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GetStreamFor(const nsICacheObject* i_pObject, nsStream** o_stream)
{
ENSURE_INIT;
MonitorLocker ml(this);
*o_stream = 0;
if (i_pObject)
{
nsresult r = i_pObject->GetStream(o_stream);
if (r != NS_OK)
return r;
char *filename = nsnull;
i_pObject->GetFilename (&filename);
PR_ASSERT(filename);
char* fullname = FullFilename(filename);
if (fullname)
{
*o_stream = new nsFileStream(fullname);
}
}
return NS_OK;
}
// Private Function
PRBool nsDiskModule::InitDB(void)
{
MonitorLocker ml(this);
if (m_pDB)
return PR_TRUE;
HASHINFO hash_info = {
16*1024, /* bucket size */
0, /* fill factor */
0, /* number of elements */
0, /* bytes to cache */
0, /* hash function */
0}; /* byte order */
char *filename;
nsICachePref* pICachePref = GetPrefsInstance();
PR_ASSERT (pICachePref);
pICachePref->GetDiskCacheDBFilename (&filename);
m_pDB = dbopen(
FullFilename(filename),
O_RDWR | O_CREAT,
0600, // this is octal, yixiong
DB_HASH,
&hash_info);
if (!m_pDB)
return PR_FALSE;
/* Open and read in the number of existing entries */
m_Entries = 0;
m_SizeInUse = 0;
int status;
DBT key, data;
if (0 == g_pTempObj)
{
nsresult rv = nsComponentManager::CreateInstance(kCacheObjectCID,
nsnull,
kICacheObjectIID,
(void**) &g_pTempObj);
PR_ASSERT (rv == NS_OK);
}
if(!(status = (*m_pDB->seq)(m_pDB, &key, &data, R_FIRST)))
{
do
{
/* Also validate the corresponding file here *///TODO
g_pTempObj->SetInfo(data.data);
PRUint32 size;
g_pTempObj->GetSize(&size);
m_SizeInUse += size;
m_Entries++;
}
while(!(status = (*m_pDB->seq) (m_pDB, &key, &data, R_NEXT)));
}
if (status < 0)
return PR_FALSE;
return PR_TRUE;
}
NS_IMETHODIMP
nsDiskModule::ReduceSizeTo(const PRUint32 i_NewSize)
{
MonitorLocker ml(this);
PRInt32 needToFree = m_SizeInUse - i_NewSize;
if ((m_Entries>0) && (needToFree > 0))
{
PRUint32 avg = m_SizeInUse/m_Entries;
if (avg==0)
return NS_ERROR_FAILURE;
PRUint32 nObjectsToFree = needToFree/avg;
if (nObjectsToFree < 1)
nObjectsToFree = 1;
while (nObjectsToFree > 0)
{
RemoveByObject (LRUObject(m_pDB));
--nObjectsToFree;
}
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDiskModule::RemoveByURL(const char* i_url)
{
ENSURE_INIT;
nsICacheObject* pICacheObject;
nsresult r = GetObjectByURL(i_url, &pICacheObject);
if (r != NS_OK)
return r;
return RemoveByObject(pICacheObject);
}
NS_IMETHODIMP
nsDiskModule::RemoveByObject(nsICacheObject* pObject)
{
MonitorLocker ml(this);
nsresult bStatus = NS_ERROR_FAILURE;
if (!pObject)
return bStatus;
//PR_ASSERT(Contains(pObject);
// TODO Mark the objects state for deletion so that we dont
// read it in the meanwhile.
pObject->SetState(nsCacheObject::EXPIRED);
//Remove it from the index
DBT key;
pObject->GetAddress((char **) &key.data);
key.size = PL_strlen((char *)key.data);
if (0 == (*m_pDB->del)(m_pDB, &key, 0))
{
--m_Entries;
PRUint32 size;
pObject->GetSize (&size);
m_SizeInUse -= size;
if (-1 == (*m_pDB->sync)(m_pDB, 0))
{
//Failed to sync database
PR_ASSERT(0);
}
}
//Remove it from the recently used list
recentlyUsedObject* obj;
PRCList* list = &g_RecentlyUsedList;
if (!PR_CLIST_IS_EMPTY(&g_RecentlyUsedList))
{
list = g_RecentlyUsedList.next;
nsICacheObject* pObj;
PRBool bDone = PR_FALSE;
while ((list != &g_RecentlyUsedList) && !bDone)
{
obj = OBJECT_PTR(list);
pObj = obj->cacheObject;
if (pObj == pObject)
{
bDone = PR_TRUE;
PR_REMOVE_LINK(&obj->link);
}
list = list->next;
}
}
//Remove it from the disk
char *filename;
pObject->GetFilename(&filename);
if (PR_SUCCESS == PR_Delete(FullFilename(filename)))
{
bStatus = NS_OK;
}
else
{
//Failed to delete the file off the disk!
bStatus = NS_ERROR_FAILURE;
}
//Finally delete it
delete pObject;
pObject = 0;
return bStatus;
}
NS_IMETHODIMP
nsDiskModule::RemoveByIndex(const PRUint32 i_index)
{
//This will probably go away.
ENSURE_INIT;
//TODO
// Also remove the file corresponding to this item.
//return PR_FALSE;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskModule::RemoveAll(void)
{
MonitorLocker ml (this);
while (m_Entries > 0)
{
RemoveByIndex (--m_Entries);
}
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::Revalidate(void)
{
ENSURE_INIT;
//TODO - This will add a dependency on HTTP lib
//return PR_FALSE;
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsDiskModule::SetSize(const PRUint32 i_Size)
{
MonitorLocker ml(this);
m_Size = i_Size;
if (m_Size >0)
{
ReduceSizeTo((PRUint32)(CLEANUP_FACTOR*m_Size));
}
else
{
RemoveAll();
}
return NS_OK;
}
char* FullFilename(const char* i_Filename)
{
static int cacheFolderLength=0;
if (0 == g_FullFilename)
{
g_FullFilename = new char[MAX_FILENAME_LEN];
*g_FullFilename = '\0';
if (0 == g_FullFilename)
return 0;
}
char *folder;
nsICachePref* pICachePref = GetPrefsInstance();
PR_ASSERT (pICachePref);
pICachePref->GetDiskCacheFolder (&folder);
PR_ASSERT (folder);
PL_strcpy(g_FullFilename, folder);
if (0==cacheFolderLength)
cacheFolderLength = PL_strlen(folder);
#ifndef XP_MAC
if (g_FullFilename[cacheFolderLength-1]!=PR_GetDirectorySeparator())
{
g_FullFilename[cacheFolderLength] = PR_GetDirectorySeparator();
g_FullFilename[cacheFolderLength+1] = '\0';
}
#endif
PL_strcat(g_FullFilename, i_Filename);
return g_FullFilename;
}
nsICacheObject* LRUObject(DB* pDB)
{
int status;
DBT key, data;
nsICacheObject* pTempObj;
nsresult rv = nsComponentManager::CreateInstance(kCacheObjectCID,
nsnull,
kICacheObjectIID,
(void**) &pTempObj);
if (rv != NS_OK)
return nsnull;
nsICacheObject* pOldest=0;
if(!(status = (*pDB->seq)(pDB, &key, &data, R_FIRST)))
{
do
{
pTempObj->SetInfo(data.data);
PRIntervalTime old, current;
if (pOldest)
{
pOldest->GetLastAccessed (&old);
}
pTempObj->GetLastAccessed (&current);
if (!pOldest || (old > current))
pOldest = pTempObj;
}
while(!(status = (*pDB->seq) (pDB, &key, &data, R_NEXT)));
}
return ((nsICacheObject *) pOldest);
}
NS_IMETHODIMP
nsDiskModule::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_ASSERTION(aInstancePtr, "no instance pointer");
*aInstancePtr = 0;
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()) ||
aIID.Equals(nsCOMTypeInfo<nsICacheModule>::GetIID()))
{
*aInstancePtr = NS_STATIC_CAST (nsICacheModule*, this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsDiskModule);
NS_IMPL_RELEASE(nsDiskModule);
NS_METHOD
nsDiskModule::Create(nsISupports* aOuter, const nsIID& aIID, void** aResult)
{
nsDiskModule* cm = new nsDiskModule();
if (cm == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF (cm);
nsresult rv = cm->QueryInterface (aIID, aResult);
NS_RELEASE (cm);
return rv;
}
NS_IMETHODIMP
nsDiskModule::Enable(PRBool i_bEnable)
{
m_Enabled = i_bEnable;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GetNumOfEntries(PRUint32* o_nEntries)
{
*o_nEntries = m_Entries;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GetEnumerator(nsEnumeration** o_enum)
{
MonitorLocker ml((nsMonitorable*)this);
if (!m_pEnumeration)
{
PR_ASSERT(m_pIterator);
((nsDiskModule*)this)->m_pEnumeration =
new nsEnumeration((nsIterator*)m_pIterator);
}
else
((nsDiskModule*)this)->m_pEnumeration->Reset();
*o_enum = m_pEnumeration;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::IsEnabled(PRBool* o_bEnabled)
{
*o_bEnabled = m_Enabled;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::IsReadOnly (PRBool* o_bReadOnly)
{
*o_bReadOnly = PR_FALSE; // for Now
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GetNextModule(nsICacheModule** o_pICacheModule)
{
*o_pICacheModule = m_pNext;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::SetNextModule(nsICacheModule* pNext)
{
/* No overwriting */
PR_ASSERT(m_pNext == 0);
if (m_pNext)
{
/* ERROR */
delete m_pNext; //Worst case.
m_pNext = 0;
}
m_pNext = pNext;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GetSize(PRUint32* o_size)
{
*o_size = m_Size;
return NS_OK;
}
NS_IMETHODIMP
nsDiskModule::GetSizeInUse(PRUint32* o_size)
{
*o_size = m_SizeInUse;
return NS_OK;
}
#undef ENSURE_INIT

View File

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIGenericFactory.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsDiskModule.h"
#include "nscore.h"
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
static NS_DEFINE_CID(kDiskModuleCID, NS_DISKMODULE_CID);
////////////////////////////////////////////////////////////////////////////////
// return the proper factory to the caller
extern "C" PR_IMPLEMENT(nsresult)
NSGetFactory(nsISupports* aServMgr,
const nsCID &aClass,
const char *aClassName,
const char *aProgID,
nsIFactory **aFactory)
{
nsresult rv;
if (aFactory == nsnull)
return NS_ERROR_NULL_POINTER;
nsIGenericFactory* fact;
if (aClass.Equals(kDiskModuleCID)) {
rv = NS_NewGenericFactory(&fact, nsDiskModule::Create);
}
else {
rv = NS_ERROR_FAILURE;
}
if (NS_SUCCEEDED(rv))
*aFactory = fact;
return rv;
}
extern "C" PR_IMPLEMENT(nsresult)
NSRegisterSelf(nsISupports* aServMgr , const char* aPath)
{
nsresult rv;
NS_WITH_SERVICE1(nsIComponentManager, compMgr, aServMgr,
kComponentManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = compMgr->RegisterComponent(kDiskModuleCID,
"Disk Module Cache",
"components://necko/cache/disk",
aPath, PR_TRUE, PR_TRUE);
if (NS_FAILED(rv)) return rv;;
return rv;
}
extern "C" PR_IMPLEMENT(nsresult)
NSUnregisterSelf(nsISupports* aServMgr, const char* aPath)
{
nsresult rv;
NS_WITH_SERVICE1(nsIComponentManager, compMgr, aServMgr, kComponentManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = compMgr->UnregisterComponent(kDiskModuleCID, aPath);
if (NS_FAILED(rv)) return rv;
return rv;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,113 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsFileStream.h"
#include "plstr.h"
#include "prlog.h"
nsFileStream::nsFileStream(const char* i_Filename):m_pFile(0),m_pFilename(0)
{
PR_ASSERT(i_Filename);
if (i_Filename)
{
m_pFilename = new char[PL_strlen(i_Filename)+1];
PL_strcpy(m_pFilename, i_Filename);
Open();
}
}
nsFileStream::~nsFileStream()
{
if (m_pFilename)
{
delete[] m_pFilename;
m_pFilename = 0;
}
if (m_pFile)
PR_Close(m_pFile);
}
/*
nsrefcnt nsFileStream::AddRef(void)
{
return ++m_RefCnt;
}
nsrefcnt nsFileStream::Release(void)
{
if (--m_RefCnt == 0)
{
delete this;
return 0;
}
return m_RefCnt;
}
nsresult nsFileStream::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
return NS_OK;
}
*/
PRBool nsFileStream::Open()
{
if (m_pFile)
PR_Close(m_pFile);
PR_ASSERT(m_pFilename);
if (m_pFilename)
{
m_pFile = PR_Open(
m_pFilename,
PR_CREATE_FILE | PR_RDWR,
0600);// Read and write by owner only
PR_ASSERT(m_pFile);
if (m_pFile)
return PR_TRUE;
}
return PR_FALSE;
}
PRInt32 nsFileStream::Read(void* o_Buffer, PRUint32 i_Len)
{
if (!m_pFile && !Open())
return 0;
// heck, remove later.
// PRInt32 r = PR_Seek(m_pFile, 0, PR_SEEK_SET) ;
// end heck
return PR_Read(m_pFile, o_Buffer, i_Len);
}
void nsFileStream::Reset()
{
Open();
}
PRInt32 nsFileStream::Write(const void* i_Buffer, PRUint32 i_Len)
{
if (!m_pFile && !Open())
return 0;
return PR_Write(m_pFile, i_Buffer, i_Len);
}

View File

@ -1,41 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* This is the implementation of the nsMonitorable::MonitorLocker class.
* Although the inlines work ok elsewhere, IRIX chokes on these. Hence
* moving these to a cpp.
* -Gagan Saksena 09/15/98
*/
#include "nsMonitorable.h"
nsMonitorable::MonitorLocker::MonitorLocker(nsMonitorable* i_pThis):
m_pMonitorable(i_pThis)
{
if (m_pMonitorable) m_pMonitorable->Lock();
}
nsMonitorable::MonitorLocker::~MonitorLocker()
{
if (m_pMonitorable) m_pMonitorable->Unlock();
}

View File

@ -1,53 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = memcache
LIBRARY_NAME = memcache
IS_COMPONENT = 1
REQUIRES = nspr
CPPSRCS = \
nsMemModule.cpp \
nsMemCacheObject.cpp \
nsMemStream.cpp \
nsMonitorable.cpp \
nsMemModuleFactory.cpp \
$(NULL)
LOCAL_INCLUDES = \
-I$(srcdir) \
-I$(srcdir)/../../include \
-I$(srcdir)/../../public \
-I$(srcdir)/.. \
$(NULL)
EXTRA_LIBS = $(NSPR_LIBS)
include $(topsrcdir)/config/rules.mk

View File

@ -1,65 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE=MemoryCache
IS_COMPONENT=1
MAKE_OBJ_TYPE=DLL
DLLNAME=MemoryCache
DLL=.\$(OBJDIR)\$(DLLNAME).dll
LLIBS= $(LLIBS) \
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsMemModule.obj \
.\$(OBJDIR)\nsMonitorable.obj \
.\$(OBJDIR)\nsMemCacheObject.obj \
.\$(OBJDIR)\nsMemStream.obj \
.\$(OBJDIR)\nsMemModuleFactory.obj \
$(NULL)
LOCAL_INCLUDES= -I. \
-I..\..\public \
-I..\..\include \
INCLUDES = $(LOCAL_INCLUDES)
REQUIRES = nspr
INCS = -I..\..\public \
-I..\..\include \
$(INCS) \
-I$(DEPTH)\dist\include \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) $(DLL) $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsMemCacheObject
*
* Gagan Saksena 04/22/98
*
*/
#include "prtypes.h"
#include "nsMemCacheObject.h"
#include "nsMemStream.h"
nsMemCacheObject::~nsMemCacheObject()
{
if (m_pNextObject)
{
delete m_pNextObject;
m_pNextObject = 0;
}
if (m_pObject)
{
nsStream* pStream;
m_pObject->GetStream(&pStream);
if (pStream)
delete (nsMemStream*)pStream;
delete m_pObject;
m_pObject = 0;
}
}

View File

@ -1,103 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* The nsMemCacheObject class holds the actual nsCacheObject and a pointer
* to the next nsMemCacheObject. Pretty simple solution for the time being.
* Should be replaced once the memory hash table stuff gets up and running.
*
* -Gagan Saksena 09/15/98.
*/
#ifndef _nsMemCacheObject_h_
#define _nsMemCacheObject_h_
#include "prtypes.h"
#include "prlog.h"
#include "nsICacheObject.h"
#include "nsCacheObject.h"
class nsMemCacheObject
{
public:
nsMemCacheObject(void);
nsMemCacheObject(nsICacheObject* io_pObject);
nsMemCacheObject(const char* i_url);
~nsMemCacheObject();
void Next(nsMemCacheObject* pObject);
void Next(nsICacheObject* io_pObject);
nsMemCacheObject* Next(void) const;
nsICacheObject* ThisObject(void) const;
private:
nsICacheObject* m_pObject;
nsMemCacheObject* m_pNextObject;
nsMemCacheObject& operator=(const nsMemCacheObject& mco);
nsMemCacheObject(const nsMemCacheObject&);
};
inline nsMemCacheObject::nsMemCacheObject(void):
m_pObject((nsICacheObject *) new nsCacheObject()),
m_pNextObject(0)
{
}
inline nsMemCacheObject::nsMemCacheObject(nsICacheObject* io_pObject):
m_pObject(io_pObject),
m_pNextObject(0)
{
}
inline nsMemCacheObject::nsMemCacheObject(const char* i_url):
m_pObject((nsICacheObject *) new nsCacheObject(i_url)),
m_pNextObject(0)
{
}
inline nsMemCacheObject* nsMemCacheObject::Next(void) const
{
return m_pNextObject;
}
inline void nsMemCacheObject::Next(nsMemCacheObject* pObject)
{
PR_ASSERT(0==m_pNextObject);
m_pNextObject = pObject;
}
inline void nsMemCacheObject::Next(nsICacheObject* pObject)
{
PR_ASSERT(0==m_pNextObject);
m_pNextObject = new nsMemCacheObject(pObject);
}
inline nsICacheObject* nsMemCacheObject::ThisObject(void) const
{
return m_pObject;
}
#endif //_nsMemCacheObject_h_

View File

@ -1,489 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "prtypes.h"
#include "prmem.h"
#include "plstr.h"
#include "prclist.h"
#include "prio.h"
#include "prsystem.h"
#include "prlog.h"
#include "nsMemModule.h"
#include "nsMemCacheObject.h"
#include "nsCacheManager.h"
#include "nsICacheManager.h"
#include "nsICachePref.h"
#include "nsMemStream.h"
/*
* nsMemModule
*
* Gagan Saksena 02/02/98
*
*/
static NS_DEFINE_IID(kICacheManagerIID, NS_ICACHEMANAGER_IID);
static NS_DEFINE_IID(kCacheManagerCID, NS_CACHEMANAGER_CID);
nsMemModule::nsMemModule():
m_pFirstObject(0),
m_SizeInUse(0),
m_pEnumeration(0),
m_pNext(0)
{
nsICacheManager* pICacheMgr;
nsresult rv = nsServiceManager::GetService (kCacheManagerCID,
kICacheManagerIID,
(nsISupports **) &pICacheMgr);
PR_ASSERT (rv == NS_OK);
nsICachePref* pPref;
rv = pICacheMgr->GetPrefs (&pPref);
PR_ASSERT (rv == NS_OK);
pPref->GetMemCacheSize(&m_Size);
}
nsMemModule::nsMemModule(const PRUint32 size):
m_pFirstObject(0),
m_Size (size),
m_SizeInUse(0),
m_pEnumeration(0),
m_pNext(0)
{
}
nsMemModule::~nsMemModule()
{
if (m_pFirstObject) {
delete m_pFirstObject;
m_pFirstObject = 0;
}
}
NS_IMETHODIMP
nsMemModule::AddObject(nsICacheObject* io_pObject)
{
#if 0
if (io_pObject)
{
m_ht.Put(io_pObject->Address(), io_pObject);
}
return NS_ERROR_FAILURE;
#endif
if (io_pObject)
{
MonitorLocker ml((nsMonitorable*)this);
nsStream* pStream = (nsStream *) nsnull;
io_pObject->GetStream(&pStream);
// I removed this assert. I don't think it should be here. yixiong
// pStream would be set later by GetStreamFor( ) in nsCacheobject
// PR_ASSERT(pStream); // A valid stream does exist for this
if (m_pFirstObject)
{
LastObject()->Next(new nsMemCacheObject(io_pObject));
}
else
{
m_pFirstObject = new nsMemCacheObject(io_pObject);
}
m_Entries++;
io_pObject->SetModuleIndex(nsCacheManager::MEM);
return NS_OK;
}
// Todo: Better error handling
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsMemModule::ContainsURL (const char* i_url, PRBool* o_bContain)
{
MonitorLocker ml((nsMonitorable*)this);
*o_bContain = PR_FALSE;
if (m_pFirstObject && i_url && *i_url)
{
nsMemCacheObject* pObj = m_pFirstObject;
do
{
char *thisURL = nsnull;
pObj->ThisObject()->GetAddress (&thisURL);
if (0 == PL_strcasecmp(thisURL, i_url))
{
*o_bContain = PR_TRUE;
break;
}
pObj = pObj->Next();
}
while (pObj);
}
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::ContainsCacheObj(nsICacheObject* i_pObject, PRBool* o_bContain)
{
MonitorLocker ml((nsMonitorable*)this);
*o_bContain = PR_FALSE;
char *url = (char *) nsnull;
if (i_pObject)
{
i_pObject->GetAddress (&url);
}
if (url && *url)
{
this->ContainsURL(url, o_bContain);
}
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GarbageCollect(void)
{
MonitorLocker ml((nsMonitorable*) this);
if (m_Entries > 0)
{
nsEnumeration* pEnum;
GetEnumerator(&pEnum);
PRUint32 idx = 0;
while (pEnum->HasMoreElements())
{
nsICacheObject* pObj = (nsICacheObject*) pEnum->NextElement();
PRBool bExpired = PR_FALSE;
if (pObj)
{
pObj->IsExpired (&bExpired);
}
if (bExpired == PR_TRUE)
{
nsresult r = RemoveByIndex (idx);
PR_ASSERT(r == NS_OK);
}
++idx;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetObjectByIndex (const PRUint32 i_index,
nsICacheObject** ppICacheObject)
{
MonitorLocker ml((nsMonitorable*)this);
nsMemCacheObject* pNth = 0;
if (m_pFirstObject)
{
PRUint32 idx = 0;
pNth = m_pFirstObject;
while (pNth->Next() && (idx++ != i_index ))
{
pNth = pNth->Next();
}
}
if (pNth)
*ppICacheObject = pNth->ThisObject();
else
*ppICacheObject = (nsICacheObject *) nsnull;
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetObjectByURL(const char* i_url, nsICacheObject** ppICacheObject)
{
MonitorLocker ml((nsMonitorable*)this);
*ppICacheObject = (nsICacheObject *) nsnull;
if (m_pFirstObject && i_url && *i_url)
{
nsMemCacheObject* pObj = m_pFirstObject;
do
{
char *thisURL;
pObj->ThisObject()->GetAddress (&thisURL);
if (0 == PL_strcasecmp(thisURL, i_url))
{
*ppICacheObject = pObj->ThisObject();
break;
}
pObj = pObj->Next();
}
while (pObj);
}
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetStreamFor(const nsICacheObject* i_pObject, nsStream** o_stream)
{
MonitorLocker ml(this);
*o_stream = nsnull;
if (i_pObject)
{
PRBool bContain = PR_FALSE;
ContainsCacheObj((nsICacheObject*) i_pObject, &bContain);
if (bContain)
{
nsStream* pStream = (nsStream *) nsnull;
i_pObject->GetStream(&pStream);
if (pStream)
{
*o_stream = pStream;
return NS_OK;
}
}
// Set up a new stream for this object
*o_stream = new nsMemStream();
}
return NS_OK;
}
nsMemCacheObject* nsMemModule::LastObject(void) const
{
MonitorLocker ml((nsMonitorable*)this);
nsMemCacheObject* pLast = 0;
if (m_pFirstObject)
{
pLast = m_pFirstObject;
while (pLast->Next())
pLast = pLast->Next();
}
return pLast;
}
NS_IMETHODIMP
nsMemModule::ReduceSizeTo(const PRUint32 i_NewSize)
{
//TODO
return PR_TRUE;
}
NS_IMETHODIMP
nsMemModule::RemoveByURL (const char* i_url)
{
//TODO
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemModule::RemoveByIndex(const PRUint32 i_index)
{
//TODO
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemModule::RemoveByObject(nsICacheObject* i_pObj)
{
//TODO
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemModule::RemoveAll()
{
//TODO
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsMemModule::SetSize(const PRUint32 i_Size)
{
//TODO
return NS_ERROR_NOT_IMPLEMENTED;
}
//////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsMemModule::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
NS_ASSERTION(aInstancePtr, "no instance pointer");
*aInstancePtr = 0;
if (aIID.Equals(nsCOMTypeInfo<nsISupports>::GetIID()) ||
aIID.Equals(nsCOMTypeInfo<nsICacheModule>::GetIID()))
{
*aInstancePtr = NS_STATIC_CAST (nsICacheModule*, this);
NS_ADDREF_THIS();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(nsMemModule);
NS_IMPL_RELEASE(nsMemModule);
NS_METHOD
nsMemModule::Create (nsISupports *aOuter, REFNSIID aIID, void** aResult)
{
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
nsMemModule* pm = new nsMemModule();
if (pm == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF (pm);
nsresult rv = pm->QueryInterface (aIID, aResult);
NS_RELEASE (pm);
return rv;
}
//////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsMemModule::Enable(PRBool i_bEnable)
{
m_Enabled = i_bEnable;
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetNumOfEntries(PRUint32* o_nEntries)
{
*o_nEntries = m_Entries;
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetEnumerator(nsEnumeration** o_enum)
{
MonitorLocker ml((nsMonitorable*)this);
if (!m_pEnumeration)
{
PR_ASSERT(m_pIterator);
((nsMemModule*)this)->m_pEnumeration =
new nsEnumeration((nsIterator*)m_pIterator);
}
else
((nsMemModule*)this)->m_pEnumeration->Reset();
*o_enum = m_pEnumeration;
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::IsEnabled(PRBool* o_bEnabled)
{
*o_bEnabled = m_Enabled;
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::IsReadOnly (PRBool* o_bReadOnly)
{
*o_bReadOnly = PR_FALSE; // for Now
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetNextModule(nsICacheModule** o_pICacheModule)
{
if (m_pNext) {
*o_pICacheModule = m_pNext;
return NS_OK;
}
return NS_ERROR_FAILURE ;
}
NS_IMETHODIMP
nsMemModule::SetNextModule(nsICacheModule* pNext)
{
/* No overwriting */
PR_ASSERT(m_pNext == 0);
if (m_pNext)
{
/* ERROR */
delete m_pNext; //Worst case.
m_pNext = 0;
}
m_pNext = pNext;
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetSize(PRUint32* o_size)
{
*o_size = m_Size;
return NS_OK;
}
NS_IMETHODIMP
nsMemModule::GetSizeInUse(PRUint32* o_size)
{
*o_size = m_SizeInUse;
return NS_OK;
}
/*
PRUint32 nsMemModule::nsMemKey::HashValue()
{
return 0;
}
PRBool nsMemModule::nsMemKey::Equals(nsHashKey *aKey)
{
return PR_FALSE;
}
nsHashKey* nsMemModule::nsMemKey::Clone()
{
return new nsMemModule::nsMemKey();
}
nsMemModule::nsMemKey::neMemKey()
{
}
*/

View File

@ -1,91 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsIGenericFactory.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsMemModule.h"
#include "nscore.h"
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
static NS_DEFINE_CID(kMemModuleCID, NS_MEMMODULE_CID);
////////////////////////////////////////////////////////////////////////////////
// return the proper factory to the caller
extern "C" PR_IMPLEMENT(nsresult)
NSGetFactory(nsISupports* aServMgr,
const nsCID &aClass,
const char *aClassName,
const char *aProgID,
nsIFactory **aFactory)
{
nsresult rv;
if (aFactory == nsnull)
return NS_ERROR_NULL_POINTER;
nsIGenericFactory* fact;
if (aClass.Equals(kMemModuleCID)) {
rv = NS_NewGenericFactory(&fact, nsMemModule::Create);
}
else {
rv = NS_ERROR_FAILURE;
}
if (NS_SUCCEEDED(rv))
*aFactory = fact;
return rv;
}
extern "C" PR_IMPLEMENT(nsresult)
NSRegisterSelf(nsISupports* aServMgr , const char* aPath)
{
nsresult rv;
NS_WITH_SERVICE1(nsIComponentManager, compMgr, aServMgr,
kComponentManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = compMgr->RegisterComponent(kMemModuleCID,
"Mem Module Cache",
"component://necko/cache/MemModule",
aPath, PR_TRUE, PR_TRUE);
if (NS_FAILED(rv)) return rv;;
return rv;
}
extern "C" PR_IMPLEMENT(nsresult)
NSUnregisterSelf(nsISupports* aServMgr, const char* aPath)
{
nsresult rv;
NS_WITH_SERVICE1(nsIComponentManager, compMgr, aServMgr, kComponentManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = compMgr->UnregisterComponent(kMemModuleCID, aPath);
if (NS_FAILED(rv)) return rv;
return rv;
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -1,127 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsMemStream.h"
#include "prmem.h"
#include "prlog.h" /* Assert */
#ifndef XP_MAC
#include "memory.h"
#else
#include "cstring"
#endif
static const PRUint32 kPageSize = 1024;//4096;
nsMemStream::nsMemStream():m_AllocSize(0),m_Size(0),m_pStart(0),m_ReadOffset(0),m_WriteOffset(0)
{
}
nsMemStream::~nsMemStream()
{
PR_FREEIF(m_pStart);
}
/*
nsrefcnt nsMemStream::AddRef(void)
{
return ++m_RefCnt;
}
nsrefcnt nsMemStream::Release(void)
{
if (--m_RefCnt == 0)
{
delete this;
return 0;
}
return m_RefCnt;
}
nsresult nsMemStream::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
return NS_OK;
}
*/
PRInt32 nsMemStream::Read(void* o_Buffer, PRUint32 i_Len)
{
if (m_Size > 0)
{
PR_ASSERT(m_pStart); //This has to be there if m_Size > 0
char* pCurrentRead = (char*) m_pStart + m_ReadOffset;
unsigned int validLen = m_Size - m_ReadOffset;
if (0 == validLen)
return 0;
if (validLen > i_Len)
validLen = i_Len;
memcpy(o_Buffer, pCurrentRead, validLen);
m_ReadOffset += validLen;
return validLen;
}
return 0;
}
void nsMemStream::Reset()
{
m_ReadOffset = 0;
}
PRInt32 nsMemStream::Write(const void* i_Buffer, PRUint32 i_Len)
{
if (!m_pStart)
{
m_pStart = PR_Calloc(1, kPageSize);
if (!m_pStart)
{
PR_Free(m_pStart);
return 0;
}
m_WriteOffset = 0;
m_AllocSize = kPageSize;
}
unsigned int validLen = m_AllocSize - m_Size;
while (validLen < i_Len)
{
//Alloc some more
m_pStart = PR_Realloc(m_pStart, m_AllocSize+kPageSize);
if (!m_pStart)
{
PR_Free(m_pStart);
m_AllocSize = 0;
m_WriteOffset = 0;
m_Size = 0;
return 0;
}
m_AllocSize += kPageSize;
validLen += kPageSize;
}
char* pCurrentWrite = (char*)m_pStart + m_WriteOffset;
memcpy(pCurrentWrite, i_Buffer, i_Len);
m_WriteOffset += i_Len;
m_Size += i_Len;
return i_Len;
}

View File

@ -1,41 +0,0 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* This is the implementation of the nsMonitorable::MonitorLocker class.
* Although the inlines work ok elsewhere, IRIX chokes on these. Hence
* moving these to a cpp.
* -Gagan Saksena 09/15/98
*/
#include "nsMonitorable.h"
nsMonitorable::MonitorLocker::MonitorLocker(nsMonitorable* i_pThis):
m_pMonitorable(i_pThis)
{
if (m_pMonitorable) m_pMonitorable->Lock();
}
nsMonitorable::MonitorLocker::~MonitorLocker()
{
if (m_pMonitorable) m_pMonitorable->Unlock();
}

View File

@ -1,46 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = cacheobj
LIBRARY_NAME = cacheobj
IS_COMPONENT = 1
CPPSRCS = nsCacheObject.cpp
REQUIRES = nspr
LOCAL_INCLUDES = \
-I$(srcdir)/../include \
-I$(srcdir)/../public \
-I$(PUBLIC)/netlib \
$(NULL)
EXTRA_LIBS = $(NSPR_LIBS)
include $(topsrcdir)/config/rules.mk

View File

@ -1,61 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE=cacheobj
IS_COMPONENT=1
MAKE_OBJ_TYPE=DLL
DLLNAME=cacheobj
DLL=.\$(OBJDIR)\$(DLLNAME).dll
LLIBS= $(LLIBS) \
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsCacheObject.obj \
$(NULL)
LOCAL_INCLUDES= -I. \
-I..\public \
-I..\include \
INCLUDES = $(LOCAL_INCLUDES)
REQUIRES = nspr
INCS = $(INCS) \
-I..\include \
-I..\public \
-I$(DEPTH)\dist\include \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) $(DLL) $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@ -1,938 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef XP_MAC
#include "memory.h"
#else
#include "cstring"
#endif
//#include "nspr.h"
#include "nscore.h"
#include "prmem.h"
#include "prprf.h"
#include "plstr.h"
#include "prinrval.h"
// #include "nsStream.h"
// #include "nsCacheTrace.h"
#include "nsICacheModule.h"
#include "nsICacheManager.h"
#include "nsCacheObject.h"
/*
* nsCacheObject
*
* Gagan Saksena 02/02/98
*
*/
static const PRIntervalTime DEFAULT_EXPIRES = PR_SecondsToInterval(86400);
//static const PRIntervalTime DEFAULT_EXPIRES = 1000;
//static const PRIntervalTime DEFAULT_EXPIRES = PR_IntervalNow();
// Globals, need to check if safe to unload module
static PRInt32 gLockCnt = 0;
static PRInt32 gInstanceCnt = 0;
// Define constants for easy use
static NS_DEFINE_IID(kICACHEOBJECTIID, NS_ICACHEOBJECT_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kICACHEMANAGERIID, NS_ICACHEMANAGER_IID);
static NS_DEFINE_IID(kCacheManagerCID, NS_CACHEMANAGER_CID);
#if !defined(IS_LITTLE_ENDIAN) && !defined(IS_BIG_ENDIAN)
ERROR! Must have a byte order
#endif
#ifdef IS_LITTLE_ENDIAN
#define COPY_INT32(_a,_b) memcpy(_a, _b, sizeof(int32))
#else
#define COPY_INT32(_a,_b) /* swap */ \
do { \
((char *)(_a))[0] = ((char *)(_b))[3]; \
((char *)(_a))[1] = ((char *)(_b))[2]; \
((char *)(_a))[2] = ((char *)(_b))[1]; \
((char *)(_a))[3] = ((char *)(_b))[0]; \
} while(0)
#endif
/* Convenient macros used in stuffing and reading back cache object to a void * */
/* TODO: Change these to file scope functions */
#define STUFF_STRING(string) \
{ \
len = (string ? PL_strlen(string)+1 : 0); \
COPY_INT32((void *)cur_ptr, &len); \
cur_ptr = cur_ptr + sizeof(int32); \
if(len) \
memcpy((void *)cur_ptr, string, len); \
cur_ptr += len; \
}
#define STUFF_NUMBER(number) \
{ \
COPY_INT32((void *)cur_ptr, &number); \
cur_ptr = cur_ptr + sizeof(PRUint32); \
}
#define STUFF_TIME(number) \
{ \
COPY_INT32((void *)cur_ptr, &number); \
cur_ptr = cur_ptr + sizeof(PRIntervalTime); \
}
#define STUFF_BOOL(bool_val) \
{ \
if(bool_val) \
((char *)(cur_ptr))[0] = 1; \
else \
((char *)(cur_ptr))[0] = 0; \
cur_ptr = cur_ptr + sizeof(char); \
}
/* if any strings are larger than this then
* there was a serious database error
*/
#define MAX_HUGE_STRING_SIZE 10000
#define RETRIEVE_STRING(string) \
{ \
if(cur_ptr > max_ptr) \
{ \
return PR_TRUE; \
} \
COPY_INT32(&len, cur_ptr); \
cur_ptr += sizeof(int32); \
if(len) \
{ \
if(len > MAX_HUGE_STRING_SIZE) \
{ \
return PR_FALSE; \
} \
string = new char[len]; \
if(!string) \
{ \
return PR_FALSE; \
} \
memcpy(string, cur_ptr, len); \
cur_ptr += len; \
} \
}
#define RETRIEVE_NUMBER(number) \
{ \
if(cur_ptr > max_ptr) \
return PR_TRUE; \
COPY_INT32(&number, cur_ptr); \
cur_ptr += sizeof(int32); \
}
#define RETRIEVE_TIME(number) \
{ \
if(cur_ptr > max_ptr) \
return PR_TRUE; \
COPY_INT32(&number, cur_ptr); \
cur_ptr += sizeof(PRIntervalTime); \
}
#define RETRIEVE_BOOL(bool) \
{ \
if(cur_ptr > max_ptr) \
return PR_TRUE; \
if(((char *)(cur_ptr))[0]) \
bool = TRUE; \
else \
bool = FALSE; \
cur_ptr += sizeof(char); \
}
/* TODO- Further optimization, initialize these to null,
but that will add more work on copy constructor which is ok */
nsCacheObject::nsCacheObject():
m_Charset(new char[1]),
m_ContentEncoding(new char[1]),
m_ContentType(new char[1]),
m_Etag(new char[1]),
m_Filename(new char[1]),
m_State(INIT),
m_bIsCompleted(PR_FALSE),
m_Module(-1),
m_pInfo(0),
m_PageServicesURL(new char[1]),
m_PostData(new char[1]),
m_PostDataLen(0),
m_pStream(0),
m_URL(new char[1])
{
Init();
*m_Charset = '\0';
*m_ContentEncoding = '\0';
*m_ContentType = '\0';
*m_Etag = '\0';
*m_Filename = '\0';
*m_PageServicesURL = '\0';
*m_PostData = '\0';
*m_URL = '\0';
NS_INIT_ISUPPORTS() ;
PR_AtomicIncrement(&gInstanceCnt) ;
}
nsCacheObject::~nsCacheObject()
{
if (m_Charset)
delete[] m_Charset;
if (m_ContentEncoding)
delete[] m_ContentEncoding;
if (m_ContentType)
delete[] m_ContentType;
if (m_Etag)
delete[] m_Etag;
if (m_Filename)
delete[] m_Filename;
if (m_PageServicesURL)
delete[] m_PageServicesURL;
if (m_PostData)
delete[] m_PostData;
if (m_URL)
delete[] m_URL;
if (m_pStream)
delete m_pStream;
PR_AtomicDecrement(&gInstanceCnt) ;
}
nsCacheObject::nsCacheObject(const nsCacheObject& another):
m_Charset(new char[PL_strlen(another.m_Charset)+1]),
m_ContentEncoding(new char[PL_strlen(another.m_ContentEncoding)+1]),
m_ContentType(new char[PL_strlen(another.m_ContentType)+1]),
m_Etag(new char[PL_strlen(another.m_Etag)+1]),
m_Filename(new char[PL_strlen(another.m_Filename)+1]),
m_State(another.m_State),
m_bIsCompleted(another.m_bIsCompleted),
m_pInfo(0), /* Should this be copied as well? */
m_PageServicesURL(new char[PL_strlen(another.m_PageServicesURL)+1]),
m_PostData(new char[another.m_PostDataLen+1]),
m_PostDataLen(another.m_PostDataLen),
m_pStream(0),
m_URL(new char[PL_strlen(another.m_URL)+1])
{
PL_strncpyz(m_Charset, another.m_Charset, PL_strlen(another.m_Charset)+1);
PL_strncpyz(m_ContentEncoding, another.m_ContentEncoding, PL_strlen(another.m_ContentEncoding)+1);
PL_strncpyz(m_ContentType, another.m_ContentType, PL_strlen(another.m_ContentType)+1);
PL_strncpyz(m_Etag, another.m_Etag, PL_strlen(another.m_Etag)+1);
PL_strncpyz(m_Filename, another.m_Filename, PL_strlen(another.m_Filename)+1);
PL_strncpyz(m_PageServicesURL, another.m_PageServicesURL, PL_strlen(another.m_PageServicesURL)+1);
PL_strncpyz(m_PostData, another.m_PostData, another.m_PostDataLen+1);
PL_strncpyz(m_URL, another.m_URL, PL_strlen(another.m_URL)+1);
m_Hits = another.m_Hits;
m_LastAccessed = another.m_LastAccessed;
m_LastModified = another.m_LastModified;
m_Size = another.m_Size;
m_Module = another.m_Module;
NS_INIT_ISUPPORTS() ;
PR_AtomicIncrement(&gInstanceCnt) ;
}
nsCacheObject::nsCacheObject(const char* i_url):
m_Charset(new char[1]),
m_ContentEncoding(new char[1]),
m_ContentType(new char[1]),
m_Etag(new char[1]),
m_Filename(new char[1]),
m_State(INIT),
m_bIsCompleted(PR_FALSE),
m_Module(-1),
m_pInfo(0),
m_PageServicesURL(new char[1]),
m_PostData(new char[1]),
m_PostDataLen(0),
m_pStream(0),
m_URL(new char[PL_strlen(i_url)+1])
{
Init();
PR_ASSERT(i_url);
PL_strncpyz(m_URL, i_url, PL_strlen(i_url)+1);
*m_Charset = '\0';
*m_ContentEncoding = '\0';
*m_ContentType = '\0';
*m_Etag = '\0';
*m_Filename = '\0';
*m_PageServicesURL = '\0';
*m_PostData = '\0';
NS_INIT_ISUPPORTS() ;
PR_AtomicIncrement(&gInstanceCnt) ;
}
NS_IMPL_ISUPPORTS(nsCacheObject, nsCOMTypeInfo<nsICacheObject>::GetIID( )) ;
NS_IMETHODIMP
nsCacheObject::SetAddress(const char* i_url)
{
PR_ASSERT(i_url && *i_url);
if (!i_url)
return NS_ERROR_NULL_POINTER ;
if (m_URL)
delete[] m_URL;
int len = PL_strlen(i_url);
m_URL = new char[len + 1];
PL_strncpyz(m_URL, i_url, len+1);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::SetCharset(const char* i_Charset)
{
// PR_ASSERT(i_Charset && *i_Charset);
if (!i_Charset) //TODO reset m_charset here
return NS_ERROR_NULL_POINTER ;
if (m_Charset)
delete[] m_Charset;
int len = PL_strlen(i_Charset);
m_Charset = new char[len + 1];
PL_strncpyz(m_Charset, i_Charset, len+1);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::SetContentEncoding(const char* i_Encoding)
{
// PR_ASSERT(i_Encoding && *i_Encoding);
if (!i_Encoding)
return NS_ERROR_NULL_POINTER ;
if (m_ContentEncoding)
delete[] m_ContentEncoding;
int len = PL_strlen(i_Encoding);
m_ContentEncoding = new char[len + 1];
PL_strncpyz(m_ContentEncoding, i_Encoding, len+1);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::SetContentType(const char* i_Type)
{
// PR_ASSERT(i_Type && *i_Type);
if (!i_Type)
{
/* Reset to empty */ // TODO ??
return NS_ERROR_NULL_POINTER ;
}
if (m_ContentType)
delete[] m_ContentType;
int len = PL_strlen(i_Type);
m_ContentType = new char[len + 1];
PL_strncpyz(m_ContentType, i_Type, len+1);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::SetEtag(const char* i_etag)
{
// PR_ASSERT(i_etag && *i_etag);
if (!i_etag)
return NS_ERROR_NULL_POINTER ;
if (m_Etag)
delete[] m_Etag;
m_Etag = new char[PL_strlen(i_etag) + 1];
PL_strncpyz(m_Etag, i_etag, PL_strlen(i_etag)+1);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::SetFilename(const char* i_Filename)
{
// PR_ASSERT(i_Filename && *i_Filename);
if (!i_Filename)
return NS_ERROR_NULL_POINTER ;
if (m_Filename)
delete[] m_Filename;
int len = PL_strlen(i_Filename);
m_Filename = new char[len +1];
PL_strncpyz(m_Filename, i_Filename, len+1);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::GetInfo(void** o_info)
{
if (!o_info)
return NS_ERROR_NULL_POINTER ;
if (m_pInfo) {
*o_info = m_pInfo;
return NS_OK ;
}
nsCacheObject* pThis = (nsCacheObject*) this;
if (m_URL){
pThis->m_info_size = sizeof(nsCacheObject);
pThis->m_info_size -= sizeof(void*); // m_info itself is not being serialized
pThis->m_info_size -= sizeof(char*); // neither is m_PostData
pThis->m_info_size -= sizeof(nsStream*); // nor the stream
pThis->m_info_size -= sizeof(PRBool); // bIsCompleted.
//todo -optimize till here
//Add the strings sizes
pThis->m_info_size += PL_strlen(m_Charset)+1;
pThis->m_info_size += PL_strlen(m_ContentEncoding)+1;
pThis->m_info_size += PL_strlen(m_ContentType)+1;
pThis->m_info_size += PL_strlen(m_Etag)+1;
pThis->m_info_size += PL_strlen(m_Filename)+1;
pThis->m_info_size += PL_strlen(m_PageServicesURL)+1;
pThis->m_info_size += PL_strlen(m_URL)+1;
//Add the Postdata len
pThis->m_info_size += m_PostDataLen+1;
//For the virtual function table. This is really nasty, yixiong
pThis->m_info_size -= sizeof(void*) ;
void* new_obj = PR_Calloc(1, m_info_size * sizeof(char));
if (!new_obj)
{
PR_Free(new_obj);
return NS_ERROR_OUT_OF_MEMORY ;
}
PRUint32 len;
char* cur_ptr = (char*) new_obj;
/* put the total size of the struct into
* the first field so that we have
* a cross check against corruption
*/
COPY_INT32((void *)cur_ptr, &m_info_size);
cur_ptr += sizeof(PRUint32);
/* put the version number of the structure
* format that we are using. By using a version
* string when writting we can support
* backwards compatibility in our reading code
*/
COPY_INT32((void *)cur_ptr, &kCACHE_VERSION);
cur_ptr += sizeof(PRUint32);
STUFF_STRING(m_Charset);
STUFF_STRING(m_ContentEncoding);
STUFF_NUMBER(m_ContentLength);
STUFF_STRING(m_ContentType);
STUFF_STRING(m_Etag);
STUFF_TIME(m_Expires);
STUFF_STRING(m_Filename);
STUFF_NUMBER(m_Hits);
STUFF_TIME(m_LastAccessed);
STUFF_TIME(m_LastModified);
STUFF_NUMBER(m_Module);
STUFF_STRING(m_PageServicesURL);
STUFF_NUMBER(m_PostDataLen);
/* There is a possibility of it not being a string! */
if (m_PostData)
{
// 4 bytes missing, yixiong
memcpy(cur_ptr, m_PostData, m_PostDataLen+1);
cur_ptr += m_PostDataLen+1;
}
STUFF_NUMBER(m_Size);
STUFF_NUMBER(m_State);
STUFF_STRING(m_URL);
// Important Assertion. Dont remove!
// If this fails then you or somebody has added a variable to the
// nsCacheObject class and a decision on its "cacheability" has
// not yet been made.
PR_ASSERT(cur_ptr == (char*) new_obj + m_info_size);
pThis->m_pInfo = new_obj;
*o_info = pThis->m_pInfo ;
}
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::SetInfo(void* i_data)
{
if (!i_data)
return NS_ERROR_NULL_POINTER ;
char* cur_ptr = (char*) i_data;
//Reset the m_pInfo;
if (m_pInfo)
{
PR_Free(m_pInfo);
m_pInfo = 0;
}
//Reset all strings
if (m_Charset)
delete[] m_Charset;
if (m_ContentEncoding)
delete[] m_ContentEncoding;
if (m_ContentType)
delete[] m_ContentType;
if (m_Etag)
delete[] m_Etag;
if (m_Filename)
delete[] m_Filename;
if (m_PageServicesURL)
delete[] m_PageServicesURL;
if (m_URL)
delete[] m_URL;
if (m_PostData)
delete[] m_PostData;
m_PostDataLen = 0;
COPY_INT32(&m_info_size, cur_ptr);
char* max_ptr = cur_ptr + m_info_size;
cur_ptr += sizeof(PRUint32);
PRUint32 version;
COPY_INT32(&version, cur_ptr);
cur_ptr += sizeof(PRUint32);
PR_ASSERT(version == kCACHE_VERSION);
if (version != kCACHE_VERSION)
{
//TODO Bad cache version
return NS_ERROR_FAILURE ;
}
PRUint32 len;
RETRIEVE_STRING(m_Charset);
RETRIEVE_STRING(m_ContentEncoding);
RETRIEVE_NUMBER(m_ContentLength);
RETRIEVE_STRING(m_ContentType);
RETRIEVE_STRING(m_Etag);
RETRIEVE_TIME(m_Expires);
RETRIEVE_STRING(m_Filename);
RETRIEVE_NUMBER(m_Hits);
RETRIEVE_TIME(m_LastAccessed);
RETRIEVE_TIME(m_LastModified);
RETRIEVE_NUMBER(m_Module);
RETRIEVE_STRING(m_PageServicesURL);
RETRIEVE_NUMBER(m_PostDataLen);
// Special case-
m_PostData = new char[m_PostDataLen + 1];
if (m_PostData)
{
memcpy(m_PostData, cur_ptr, m_PostDataLen+1);
}
cur_ptr += m_PostDataLen +1;
RETRIEVE_NUMBER(m_Size);
RETRIEVE_NUMBER(m_State);
RETRIEVE_STRING(m_URL);
// Most important assertion! Don't ever remove!
PR_ASSERT(cur_ptr == max_ptr);
// Since we are reading off its info from an indexed entry
m_bIsCompleted = PR_TRUE;
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::GetInfoSize(PRUint32 *o_size)
{
if (!m_pInfo)
{
GetInfo(&m_pInfo);
}
*o_size = m_info_size;
return NS_OK ;
}
void nsCacheObject::Init()
{
m_Size = 0;
m_Expires = PR_IntervalNow() + DEFAULT_EXPIRES;
m_Hits = 0;
}
NS_IMETHODIMP
nsCacheObject::SetPageServicesURL(const char* i_Url)
{
// PR_ASSERT(i_Url && *i_Url);
if (!i_Url)
return NS_ERROR_NULL_POINTER ;
if (m_PageServicesURL)
delete[] m_PageServicesURL;
m_PageServicesURL = new char[PL_strlen(i_Url) + 1];
PL_strncpyz(m_PageServicesURL, i_Url, PL_strlen(i_Url)+1);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::SetPostData(const char* i_data, const PRUint32 i_Len)
{
if (!i_data || (0 ==i_Len))
return NS_ERROR_NULL_POINTER ;
if (m_PostData)
delete[] m_PostData;
m_PostData = new char[i_Len+1];
PL_strncpyz(m_PostData, i_data, i_Len+1);
m_PostDataLen = i_Len;
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::Read(char* o_Buffer, PRUint32 len, PRUint32 * pLeng)
{
nsresult rv ;
if (!m_pStream)
{
PR_ASSERT(m_Module >=0);
if (0 <= m_Module)
{
nsICacheModule* pModule ;
nsICacheManager* cacheManager ;
rv = nsServiceManager::GetService(kCacheManagerCID,
kICACHEMANAGERIID,
(nsISupports **)&cacheManager) ;
rv = cacheManager->GetModule(m_Module, &pModule);
if (NS_SUCCEEDED(rv) && pModule)
{
rv = pModule->GetStreamFor(this, &m_pStream);
if (NS_SUCCEEDED(rv) && m_pStream)
{
*pLeng = m_pStream->Read(o_Buffer, len);
return NS_OK ;
}
}
}
return NS_ERROR_FAILURE ;
}
*pLeng = m_pStream->Read(o_Buffer, len);
return NS_OK ;
}
NS_IMETHODIMP
nsCacheObject::Reset(void)
{
if (m_pStream)
m_pStream->Reset();
// TODO change states too.
return NS_OK ;
}
#if 0
/* Caller must free returned string */
// TODO change to use PR_stuff...
const char* nsCacheObject::Trace() const
{
char linebuffer[256];
char* total;
PR_Sprintf(linebuffer, "nsCacheObject:URL=%s,SIZE=%d,ET=%s,\n\tLM=%d,LA=%d,EXP=%d,HITS=%d\n",
m_URL,
m_Size,
m_Etag,
m_LastModified,
m_LastAccessed,
m_Expires,
m_Hits);
total = new char[PL_strlen(linebuffer) +1];
PL_strcpy(total, linebuffer);
return total;
}
#endif
NS_IMETHODIMP
nsCacheObject::Write(const char* i_Buffer, const PRUint32 len, PRUint32 * oLeng)
{
nsresult rv ;
if (!oLeng)
return NS_ERROR_NULL_POINTER ;
PRUint32 amountWritten = 0;
if (!m_pStream)
{
PR_ASSERT(m_Module >=0);
if (0 <= m_Module)
{
nsICacheModule* pModule ;
nsICacheManager* cacheManager ;
rv = nsServiceManager::GetService(kCacheManagerCID,
kICACHEMANAGERIID,
(nsISupports **)&cacheManager) ;
rv = cacheManager->GetModule(m_Module, &pModule);
if (NS_SUCCEEDED(rv) && pModule)
{
rv = pModule->GetStreamFor(this, &m_pStream);
PR_ASSERT(m_pStream);
if (!m_pStream)
return NS_ERROR_FAILURE ;
}
}
else
return NS_ERROR_FAILURE ;
}
amountWritten = m_pStream->Write(i_Buffer, len);
m_Size += amountWritten;
*oLeng = amountWritten;
return NS_OK ;
}
nsCacheObjectFactory::nsCacheObjectFactory ()
{
NS_INIT_ISUPPORTS();
PR_AtomicIncrement(&gInstanceCnt);
}
nsCacheObjectFactory::~nsCacheObjectFactory ()
{
PR_AtomicDecrement(&gInstanceCnt);
}
/*
NS_IMETHODIMP
nsCacheObjectFactory::QueryInterface(const nsIID &aIID, void **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsISupports*,this);
} else if (aIID.Equals(kIFactoryIID)) {
*aResult = NS_STATIC_CAST(nsISupports*,NS_STATIC_CAST(nsIFactory*,this));
} else {
*aResult = nsnull;
return NS_ERROR_NO_INTERFACE;
}
NS_ADDREF(NS_REINTERPRET_CAST(nsISupports*,*aResult));
return NS_OK;
}
NS_IMPL_ADDREF(nsCacheObjectFactory)
NS_IMPL_RELEASE(nsCacheObjectFactory)
*/
NS_IMPL_ISUPPORTS(nsCacheObjectFactory, kIFactoryIID) ;
NS_IMETHODIMP
nsCacheObjectFactory::CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
*aResult = nsnull;
nsISupports *inst = new nsCacheObject();
if (!inst) {
return NS_ERROR_OUT_OF_MEMORY;
}
// All XPCOM methods return nsresult
nsresult rv = inst->QueryInterface(aIID, aResult);
// There are handy macros, NS_SUCCEEDED and NS_FAILED
// to test the return value of an XPCOM method.
if (NS_FAILED(rv)) {
// We didn't get the right interface, so clean up
delete inst;
}
return rv;
}
NS_IMETHODIMP
nsCacheObjectFactory::LockFactory(PRBool aLock)
{
if (aLock) {
PR_AtomicIncrement(&gLockCnt);
} else {
PR_AtomicDecrement(&gLockCnt);
}
return NS_OK;
}
/////////////////////////////////////////////////////////////////////
// Exported functions. With these in place we can compile
// this module into a dynamically loaded and registered
// component.
static NS_DEFINE_CID(kCacheObjectCID, NS_CACHEOBJECT_CID);
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
// The "name" of our component
static const char* g_desc = "Cache Object XPCOM Module";
extern "C" NS_EXPORT nsresult
NSGetFactory(nsISupports *serviceMgr,
const nsCID &aCID,
const char *aClassName,
const char *aProgID,
nsIFactory **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
*aResult = nsnull;
nsISupports *inst;
if (aCID.Equals(kCacheObjectCID)) {
// Ok, we know this CID and here is the factory
// that can manufacture the objects
inst = new nsCacheObjectFactory();
} else {
return NS_ERROR_NO_INTERFACE;
}
if (!inst)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = inst->QueryInterface(kIFactoryIID,
(void **) aResult);
if (NS_FAILED(rv)) {
delete inst;
}
return rv;
}
extern "C" NS_EXPORT PRBool
NSCanUnload(nsISupports* serviceMgr)
{
return PRBool(gInstanceCnt == 0 && gLockCnt == 0);
}
extern "C" NS_EXPORT nsresult
NSRegisterSelf(nsISupports *aServMgr, const char *path)
{
nsresult rv = NS_OK;
// We will use the service manager to obtain the component
// manager, which will enable us to register a component
// with a ProgID (text string) instead of just the CID.
nsIServiceManager *sm;
// We can get the IID of an interface with the static GetIID() method as
// well.
rv = aServMgr->QueryInterface(nsIServiceManager::GetIID(), (void **)&sm);
if (NS_FAILED(rv))
return rv;
nsIComponentManager *cm;
rv = sm->GetService(kComponentManagerCID, nsIComponentManager::GetIID(), (nsISupports **)&cm);
if (NS_FAILED(rv)) {
NS_RELEASE(sm);
return rv;
}
// Note the text string, we can access the hello component with just this
// string without knowing the CID
rv = cm->RegisterComponent(kCacheObjectCID, g_desc, "component://cacheobject",
path, PR_TRUE, PR_TRUE);
sm->ReleaseService(kComponentManagerCID, cm);
NS_RELEASE(sm);
#ifdef NS_DEBUG
printf("*** %s registered\n",g_desc);
#endif
return rv;
}
extern "C" NS_EXPORT nsresult
NSUnregisterSelf(nsISupports* aServMgr, const char *path)
{
nsresult rv = NS_OK;
nsIServiceManager *sm;
rv = aServMgr->QueryInterface(nsIServiceManager::GetIID(), (void **)&sm);
if (NS_FAILED(rv))
return rv;
nsIComponentManager *cm;
rv = sm->GetService(kComponentManagerCID, nsIComponentManager::GetIID(), (nsISupports **)&cm);
if (NS_FAILED(rv)) {
NS_RELEASE(sm);
return rv;
}
rv = cm->UnregisterComponent(kCacheObjectCID, path);
sm->ReleaseService(kComponentManagerCID, cm);
NS_RELEASE(sm);
return rv;
}

View File

@ -1,46 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = cachepref
LIBRARY_NAME = cachepref
IS_COMPONENT = 1
CPPSRCS = nsCachePref.cpp
REQUIRES = nspr
LOCAL_INCLUDES = \
-I$(srcdir)/../include \
-I$(srcdir)/../public \
-I$(PUBLIC)/netlib \
$(NULL)
EXTRA_LIBS = $(NSPR_LIBS)
include $(topsrcdir)/config/rules.mk

View File

@ -1,512 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef XP_UNIX
#include "xp.h" // This complains on unix. Works ok without there.
#endif
//#include "prefapi.h"
#include "nsIPref.h"
#include "prmem.h"
#include "prprf.h"
#include "nsICacheManager.h"
#include "plstr.h"
#if defined(XP_PC)
#include <direct.h>
#endif /* XP_PC */
#include "nspr.h"
#include "nscore.h"
#include "nsRepository.h"
#include "nsIFactory.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#ifdef XP_MAC
#include "uprefd.h"
#endif
#include "nsCachePref.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kICachePrefIID, NS_ICACHEPREF_IID);
static NS_DEFINE_IID(kCachePrefCID, NS_CACHEPREF_CID);
static NS_DEFINE_IID(kICACHEMANAGERIID, NS_ICACHEMANAGER_IID);
static NS_DEFINE_IID(kCacheManagerCID, NS_CACHEMANAGER_CID);
static NS_DEFINE_IID(knsPrefCID, NS_PREF_CID);
static NS_DEFINE_IID(kInsPrefIID, NS_IPREF_IID);
static const PRUint32 MEM_CACHE_SIZE_DEFAULT = 1024*1024;
static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*MEM_CACHE_SIZE_DEFAULT;
static const PRUint32 BKG_THREAD_SLEEP = 15*60; /*in seconds, 15 minutes */
static const PRUint16 BUGS_FOUND_SO_FAR = 0;
//Preferences
static const char * const MEM_CACHE_PREF = "browser.cache.memory_cache_size";
static const char * const DISK_CACHE_PREF = "browser.cache.disk_cache_size";
static const char * const CACHE_DIR_PREF = "browser.cache.directory";
static const char * const FREQ_PREF = "browser.cache.check_doc_frequency";
//Not implemented as yet...
static const char * const BKG_CLEANUP = "browser.cache.cleanup_period"; //Default for BKG_THREAD_SLEEP
/* Find a bug in NU_CACHE, get these many chocolates */
static const PRUint16 CHOCOLATES_PER_BUG_FOUND = 2^BUGS_FOUND_SO_FAR;
static int PR_CALLBACK Cache_PrefChangedFunc(const char *pref, void *data);
static PRInt32 gInstanceCnt = 0 ;
static PRInt32 gLockCnt = 0 ;
nsCachePref::nsCachePref(void):
m_RefreshFreq(ONCE) ,
m_MemCacheSize(MEM_CACHE_SIZE_DEFAULT),
m_DiskCacheSize(DISK_CACHE_SIZE_DEFAULT),
m_DiskCacheDBFilename(new char[6+1]),
m_DiskCacheFolder(0),
m_BkgSleepTime(BKG_THREAD_SLEEP)
{
nsIPref * pref=nsnull ;
nsresult rv = nsServiceManager::GetService(knsPrefCID,
kInsPrefIID,
(nsISupports **)&pref) ;
rv = pref->RegisterCallback("browser.cache",Cache_PrefChangedFunc,0);
m_DiskCacheDBFilename = "nufat.db" ;
SetupPrefs(0);
NS_INIT_ISUPPORTS() ;
PR_AtomicIncrement(&gInstanceCnt) ;
}
nsCachePref::~nsCachePref()
{
if (m_DiskCacheFolder)
{
delete m_DiskCacheFolder;
m_DiskCacheFolder = 0;
}
PR_AtomicDecrement(&gInstanceCnt) ;
}
//Read all the stuff from pref here.
NS_IMETHODIMP
nsCachePref::SetupPrefs(const char* i_Pref)
{
PRBool bSetupAll = PR_FALSE;
PRInt32 nTemp;
char* tempPref=0;
if (!i_Pref)
bSetupAll = PR_TRUE;
nsIPref * pref ;
nsServiceManager::GetService(knsPrefCID,
kInsPrefIID,
(nsISupports **)&pref) ;
if (bSetupAll || !PL_strcmp(i_Pref,MEM_CACHE_PREF))
{
if (NS_SUCCEEDED(pref->GetIntPref(MEM_CACHE_PREF,&nTemp)) ) {
m_MemCacheSize = 1024*nTemp;
}
else {
m_MemCacheSize = MEM_CACHE_SIZE_DEFAULT;
}
}
if (bSetupAll || !PL_strcmp(i_Pref,DISK_CACHE_PREF))
{
if (NS_SUCCEEDED(pref->GetIntPref(DISK_CACHE_PREF,&nTemp)))
m_DiskCacheSize = 1024*nTemp;
else
m_DiskCacheSize = DISK_CACHE_SIZE_DEFAULT;
}
if (bSetupAll || !PL_strcmp(i_Pref,FREQ_PREF))
{
if (NS_SUCCEEDED(pref->GetIntPref(FREQ_PREF,&nTemp)))
{
m_RefreshFreq = (nsCachePref::Refresh)nTemp;
}
else
m_RefreshFreq = ONCE;
}
if (bSetupAll || !PL_strcmp(i_Pref,CACHE_DIR_PREF))
{
/* the CopyPathPref is not in nsIPref, is CopyCharPref ok? -xyz */
nsresult rv = pref->CopyCharPref(CACHE_DIR_PREF,&tempPref) ;
if (NS_SUCCEEDED(rv))
{
PR_ASSERT(tempPref);
delete [] m_DiskCacheFolder;
m_DiskCacheFolder = new char[PL_strlen(tempPref)+2];
if (!m_DiskCacheFolder)
{
if (tempPref)
PR_Free(tempPref);
return NS_OK ;
}
PL_strcpy(m_DiskCacheFolder, tempPref);
}
else //TODO set to temp folder
{
#if defined(XP_PC)
char tmpBuf[_MAX_PATH];
PRFileInfo dir;
PRStatus status;
char *cacheDir = new char [_MAX_PATH];
if (!cacheDir)
return NS_OK;
cacheDir = _getcwd(cacheDir, _MAX_PATH);
// setup the cache dir.
PL_strcpy(tmpBuf, cacheDir);
sprintf(cacheDir,"%s%s%s%s", tmpBuf, "\\", "cache", "\\");
status = PR_GetFileInfo(cacheDir, &dir);
if (PR_FAILURE == status) {
// Create the dir.
status = PR_MkDir(cacheDir, 0600);
if (PR_SUCCESS != status) {
m_DiskCacheFolder = new char[1];
*m_DiskCacheFolder = '\0';
return NS_OK;
}
}
m_DiskCacheFolder = cacheDir;
#endif /* XP_PC */
delete [] m_DiskCacheFolder;
m_DiskCacheFolder = new char[5] ;
PL_strcpy(m_DiskCacheFolder, "/tmp") ;
}
}
if (tempPref)
PR_Free(tempPref);
return NS_OK ;
}
NS_IMETHODIMP
nsCachePref::GetBkgSleepTime(PRUint32* o_time)
{
*o_time = BKG_THREAD_SLEEP;
return NS_OK ;
}
NS_IMETHODIMP
nsCachePref::GetDiskCacheDBFilename(char** o_name)
{
*o_name = "nufat.db";
return NS_OK ;
}
nsICachePref*
nsCachePref::GetInstance()
{
nsICacheManager * cachemanager ;
nsICachePref * cachepref ;
nsresult rv = nsServiceManager::GetService(kCacheManagerCID,
kICACHEMANAGERIID,
(nsISupports **) &cachemanager) ;
rv = cachemanager->GetPrefs(&cachepref);
return cachepref ;
}
/*
nsrefcnt nsCachePref::AddRef(void)
{
return ++m_RefCnt;
}
nsrefcnt nsCachePref::Release(void)
{
if (--m_RefCnt == 0)
{
delete this;
return 0;
}
return m_RefCnt;
}
nsresult nsCachePref::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
return NS_OK;
}
*/
NS_IMPL_ISUPPORTS(nsCachePref, nsCOMTypeInfo<nsICachePref>::GetIID() ) ;
int PR_CALLBACK Cache_PrefChangedFunc(const char *pref, void *data) {
// nsCachePref::GetInstance()->SetupPrefs(pref);
nsICachePref* cachepref ;
nsresult rv = nsServiceManager::GetService(kCachePrefCID,
kICachePrefIID,
(nsISupports **)&cachepref) ;
if (NS_FAILED(rv))
return PR_FALSE ;
else
{
cachepref->SetupPrefs(pref) ;
return PR_TRUE;
}
}
/////////////////////////////////////////////////////////////////////
// Exported functions. With these in place we can compile
// this module into a dynamically loaded and registered
// component.
//static NS_DEFINE_CID(kCacheObjectCID, NS_CACHEOBJECT_CID);
/*
#include "nsIFactory.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nspr.h"
#include "nscore.h"
#include "nsRepository.h"
#include "nsICacheManager.h"
#include "nsICachePref.h"
#include "nsCachePref.h"
*/
// static NS_DEFINE_IID(kICachePrefIID, NS_ICACHEPREF_IID);
//static NS_DEFINE_IID(kCachePrefCID, NS_CACHEPREF_CID);
static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID);
// static NS_DEFINE_IID(kICACHEMANAGERIID, NS_ICACHEMANAGER_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
// The "name" of our component
static const char* g_desc = "Cache Prefrence XPCOM Module";
nsCachePrefFactory::nsCachePrefFactory ()
{
NS_INIT_ISUPPORTS();
PR_AtomicIncrement(&gInstanceCnt);
}
nsCachePrefFactory::~nsCachePrefFactory ()
{
PR_AtomicDecrement(&gInstanceCnt);
}
/*
NS_IMETHODIMP
nsCacheObjectFactory::QueryInterface(const nsIID &aIID, void **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsISupports*,this);
} else if (aIID.Equals(kIFactoryIID)) {
*aResult = NS_STATIC_CAST(nsISupports*,NS_STATIC_CAST(nsIFactory*,this));
} else {
*aResult = nsnull;
return NS_ERROR_NO_INTERFACE;
}
NS_ADDREF(NS_REINTERPRET_CAST(nsISupports*,*aResult));
return NS_OK;
}
NS_IMPL_ADDREF(nsCacheObjectFactory)
NS_IMPL_RELEASE(nsCacheObjectFactory)
*/
NS_IMPL_ISUPPORTS(nsCachePrefFactory, kIFactoryIID) ;
NS_IMETHODIMP
nsCachePrefFactory::CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
*aResult = nsnull;
nsISupports *inst = new nsCachePref();
if (!inst) {
return NS_ERROR_OUT_OF_MEMORY;
}
// All XPCOM methods return nsresult
nsresult rv = inst->QueryInterface(aIID, aResult);
// There are handy macros, NS_SUCCEEDED and NS_FAILED
// to test the return value of an XPCOM method.
if (NS_FAILED(rv)) {
// We didn't get the right interface, so clean up
delete inst;
}
return rv;
}
NS_IMETHODIMP
nsCachePrefFactory::LockFactory(PRBool aLock)
{
if (aLock) {
PR_AtomicIncrement(&gLockCnt);
} else {
PR_AtomicDecrement(&gLockCnt);
}
return NS_OK;
}
extern "C" NS_EXPORT nsresult
NSGetFactory(nsISupports *serviceMgr,
const nsCID &aCID,
const char *aClassName,
const char *aProgID,
nsIFactory **aResult)
{
if (!aResult)
return NS_ERROR_NULL_POINTER;
*aResult = nsnull;
nsISupports *inst;
if (aCID.Equals(kCachePrefCID)) {
// Ok, we know this CID and here is the factory
// that can manufacture the objects
inst = new nsCachePrefFactory();
} else {
return NS_ERROR_NO_INTERFACE;
}
if (!inst)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = inst->QueryInterface(kIFactoryIID,
(void **) aResult);
if (NS_FAILED(rv)) {
delete inst;
}
return rv;
}
extern "C" NS_EXPORT PRBool
NSCanUnload(nsISupports* serviceMgr)
{
return PRBool(gInstanceCnt == 0 && gLockCnt == 0);
}
extern "C" NS_EXPORT nsresult
NSRegisterSelf(nsISupports *aServMgr, const char *path)
{
nsresult rv = NS_OK;
// We will use the service manager to obtain the component
// manager, which will enable us to register a component
// with a ProgID (text string) instead of just the CID.
nsIServiceManager *sm;
// We can get the IID of an interface with the static GetIID() method as
// well.
rv = aServMgr->QueryInterface(nsIServiceManager::GetIID(), (void **)&sm);
if (NS_FAILED(rv))
return rv;
nsIComponentManager *cm;
rv = sm->GetService(kComponentManagerCID, nsIComponentManager::GetIID(), (nsISupports **)&cm);
if (NS_FAILED(rv)) {
NS_RELEASE(sm);
return rv;
}
// Note the text string, we can access the hello component with just this
// string without knowing the CID
rv = cm->RegisterComponent(kCachePrefCID, g_desc, "component://cachePref",
path, PR_TRUE, PR_TRUE);
sm->ReleaseService(kComponentManagerCID, cm);
NS_RELEASE(sm);
#ifdef NS_DEBUG
printf("*** %s registered\n",g_desc);
#endif
return rv;
}
extern "C" NS_EXPORT nsresult
NSUnregisterSelf(nsISupports* aServMgr, const char *path)
{
nsresult rv = NS_OK;
nsIServiceManager *sm;
rv = aServMgr->QueryInterface(nsIServiceManager::GetIID(), (void **)&sm);
if (NS_FAILED(rv))
return rv;
nsIComponentManager *cm;
rv = sm->GetService(kComponentManagerCID, nsIComponentManager::GetIID(), (nsISupports **)&cm);
if (NS_FAILED(rv)) {
NS_RELEASE(sm);
return rv;
}
rv = cm->UnregisterComponent(kCachePrefCID, path);
sm->ReleaseService(kComponentManagerCID, cm);
NS_RELEASE(sm);
return rv;
}

View File

@ -19,7 +19,7 @@
#
# Contributor(s):
MODULE = netcache
MODULE = nkcache
DEPTH = ..\..\..
include <$(DEPTH)/config/config.mak>

View File

@ -1,112 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
* nsCacheModule. A class that defines the way a cache module
* should be written. Its the super class for any new modules.
* Two sample modules derived from this one are nsMemModule and nsDiskModule.
*
* Gagan Saksena 02/03/98
*
*/
#ifndef nsICacheModule_h__
#define nsICacheModule_h__
#include <nsISupports.h>
#include "nsICacheObject.h"
#include "nsEnumeration.h"
// {5D51B24F-E6C2-11d1-AFE5-006097BFC036}
#define NS_ICACHEMODULE_IID \
{ 0x5d51b24f, 0xe6c2, 0x11d1, \
{ 0xaf, 0xe5, 0x0, 0x60, 0x97, 0xbf, 0xc0, 0x36 } };
class nsICacheModule : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR (NS_ICACHEMODULE_IID);
NS_IMETHOD AddObject(nsICacheObject* i_pObject) = 0;
NS_IMETHOD ContainsURL(const char* i_url, PRBool* o_bContain) = 0;
NS_IMETHOD ContainsCacheObj(nsICacheObject* i_pObject, PRBool* o_bContain) = 0;
NS_IMETHOD Enable (PRBool i_bEnable) = 0;
NS_IMETHOD GetNumOfEntries (PRUint32* o_nEntries) = 0;
NS_IMETHOD GetEnumerator (nsEnumeration** o_enum) = 0;
/* Enumerations with a function pointer - TODO */
//TODO move to own interface for both Garbage Collection and Revalidation
NS_IMETHOD GarbageCollect (void) = 0;
NS_IMETHOD GetObjectByURL (const char* i_url, nsICacheObject** o_pObj) = 0;
NS_IMETHOD GetObjectByIndex (const PRUint32 i_index, nsICacheObject** o_pObj) = 0;
NS_IMETHOD GetStreamFor (const nsICacheObject* i_pObject, nsStream** o_pStream) = 0;
NS_IMETHOD IsEnabled (PRBool* o_bEnabled) = 0;
/* Can't do additions, deletions, validations, expirations */
NS_IMETHOD IsReadOnly (PRBool* o_bReadOnly) = 0;
NS_IMETHOD GetNextModule (nsICacheModule** o_pCacheModule) = 0;
NS_IMETHOD SetNextModule (nsICacheModule* i_pCacheModule) = 0;
NS_IMETHOD RemoveByURL (const char* i_url) = 0;
NS_IMETHOD RemoveByIndex (const PRUint32 i_index) = 0;
NS_IMETHOD RemoveByObject (nsICacheObject* i_pObject) = 0;
NS_IMETHOD RemoveAll (void) = 0;
NS_IMETHOD Revalidate (void) = 0;
NS_IMETHOD ReduceSizeTo (const PRUint32 i_newsize) = 0;
NS_IMETHOD GetSize (PRUint32* o_size) = 0;
NS_IMETHOD SetSize (const PRUint32 i_size) = 0;
NS_IMETHOD GetSizeInUse (PRUint32* o_size) = 0;
};
// {5D51B24E-E6C1-11d0-AFE5-006097BFC036}
#define NS_DISKMODULE_CID \
{ 0x5d51b24e, 0xe6c1, 0x11d0, \
{ 0xaf, 0xe5, 0x0, 0x60, 0x97, 0xbf, 0xc0, 0x36 } };
// {5D51B250-E6C2-11d1-AFE5-006097BFC036}
#define NS_MEMMODULE_CID \
{ 0x5d51b250, 0xe6c2, 0x11d1, \
{ 0xaf, 0xe5, 0x0, 0x60, 0x97, 0xbf, 0xc0, 0x36 } };
#endif

View File

@ -1,94 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/* nsICachePref. A class to separate the preference related code to
* one place. This is an incomplete implementation, I need to access
* the libprefs directly, but that would add another dependency. And
* libpref comes with a JS dependency... so holding this off for the
* moment.
*
* -Gagan Saksena 09/15/98
*/
#ifndef nsICachePref_h__
#define nsICachePref_h__
#include "nsISupports.h"
#include "prtypes.h"
#include "prlog.h"
// {7C3ED031-45E4-11d3-9B7F-0004ACB74CEC}
#define NS_ICACHEPREF_IID \
{ 0x7c3ed031, 0x45e4, 0x11d3, \
{ 0x9b, 0x7f, 0x0, 0x4, 0xac, 0xb7, 0x4c, 0xec } };
// myCachePrefCID {99E9C911-46D9-11d3-87EF-000629D01344}
#define NS_CACHEPREF_CID \
{ 0x99e9c911, 0x46d9, 0x11d3, \
{ 0x87, 0xef, 0x0, 0x6, 0x29, 0xd0, 0x13, 0x44}} ;
class nsICachePref : public nsISupports
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR (NS_ICACHEPREF_IID);
// Was "static nsCachePref* GetInstance(void)"
// Do I need this GetInstance??????
// NS_IMETHOD GetInstance(nsICachePref** o_pICachePref ) = 0;
enum Refresh
{
ONCE,
ALWAYS,
NEVER
};
NS_IMETHOD GetBkgSleepTime (PRUint32* o_time) = 0;
NS_IMETHOD GetDiskCacheDBFilename (char** o_name) = 0; /* like Fat.db */
NS_IMETHOD GetDiskCacheFolder (char** o_folder) = 0; /* Cache dir */
NS_IMETHOD GetDiskCacheSSL (PRBool* o_bSet) = 0;
NS_IMETHOD SetDiskCacheSSL (PRBool i_bSet) = 0;
NS_IMETHOD GetDiskCacheSize (PRUint32* o_size) = 0;
NS_IMETHOD SetDiskCacheSize (const PRUint32 i_size) = 0;
NS_IMETHOD GetMemCacheSize (PRUint32 * o_size) = 0;
NS_IMETHOD SetMemCacheSize (const PRUint32 i_size) = 0;
NS_IMETHOD GetFrequency (nsICachePref::Refresh* o_frequency) = 0;
/* Revalidating in background, makes IMS calls in the bkg thread to
update cache entries. TODO, this should be at a bigger time period
than the cache cleanup routine */
NS_IMETHOD RevalidateInBkg (PRBool* i_bRevalidateInBkg) = 0;
/* Setup all prefs */
NS_IMETHOD SetupPrefs(const char* i_Pref) = 0;
};
#endif // nsICachePref_h__

View File

@ -80,7 +80,7 @@ interface nsICachedNetData : nsISupports
* cache did not complete normally and, therefore, the content may be
* truncated.
*/
readonly attribute boolean partial;
readonly attribute boolean partialFlag;
/**
* This flag can be set and cleared by a protocol handler as a form of
@ -90,6 +90,14 @@ interface nsICachedNetData : nsISupports
*/
attribute boolean updateInProgress;
/**
* inUse is set if any existing channels are associated with this cache
* entry or if the updateInProgess flag is set. This can be used to
* prevent writing to a cache entry by a protocol handler if it's being
* read or written elsewhere.
*/
readonly attribute boolean inUse;
/**
* Date/time that the document was last stored on the origin server, as
* supplied by the protocol handler. This value is used as input to the
@ -137,12 +145,24 @@ interface nsICachedNetData : nsISupports
readonly attribute PRUint16 numberAccesses;
/**
* Accessors for opaque protocol-specific meta-data which can be updated by
* the protocol handler for each cache entry, independently of the content
* data.
* Accessor methods for opaque meta-data which can be read and updated
* independently of the content data.
*
* The aTag argument can be used to accommodate multiple clients of the
* cache API, each of which wants to store its own private meta-data into
* the cache. For example, there could be a "headers" tag that the HTTP
* protocol handler uses to store http response headers and a "image size"
* tag used to store the image dimensions of a GIF file. The aData
* argument refers to an opaque blob of arbitrary bytes.
*
* IMPORTANT: If aData does not contain byte-oriented data, i.e. it's not a
* string, the contents of aData must be byte-swapped by the,
* caller, so as to make the cache files endian-independent.
*/
void getProtocolPrivate(out PRUint32 length, [size_is(length), retval] out string data);
void setProtocolPrivate(in PRUint32 length, [size_is(length)] in string data);
void getAnnotation(in string aTag,
out PRUint32 aLength, [size_is(aLength), retval] out string aData);
void setAnnotation(in string aTag,
in PRUint32 aLength, [size_is(aLength)] in string aData);
/**
* As a getter, return the number of content bytes stored in the cache,
@ -190,9 +210,12 @@ interface nsICachedNetData : nsISupports
*
* Though nsIChannel provides for both async and synchronous I/O APIs, both
* may not be implemented. Only AsyncRead() and OpenOutputStream() is
* required.
* required. The aProxyChannel argument allows another channel to be
* specified as the proffered argument to nsIStreamListener methods rather
* than the cache's own channel.
*/
nsIChannel newChannel(in nsILoadGroup loadGroup);
nsIChannel newChannel(in nsILoadGroup aLoadGroup,
in nsIChannel aProxyChannel);
/**
* This method can be used by a caching protocol handler to store data in
@ -201,5 +224,6 @@ interface nsICachedNetData : nsISupports
* method implicitly sets the updateInProgress flag, if it has not already
* been set.
*/
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener);
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
in PRUint32 aStartOffset);
};

View File

@ -116,11 +116,6 @@ interface nsINetDataCache : nsISupports
*/
attribute nsINetDataCache nextCache;
/**
* The maximum permitted size of the cache, in kB.
*/
readonly attribute PRUint32 capacity;
/**
* An estimate of the amount of storage occupied by the cache, in kB.
* Actual use may be slightly higher than reported due to cache overhead

View File

@ -27,6 +27,7 @@ interface nsICachedNetData;
interface nsINetDataCache;
interface nsINetDataDiskCache;
interface nsIURI;
interface nsIFileSpec;
/**
* The network-response cache manager is partly responsible for the caching of
@ -36,11 +37,7 @@ interface nsIURI;
*
* The cache manager supervises the actions of individual cache components,
* such as the memory cache, the disk cache and any extension caches, e.g. a
* read-only CD-ROM cache. It also manages the coalescing of multiple,
* simultaneous requests for the same URI. That is, if a cache entry fill is
* in progress while a second request is made for the same URI, the cache
* manager will seamlessly splice together the streams from the stored disk
* content and the content inbound from the network.
* read-only CD-ROM cache.
*
* @See nsINetDataCache
* @See nsICachedNetData
@ -90,7 +87,7 @@ interface nsINetDataCacheManager : nsISupports
* The optionally-NULL secondaryKey argument can be used, e.g. for form
* post data or for HTTP headers in the case of HTTP.
*/
nsICachedNetData getCachedNetData(in nsIURI uri,
nsICachedNetData getCachedNetData(in string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
@ -100,7 +97,7 @@ interface nsINetDataCacheManager : nsISupports
* only partial data is stored. The flags argument behaves the same as for
* the GetCachedNetData() method, above.
*/
boolean contains(in nsIURI uri,
boolean contains(in string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
@ -153,4 +150,14 @@ interface nsINetDataCacheManager : nsISupports
* accomodate the requested capacity.
*/
attribute PRUint32 memCacheCapacity;
/**
* This attribute must be set before attempting to store into the disk cache.
*/
attribute nsIFileSpec diskCacheFolder;
};
%{ C++
// ProgID prefix for Components that implement this interface
#define NS_NETWORK_CACHE_MANAGER_PROGID NS_NETWORK_CACHE_PROGID "?name=manager"
%}

View File

@ -1,32 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = xptest
include $(topsrcdir)/config/rules.mk

View File

@ -1,28 +0,0 @@
#!gmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..
DIRS= \
xptest \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@ -1,49 +0,0 @@
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
CPPSRCS = \
disktest.cpp \
memtest.cpp \
$(NULL)
SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=)
LIBS = \
-lpref \
-lmozjs \
-lxpcom \
$(ZLIB_LIBS) \
$(NSPR_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk
DEFINES += -DUSE_NSREG -DCACHE
LIBS_DIR += -L$(DIST)/bin/components
INCLUDES += -I$(srcdir)/../../public -I$(srcdir)/../../include -I..

View File

@ -1,57 +0,0 @@
#!nmake
#
# The contents of this file are subject to the Netscape 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/NPL/
#
# 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 mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
DEPTH=..\..\..\..
MAKE_OBJ_TYPE = EXE
PROG1 = .\$(OBJDIR)\disktest.exe
PROG2 = .\$(OBJDIR)\memtest.exe
PROGRAMS = $(PROG1) $(PROG2)
LCFLAGS=-DUSE_NSREG -GX -DCACHE
REQUIRES=libreg
INCS = -I..\..\public \
-I..\..\include \
$(INCS) \
-I$(DEPTH)\dist\include \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(LIBNSPR) \
!if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE)
LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib
!endif
include <$(DEPTH)\config\rules.mak>
install:: $(PROGRAMS)
-for %p in ($(PROGRAMS)) do $(MAKE_INSTALL) %p $(DIST)\bin
clobber::
-for %p in ($(PROGRAMS)) do $(RM) %p $(DIST)\bin\%p
$(PROG1): $(OBJDIR) disktest.cpp
$(PROG2): $(OBJDIR) memtest.cpp

View File

@ -1,816 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
The TestProtocols tests the basic protocols architecture and can
be used to test individual protocols as well. If this grows too
big then we should split it to individual protocols.
-Gagan Saksena 04/29/99
*/
/*
This program would actually create a cache file in your /tmp
directory. It would try to use the default name from URI. If
that name can not be found, it will use nucache. Also, a database
file (for indexing, I guess) named nufat.db would also be generated
in the same directory.
This is only a temporary solution. We are still waiting for the final
decision on which database to use.
-yixiong 08/10/99
*/
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#endif
#include "nspr.h"
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsIEventQueueService.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsIInputStream.h"
#include "nsIBufferInputStream.h"
#include "nsCRT.h"
#include "nsIChannel.h"
#include "nsIURL.h"
#include "nsIHTTPChannel.h"
#include "nsIHttpEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIDNSService.h"
#include "nsISimpleEnumerator.h"
#include "nsIHTTPHeader.h"
#include "nsXPIDLString.h"
#ifdef CACHE
#include "nsICacheManager.h"
#include "nsICacheObject.h"
#endif
// this test app handles cookies.
#include "nsICookieService.h"
static NS_DEFINE_CID(nsCookieServiceCID, NS_COOKIESERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#ifdef CACHE
static NS_DEFINE_IID(kICacheManagerIID, NS_ICACHEMANAGER_IID) ;
static NS_DEFINE_IID(kCacheManagerCID, NS_CACHEMANAGER_CID) ;
static NS_DEFINE_IID(kICacheObjectIID, NS_ICACHEOBJECT_IID) ;
static NS_DEFINE_CID(kCacheObjectCID, NS_CACHEOBJECT_CID);
#endif
//static PRTime gElapsedTime; // enable when we time it...
static int gKeepRunning = 0;
static PRBool gVerbose = PR_FALSE;
static nsIEventQueue* gEventQ = nsnull;
class URLLoadInfo : public nsISupports
{
public:
URLLoadInfo(const char* aUrl);
virtual ~URLLoadInfo();
// ISupports interface...
NS_DECL_ISUPPORTS
const char* Name() { return mURLString.GetBuffer(); }
PRInt32 mBytesRead;
PRTime mTotalTime;
PRTime mConnectTime;
nsString mURLString;
};
URLLoadInfo::URLLoadInfo(const char *aUrl) : mURLString(aUrl)
{
NS_INIT_REFCNT();
mBytesRead = 0;
mConnectTime = mTotalTime = PR_Now();
}
URLLoadInfo::~URLLoadInfo()
{
}
NS_IMPL_ISUPPORTS(URLLoadInfo,nsCOMTypeInfo<nsISupports>::GetIID());
class TestHTTPEventSink : public nsIHTTPEventSink
{
public:
TestHTTPEventSink();
virtual ~TestHTTPEventSink();
// ISupports interface...
NS_DECL_ISUPPORTS
// nsIHTTPEventSink interface...
NS_IMETHOD OnAwaitingInput(nsISupports* i_Context);
NS_IMETHOD OnHeadersAvailable(nsISupports* i_Context);
NS_IMETHOD OnProgress(nsISupports* i_Context,
PRUint32 i_Progress,
PRUint32 i_ProgressMax);
// OnRedirect gets fired only if you have set FollowRedirects on the handler!
NS_IMETHOD OnRedirect(nsISupports* i_Context,
nsIURI* i_NewLocation);
};
TestHTTPEventSink::TestHTTPEventSink()
{
NS_INIT_REFCNT();
}
TestHTTPEventSink::~TestHTTPEventSink()
{
}
NS_IMPL_ISUPPORTS(TestHTTPEventSink,nsCOMTypeInfo<nsIHTTPEventSink>::GetIID());
NS_IMETHODIMP
TestHTTPEventSink::OnAwaitingInput(nsISupports* context)
{
printf("\n+++ TestHTTPEventSink::OnAwaitingInput +++\n");
return NS_OK;
}
NS_IMETHODIMP
TestHTTPEventSink::OnHeadersAvailable(nsISupports* context)
{
nsCOMPtr<nsISimpleEnumerator> enumerator;
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(context));
PRBool bMoreHeaders;
printf("cachetest: 162, OnHeadersAvailable, \n") ;
if (pHTTPCon) {
pHTTPCon->GetRequestHeaderEnumerator(getter_AddRefs(enumerator));
printf("Request headers:\n");
enumerator->HasMoreElements(&bMoreHeaders);
while (bMoreHeaders) {
nsCOMPtr<nsISupports> item;
nsCOMPtr<nsIHTTPHeader> header;
enumerator->GetNext(getter_AddRefs(item));
header = do_QueryInterface(item);
if (header) {
nsCOMPtr<nsIAtom> key;
nsAutoString field(eOneByte);
nsXPIDLCString value;
header->GetField(getter_AddRefs(key));
key->ToString(field);
printf("\t%s: ", field.GetBuffer());
header->GetValue(getter_Copies(value));
printf("%s\n", (const char*)value);
}
enumerator->HasMoreElements(&bMoreHeaders);
}
pHTTPCon->GetResponseHeaderEnumerator(getter_AddRefs(enumerator));
printf("Response headers:\n");
enumerator->HasMoreElements(&bMoreHeaders);
while (bMoreHeaders) {
nsCOMPtr<nsISupports> item;
nsCOMPtr<nsIHTTPHeader> header;
enumerator->GetNext(getter_AddRefs(item));
header = do_QueryInterface(item);
if (header) {
nsCOMPtr<nsIAtom> key;
nsAutoString field(eOneByte);
nsXPIDLCString value;
header->GetField(getter_AddRefs(key));
key->ToString(field);
printf("\t%s: ", field.GetBuffer());
header->GetValue(getter_Copies(value));
printf("%s\n", (const char*)value);
}
enumerator->HasMoreElements(&bMoreHeaders);
}
}
if (gVerbose) {
printf("\n+++ TestHTTPEventSink::OnHeadersAvailable +++\n");
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(context));
if (pHTTPCon) {
char* type;
//optimize later TODO allow atoms here...! intead of just the header strings
pHTTPCon->GetContentType(&type);
if (type) {
printf("\nReceiving ... %s\n", type);
nsCRT::free(type);
}
}
}
return NS_OK;
}
NS_IMETHODIMP
TestHTTPEventSink::OnProgress(nsISupports* context, PRUint32 i_Progress, PRUint32 i_ProgressMax)
{
printf("\n+++ TestHTTPEventSink::OnProgress +++\n");
return NS_OK;
}
NS_IMETHODIMP
TestHTTPEventSink::OnRedirect(nsISupports* context, nsIURI* i_NewLocation)
{
printf("\n+++ TestHTTPEventSink::OnRedirect +++\n");
return NS_OK;
}
class InputTestConsumer : public nsIStreamListener
{
public:
InputTestConsumer();
virtual ~InputTestConsumer();
// ISupports interface...
NS_DECL_ISUPPORTS
// IStreamListener interface...
NS_IMETHOD OnStartRequest(nsIChannel* channel, nsISupports* context);
NS_IMETHOD OnDataAvailable(nsIChannel* channel, nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength);
NS_IMETHOD OnStopRequest(nsIChannel* channel, nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg);
#ifdef CACHE
private:
nsICacheObject* mCacheFile ;
#endif
};
InputTestConsumer::InputTestConsumer()
{
NS_INIT_REFCNT();
#ifdef CACHE
mCacheFile = nsnull ;
#endif
}
InputTestConsumer::~InputTestConsumer()
{
#ifdef CACHE
NS_IF_RELEASE(mCacheFile) ;
#endif
}
NS_IMPL_ISUPPORTS(InputTestConsumer,nsCOMTypeInfo<nsIStreamListener>::GetIID());
NS_IMETHODIMP
InputTestConsumer::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
#ifdef CACHE
/* Stuff taken from nsPluginHostImpl.cpp */
char * aContentType = nsnull ;
nsIURI* aURL = nsnull ;
nsICacheModule* diskCache ;
nsICacheManager* cacheManager ;
nsresult rv = NS_OK, r1, r2 ;
rv = channel->GetContentType(&aContentType) ;
if (NS_FAILED(rv)) return rv ;
rv = channel ->GetURI(&aURL) ;
if (NS_FAILED(rv)) return rv ;
char * cString;
char * fileName ;
nsCOMPtr<nsIURL> pURL(do_QueryInterface(aURL)) ;
if (pURL) {
pURL -> GetSpec(&cString) ;
/* Todo, use PROGID instead */
rv = nsComponentManager::CreateInstance(kCacheObjectCID,
nsnull,
kICacheObjectIID,
(void**)&mCacheFile) ;
if (NS_FAILED(rv)) {
return rv ;
}
r1 = NS_ERROR_FAILURE ;
r1 = mCacheFile->SetAddress(cString) ;
/* use the actual filname of the net-based file as the cache filename */
r1 = pURL->GetFileName(&fileName) ;
if(!fileName) {
fileName=new char[50] ;
strcpy(fileName, "nucache") ;
}
r2 = mCacheFile ->SetFilename(fileName) ;
delete [] fileName ;
}
/* todo: use PROGID instead */
rv = nsServiceManager::GetService(kCacheManagerCID,
kICacheManagerIID,
(nsISupports **)&cacheManager) ;
if (NS_FAILED(rv)) return rv ;
// cacheManager->Init( ) ;
rv = cacheManager->GetDiskModule(&diskCache) ;
if (NS_FAILED(rv)) return rv ;
rv = diskCache->AddObject(mCacheFile) ;
#endif
URLLoadInfo* info = (URLLoadInfo*)context;
if (info) {
info->mConnectTime = PR_Now() - info->mConnectTime;
}
if (gVerbose) {
printf("\nStarted loading: %s\n", info ? info->Name() : "UNKNOWN URL");
}
/*
nsCOMPtr<nsIURI> pURI(do_QueryInterface(context));
char* location = nsnull;
if (pURI) {
pURI->GetSpec(&location);
}
printf("\nStarted loading: %s\n", location ? location : "UNKNOWN URL");
if (location) {
nsCRT::free(location);
}
*/
return NS_OK;
}
NS_IMETHODIMP
InputTestConsumer::OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength)
{
char buf[1025];
PRUint32 amt, amt_wrote;
nsresult rv;
URLLoadInfo* info = (URLLoadInfo*)context;
do {
rv = aIStream->Read(buf, 1024, &amt);
#ifdef CACHE
if (nsnull != mCacheFile ) {
mCacheFile->Write((char*)buf, amt, &amt_wrote) ;
}
#endif
if (rv == NS_BASE_STREAM_EOF) break;
if (NS_FAILED(rv)) return rv;
if (gVerbose) {
buf[amt] = '\0';
puts(buf);
}
if (info) {
info->mBytesRead += amt;
}
} while (amt);
return NS_OK;
}
NS_IMETHODIMP
InputTestConsumer::OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg)
{
URLLoadInfo* info = (URLLoadInfo*)context;
if (info) {
double connectTime;
double readTime;
PRUint32 httpStatus, o_amt=0, l ;
PRInt16 m ;
PRBool bHTTPURL = PR_FALSE, b;
char buf[2000], *s ;
PRIntervalTime t ;
if (mCacheFile) {
mCacheFile->GetLastModified(&t) ;
printf("\nlast modified: %d\n", t) ;
mCacheFile->GetEtag(&s) ;
printf("etag: %s\n", s) ;
mCacheFile->GetContentType(&s) ;
printf("content type: %s\n", s) ;
mCacheFile->GetCharset(&s) ;
printf("character set: %s\n", s) ;
mCacheFile->GetContentEncoding(&s) ;
printf("Content encoding: %s\n", s) ;
mCacheFile->GetContentLength(&l) ;
printf("Content Length: %d\n", l) ;
mCacheFile->GetExpires(&t) ;
printf("Expires: %d\n", t) ;
mCacheFile->GetFilename(&s) ;
printf("Filename: %s\n", s) ;
mCacheFile->GetState(&l) ;
printf("State: %d\n", l) ;
mCacheFile->GetInfoSize(&l) ;
printf("Info size: %d\n", l) ;
mCacheFile->IsPartial(&b) ;
printf("Is completed: %s\n", b?"True":"False") ;
mCacheFile->GetLastAccessed(&t) ;
printf("Last Access time: %d\n", t) ;
mCacheFile->GetLastModified(&t) ;
printf("Last Modified time: %d\n", t) ;
mCacheFile->GetModuleIndex(&m) ;
printf("Module: %d\n", m) ;
mCacheFile->GetPageServicesURL(&s) ;
printf("Page Service URL: %s\n", s) ;
mCacheFile->GetPostData(&s) ;
printf("Post Data: %s\n", s) ;
mCacheFile->GetPostDataLen(&l) ;
printf("Post Data Length: %d\n", l) ;
mCacheFile->GetSize(&l) ;
printf("Size: %d\n", l) ;
mCacheFile->GetAddress(&s) ;
printf("URL Address: %s \n", s) ;
/* I know my test webpage is less than 2000 bytes. yixiong */
mCacheFile->Read (buf, (PRUint32) 2000, &o_amt) ;
buf[o_amt] = '\0' ;
// printf("%s\n o_amt = %d \n", buf, o_amt) ;
}
info->mTotalTime = PR_Now() - info->mTotalTime;
connectTime = (info->mConnectTime/1000.0)/1000.0;
readTime = ((info->mTotalTime-info->mConnectTime)/1000.0)/1000.0;
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(channel));
if (pHTTPCon) {
pHTTPCon->GetResponseStatus(&httpStatus);
bHTTPURL = PR_TRUE;
}
printf("\nFinished loading: %s Status Code: %x\n", info->Name(), aStatus);
if (bHTTPURL)
printf("\tHTTP Status: %u\n", httpStatus);
if (NS_ERROR_UNKNOWN_HOST == aStatus) {
printf("\tDNS lookup failed.\n");
}
printf("\tRead: %d bytes.\n", info->mBytesRead);
printf("\tTime to connect: %.3f seconds\n", connectTime);
printf("\tTime to read: %.3f seconds.\n", readTime);
if (readTime > 0.0) {
printf("\tThroughput: %.0f bps.\n", (info->mBytesRead*8)/readTime);
} else {
printf("\tThroughput: REAL FAST!!\n");
}
} else {
printf("\nFinished loading: UNKNOWN URL. Status Code: %x\n", aStatus);
}
/*
nsCOMPtr<nsIURI> pURI(do_QueryInterface(context));
char* location = nsnull;
if (pURI) {
pURI->GetSpec(&location);
}
printf("\nFinished loading: %s Status Code: %x\n", location ? location : "UNKNOWN URL", aStatus);
if (location) {
nsCRT::free(location);
}
*/
gKeepRunning -= 1;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
class nsNotificationCallbacks : public nsIInterfaceRequestor {
public:
NS_DECL_ISUPPORTS
nsNotificationCallbacks() {
NS_INIT_REFCNT();
}
NS_IMETHOD GetInterface(const nsIID& eventSinkIID, nsISupports* *result) {
nsresult rv = NS_ERROR_FAILURE;
if (eventSinkIID.Equals(NS_GET_IID(nsIHTTPEventSink))) {
TestHTTPEventSink *sink;
sink = new TestHTTPEventSink();
if (sink == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(sink);
rv = sink->QueryInterface(eventSinkIID, (void**)result);
NS_RELEASE(sink);
}
return rv;
}
};
NS_IMPL_ISUPPORTS1(nsNotificationCallbacks, nsIInterfaceRequestor)
////////////////////////////////////////////////////////////////////////////////
nsresult StartLoadingURL(const char* aUrlString)
{
nsresult rv;
NS_WITH_SERVICE(nsIIOService, pService, kIOServiceCID, &rv);
if (pService) {
nsCOMPtr<nsIURI> pURL;
rv = pService->NewURI(aUrlString, nsnull, getter_AddRefs(pURL));
if (NS_FAILED(rv)) {
printf("ERROR: NewURI failed for %s\n", aUrlString);
return rv;
}
nsCOMPtr<nsIChannel> pChannel;
nsNotificationCallbacks* callbacks;
callbacks = new nsNotificationCallbacks();
if (!callbacks) {
NS_ERROR("Failed to create a new consumer!");
return NS_ERROR_OUT_OF_MEMORY;;
}
NS_ADDREF(callbacks);
// Async reading thru the calls of the event sink interface
rv = pService->NewChannelFromURI("load", pURL, nsnull, callbacks,
getter_AddRefs(pChannel));
NS_RELEASE(callbacks);
if (NS_FAILED(rv)) {
printf("ERROR: NewChannelFromURI failed for %s\n", aUrlString);
return rv;
}
/*
You may optionally add/set other headers on this
request object. This is done by QI for the specific
protocolConnection.
*/
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(pChannel));
if (pHTTPCon) {
// Setting a sample user agent string.
nsCOMPtr<nsIAtom> userAgent;
userAgent = NS_NewAtom("user-agent");
rv = pHTTPCon->SetRequestHeader(userAgent, "Mozilla/5.0 [en] (Win98; U)");
if (NS_FAILED(rv)) return rv;
}
InputTestConsumer* listener;
listener = new InputTestConsumer;
NS_IF_ADDREF(listener);
if (!listener) {
NS_ERROR("Failed to create a new stream listener!");
return NS_ERROR_OUT_OF_MEMORY;;
}
URLLoadInfo* info;
info = new URLLoadInfo(aUrlString);
NS_IF_ADDREF(info);
if (!info) {
NS_ERROR("Failed to create a load info!");
return NS_ERROR_OUT_OF_MEMORY;;
}
rv = pChannel->AsyncRead(0, // staring position
-1, // number of bytes to read
info, // ISupports context
listener); // IStreamListener consumer
if (NS_SUCCEEDED(rv)) {
gKeepRunning += 1;
}
NS_RELEASE(listener);
NS_RELEASE(info);
}
return rv;
}
nsresult LoadURLsFromFile(char *aFileName)
{
nsresult rv = NS_OK;
PRInt32 len, offset;
PRFileDesc* fd;
char buffer[1024];
nsString fileBuffer;
nsAutoString urlString(eOneByte);
fd = PR_Open(aFileName, PR_RDONLY, 777);
if (!fd) {
return NS_ERROR_FAILURE;
}
// Keep reading the file until EOF (or an error) is reached...
do {
len = PR_Read(fd, buffer, sizeof(buffer));
if (len>0) {
fileBuffer.Append(buffer, len);
// Treat each line as a URL...
while ((offset = fileBuffer.FindChar('\n')) != -1) {
fileBuffer.Left(urlString, offset);
fileBuffer.Cut(0, offset+1);
urlString.StripChars("\r");
if (urlString.Length()) {
printf("\t%s\n", urlString.GetBuffer());
rv = StartLoadingURL(urlString.GetBuffer());
}
}
}
} while (len>0);
// If anything is left in the fileBuffer, treat it as a URL...
fileBuffer.StripChars("\r");
if (fileBuffer.Length()) {
printf("\t%s\n", fileBuffer.GetBuffer());
StartLoadingURL(fileBuffer.GetBuffer());
}
PR_Close(fd);
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, NULL /* default */);
return rv;
}
int
main(int argc, char* argv[])
{
nsresult rv= (nsresult)-1;
if (argc < 2) {
printf("usage: %s [-verbose] [-file <name>] <url> <url> ... \n", argv[0]);
return -1;
}
/*
The following code only deals with XPCOM registration stuff. and setting
up the event queues. Copied from TestSocketIO.cpp
*/
rv = NS_AutoregisterComponents();
if (NS_FAILED(rv)) return rv;
// Create the Event Queue for this thread...
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
#if 0 // Jud sez
// fire up an instance of the cookie manager.
// I'm doing this using the serviceManager for convenience's sake.
// Presumably an application will init it's own cookie service a
// different way (this way works too though).
NS_WITH_SERVICE(nsICookieService, cookieService, nsCookieServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
#endif // NECKO
int i;
printf("\nTrying to load:\n");
for (i=1; i<argc; i++) {
// Turn on verbose printing...
if (PL_strcasecmp(argv[i], "-verbose") == 0) {
gVerbose = PR_TRUE;
continue;
}
// Turn on netlib tracing...
if (PL_strcasecmp(argv[i], "-file") == 0) {
LoadURLsFromFile(argv[++i]);
continue;
}
printf("\t%s\n", argv[i]);
rv = StartLoadingURL(argv[i]);
}
// Enter the message pump to allow the URL load to proceed.
while ( gKeepRunning ) {
#ifdef WIN32
MSG msg;
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
gKeepRunning = 0;
}
#else
#ifdef XP_MAC
/* Mac stuff is missing here! */
#else
PLEvent *gEvent;
rv = gEventQ->GetEvent(&gEvent);
rv = gEventQ->HandleEvent(gEvent);
#endif /* XP_UNIX */
#endif /* !WIN32 */
}
return rv;
}

View File

@ -1,800 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
/*
The TestProtocols tests the basic protocols architecture and can
be used to test individual protocols as well. If this grows too
big then we should split it to individual protocols.
-Gagan Saksena 04/29/99
*/
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#endif
#include "nspr.h"
#include "nscore.h"
#include "nsCOMPtr.h"
#include "nsIEventQueueService.h"
#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIStreamListener.h"
#include "nsIInputStream.h"
#include "nsIBufferInputStream.h"
#include "nsCRT.h"
#include "nsIChannel.h"
#include "nsIURL.h"
#include "nsIHTTPChannel.h"
#include "nsIHttpEventSink.h"
#include "nsIInterfaceRequestor.h"
#include "nsIDNSService.h"
#include "nsISimpleEnumerator.h"
#include "nsIHTTPHeader.h"
#include "nsXPIDLString.h"
#ifdef CACHE
#include "nsICacheManager.h"
#include "nsICacheObject.h"
#endif
// this test app handles cookies.
#include "nsICookieService.h"
static NS_DEFINE_CID(nsCookieServiceCID, NS_COOKIESERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
#ifdef CACHE
static NS_DEFINE_IID(kICacheManagerIID, NS_ICACHEMANAGER_IID) ;
static NS_DEFINE_IID(kCacheManagerCID, NS_CACHEMANAGER_CID) ;
static NS_DEFINE_IID(kICacheObjectIID, NS_ICACHEOBJECT_IID) ;
static NS_DEFINE_CID(kCacheObjectCID, NS_CACHEOBJECT_CID);
#endif
//static PRTime gElapsedTime; // enable when we time it...
static int gKeepRunning = 0;
static PRBool gVerbose = PR_FALSE;
static nsIEventQueue* gEventQ = nsnull;
class URLLoadInfo : public nsISupports
{
public:
URLLoadInfo(const char* aUrl);
virtual ~URLLoadInfo();
// ISupports interface...
NS_DECL_ISUPPORTS
const char* Name() { return mURLString.GetBuffer(); }
PRInt32 mBytesRead;
PRTime mTotalTime;
PRTime mConnectTime;
nsString mURLString;
};
URLLoadInfo::URLLoadInfo(const char *aUrl) : mURLString(aUrl)
{
NS_INIT_REFCNT();
mBytesRead = 0;
mConnectTime = mTotalTime = PR_Now();
}
URLLoadInfo::~URLLoadInfo()
{
}
NS_IMPL_ISUPPORTS(URLLoadInfo,nsCOMTypeInfo<nsISupports>::GetIID());
class TestHTTPEventSink : public nsIHTTPEventSink
{
public:
TestHTTPEventSink();
virtual ~TestHTTPEventSink();
// ISupports interface...
NS_DECL_ISUPPORTS
// nsIHTTPEventSink interface...
NS_IMETHOD OnAwaitingInput(nsISupports* i_Context);
NS_IMETHOD OnHeadersAvailable(nsISupports* i_Context);
NS_IMETHOD OnProgress(nsISupports* i_Context,
PRUint32 i_Progress,
PRUint32 i_ProgressMax);
// OnRedirect gets fired only if you have set FollowRedirects on the handler!
NS_IMETHOD OnRedirect(nsISupports* i_Context,
nsIURI* i_NewLocation);
};
TestHTTPEventSink::TestHTTPEventSink()
{
NS_INIT_REFCNT();
}
TestHTTPEventSink::~TestHTTPEventSink()
{
}
NS_IMPL_ISUPPORTS(TestHTTPEventSink,nsCOMTypeInfo<nsIHTTPEventSink>::GetIID());
NS_IMETHODIMP
TestHTTPEventSink::OnAwaitingInput(nsISupports* context)
{
printf("\n+++ TestHTTPEventSink::OnAwaitingInput +++\n");
return NS_OK;
}
NS_IMETHODIMP
TestHTTPEventSink::OnHeadersAvailable(nsISupports* context)
{
nsCOMPtr<nsISimpleEnumerator> enumerator;
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(context));
PRBool bMoreHeaders;
printf("cachetest: 162, OnHeadersAvailable, \n") ;
if (pHTTPCon) {
pHTTPCon->GetRequestHeaderEnumerator(getter_AddRefs(enumerator));
printf("Request headers:\n");
enumerator->HasMoreElements(&bMoreHeaders);
while (bMoreHeaders) {
nsCOMPtr<nsISupports> item;
nsCOMPtr<nsIHTTPHeader> header;
enumerator->GetNext(getter_AddRefs(item));
header = do_QueryInterface(item);
if (header) {
nsCOMPtr<nsIAtom> key;
nsAutoString field(eOneByte);
nsXPIDLCString value;
header->GetField(getter_AddRefs(key));
key->ToString(field);
printf("\t%s: ", field.GetBuffer());
header->GetValue(getter_Copies(value));
printf("%s\n", (const char*)value);
}
enumerator->HasMoreElements(&bMoreHeaders);
}
pHTTPCon->GetResponseHeaderEnumerator(getter_AddRefs(enumerator));
printf("Response headers:\n");
enumerator->HasMoreElements(&bMoreHeaders);
while (bMoreHeaders) {
nsCOMPtr<nsISupports> item;
nsCOMPtr<nsIHTTPHeader> header;
enumerator->GetNext(getter_AddRefs(item));
header = do_QueryInterface(item);
if (header) {
nsCOMPtr<nsIAtom> key;
nsAutoString field(eOneByte);
nsXPIDLCString value;
header->GetField(getter_AddRefs(key));
key->ToString(field);
printf("\t%s: ", field.GetBuffer());
header->GetValue(getter_Copies(value));
printf("%s\n", (const char*)value);
}
enumerator->HasMoreElements(&bMoreHeaders);
}
}
if (gVerbose) {
printf("\n+++ TestHTTPEventSink::OnHeadersAvailable +++\n");
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(context));
if (pHTTPCon) {
char* type;
//optimize later TODO allow atoms here...! intead of just the header strings
pHTTPCon->GetContentType(&type);
if (type) {
printf("\nReceiving ... %s\n", type);
nsCRT::free(type);
}
}
}
return NS_OK;
}
NS_IMETHODIMP
TestHTTPEventSink::OnProgress(nsISupports* context, PRUint32 i_Progress, PRUint32 i_ProgressMax)
{
printf("\n+++ TestHTTPEventSink::OnProgress +++\n");
return NS_OK;
}
NS_IMETHODIMP
TestHTTPEventSink::OnRedirect(nsISupports* context, nsIURI* i_NewLocation)
{
printf("\n+++ TestHTTPEventSink::OnRedirect +++\n");
return NS_OK;
}
class InputTestConsumer : public nsIStreamListener
{
public:
InputTestConsumer();
virtual ~InputTestConsumer();
// ISupports interface...
NS_DECL_ISUPPORTS
// IStreamListener interface...
NS_IMETHOD OnStartRequest(nsIChannel* channel, nsISupports* context);
NS_IMETHOD OnDataAvailable(nsIChannel* channel, nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength);
NS_IMETHOD OnStopRequest(nsIChannel* channel, nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg);
#ifdef CACHE
private:
nsICacheObject* mCacheFile ;
#endif
};
InputTestConsumer::InputTestConsumer()
{
NS_INIT_REFCNT();
#ifdef CACHE
mCacheFile = nsnull ;
#endif
}
InputTestConsumer::~InputTestConsumer()
{
#ifdef CACHE
NS_IF_RELEASE(mCacheFile) ;
#endif
}
NS_IMPL_ISUPPORTS(InputTestConsumer,nsCOMTypeInfo<nsIStreamListener>::GetIID());
NS_IMETHODIMP
InputTestConsumer::OnStartRequest(nsIChannel* channel, nsISupports* context)
{
#ifdef CACHE
/* Stuff taken from nsPluginHostImpl.cpp */
char * aContentType = nsnull ;
nsIURI* aURL = nsnull ;
nsICacheModule* memCache ;
nsICacheManager* cacheManager ;
nsresult rv = NS_OK, r1, r2 ;
rv = channel->GetContentType(&aContentType) ;
if (NS_FAILED(rv)) return rv ;
rv = channel ->GetURI(&aURL) ;
if (NS_FAILED(rv)) return rv ;
char * cString;
char * fileName ;
nsCOMPtr<nsIURL> pURL(do_QueryInterface(aURL)) ;
if (pURL) {
pURL -> GetSpec(&cString) ;
/* Todo, use PROGID instead */
rv = nsComponentManager::CreateInstance(kCacheObjectCID,
nsnull,
kICacheObjectIID,
(void**)&mCacheFile) ;
if (NS_FAILED(rv)) {
return rv ;
}
r1 = NS_ERROR_FAILURE ;
r1 = mCacheFile->SetAddress(cString) ;
/* use the actual filname of the net-based file as the cache filename */
pURL->GetFileName(&fileName) ;
/* temp hack, name resolution needs to be added */
if(!fileName) {
fileName=new char[50] ;
strcpy(fileName, "nucache") ;
}
r2 = mCacheFile ->SetFilename(fileName) ;
delete [] fileName ;
}
/* todo: use PROGID instead */
rv = nsServiceManager::GetService(kCacheManagerCID,
kICacheManagerIID,
(nsISupports **)&cacheManager) ;
if (NS_FAILED(rv)) return rv ;
rv = cacheManager->GetMemModule(&memCache) ;
if (NS_FAILED(rv)) return rv ;
rv = memCache->AddObject(mCacheFile) ;
#endif
URLLoadInfo* info = (URLLoadInfo*)context;
if (info) {
info->mConnectTime = PR_Now() - info->mConnectTime;
}
if (gVerbose) {
printf("\nStarted loading: %s\n", info ? info->Name() : "UNKNOWN URL");
}
/*
nsCOMPtr<nsIURI> pURI(do_QueryInterface(context));
char* location = nsnull;
if (pURI) {
pURI->GetSpec(&location);
}
printf("\nStarted loading: %s\n", location ? location : "UNKNOWN URL");
if (location) {
nsCRT::free(location);
}
*/
return NS_OK;
}
NS_IMETHODIMP
InputTestConsumer::OnDataAvailable(nsIChannel* channel,
nsISupports* context,
nsIInputStream *aIStream,
PRUint32 aSourceOffset,
PRUint32 aLength)
{
char buf[1025];
PRUint32 amt, amt_wrote;
nsresult rv;
URLLoadInfo* info = (URLLoadInfo*)context;
do {
rv = aIStream->Read(buf, 1024, &amt);
#ifdef CACHE
if (nsnull != mCacheFile ) {
mCacheFile->Write((char*)buf, amt, &amt_wrote) ;
}
#endif
if (rv == NS_BASE_STREAM_EOF) break;
if (NS_FAILED(rv)) return rv;
if (gVerbose) {
buf[amt] = '\0';
puts(buf);
}
if (info) {
info->mBytesRead += amt;
}
} while (amt);
return NS_OK;
}
NS_IMETHODIMP
InputTestConsumer::OnStopRequest(nsIChannel* channel,
nsISupports* context,
nsresult aStatus,
const PRUnichar* aMsg)
{
URLLoadInfo* info = (URLLoadInfo*)context;
if (info) {
double connectTime;
double readTime;
PRUint32 httpStatus, o_amt=0 ;
PRBool bHTTPURL = PR_FALSE ;
char buf[2000] ;
if (mCacheFile) {
/*
mCacheFile->GetLastModified(&t) ;
printf("\nlast modified: %d\n", t) ;
mCacheFile->GetEtag(&s) ;
printf("etag: %s\n", s) ;
mCacheFile->GetContentType(&s) ;
printf("content type: %s\n", s) ;
mCacheFile->GetCharset(&s) ;
printf("character set: %s\n", s) ;
mCacheFile->GetContentEncoding(&s) ;
printf("Content encoding: %s\n", s) ;
mCacheFile->GetContentLength(&l) ;
printf("Content Length: %d\n", l) ;
mCacheFile->GetExpires(&t) ;
printf("Expires: %d\n", t) ;
mCacheFile->GetFilename(&s) ;
printf("Filename: %s\n", s) ;
mCacheFile->GetState(&l) ;
printf("State: %d\n", l) ;
mCacheFile->GetInfoSize(&l) ;
printf("Info size: %d\n", l) ;
mCacheFile->IsPartial(&b) ;
printf("Is completed: %s\n", b?"True":"False") ;
mCacheFile->GetLastAccessed(&t) ;
printf("Last Access time: %d\n", t) ;
mCacheFile->GetLastModified(&t) ;
printf("Last Modified time: %d\n", t) ;
mCacheFile->GetModuleIndex(&m) ;
printf("Module: %d\n", m) ;
mCacheFile->GetPageServicesURL(&s) ;
printf("Page Service URL: %s\n", s) ;
mCacheFile->GetPostData(&s) ;
printf("Post Data: %s\n", s) ;
mCacheFile->GetPostDataLen(&l) ;
printf("Post Data Length: %d\n", l) ;
mCacheFile->GetSize(&l) ;
printf("Size: %d\n", l) ;
mCacheFile->GetAddress(&s) ;
printf("URL Address: %s \n", s) ;
*/
mCacheFile->Read (buf, (PRUint32) 2000, &o_amt) ;
buf[o_amt] = '\0' ;
printf("%s\no_amt = %d \n", buf, o_amt) ;
}
info->mTotalTime = PR_Now() - info->mTotalTime;
connectTime = (info->mConnectTime/1000.0)/1000.0;
readTime = ((info->mTotalTime-info->mConnectTime)/1000.0)/1000.0;
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(channel));
if (pHTTPCon) {
pHTTPCon->GetResponseStatus(&httpStatus);
bHTTPURL = PR_TRUE;
}
printf("\nFinished loading: %s Status Code: %x\n", info->Name(), aStatus);
if (bHTTPURL)
printf("\tHTTP Status: %u\n", httpStatus);
if (NS_ERROR_UNKNOWN_HOST == aStatus) {
printf("\tDNS lookup failed.\n");
}
printf("\tRead: %d bytes.\n", info->mBytesRead);
printf("\tTime to connect: %.3f seconds\n", connectTime);
printf("\tTime to read: %.3f seconds.\n", readTime);
if (readTime > 0.0) {
printf("\tThroughput: %.0f bps.\n", (info->mBytesRead*8)/readTime);
} else {
printf("\tThroughput: REAL FAST!!\n");
}
} else {
printf("\nFinished loading: UNKNOWN URL. Status Code: %x\n", aStatus);
}
/*
nsCOMPtr<nsIURI> pURI(do_QueryInterface(context));
char* location = nsnull;
if (pURI) {
pURI->GetSpec(&location);
}
printf("\nFinished loading: %s Status Code: %x\n", location ? location : "UNKNOWN URL", aStatus);
if (location) {
nsCRT::free(location);
}
*/
gKeepRunning -= 1;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
class nsNotificationCallbacks : public nsIInterfaceRequestor {
public:
NS_DECL_ISUPPORTS
nsNotificationCallbacks() {
NS_INIT_REFCNT();
}
NS_IMETHOD GetInterface(const nsIID& eventSinkIID, nsISupports* *result) {
nsresult rv = NS_ERROR_FAILURE;
if (eventSinkIID.Equals(NS_GET_IID(nsIHTTPEventSink))) {
TestHTTPEventSink *sink;
sink = new TestHTTPEventSink();
if (sink == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(sink);
rv = sink->QueryInterface(eventSinkIID, (void**)result);
NS_RELEASE(sink);
}
return rv;
}
};
NS_IMPL_ISUPPORTS1(nsNotificationCallbacks, nsIInterfaceRequestor)
////////////////////////////////////////////////////////////////////////////////
nsresult StartLoadingURL(const char* aUrlString)
{
nsresult rv;
NS_WITH_SERVICE(nsIIOService, pService, kIOServiceCID, &rv);
if (pService) {
nsCOMPtr<nsIURI> pURL;
rv = pService->NewURI(aUrlString, nsnull, getter_AddRefs(pURL));
if (NS_FAILED(rv)) {
printf("ERROR: NewURI failed for %s\n", aUrlString);
return rv;
}
nsCOMPtr<nsIChannel> pChannel;
nsNotificationCallbacks* callbacks;
callbacks = new nsNotificationCallbacks();
if (!callbacks) {
NS_ERROR("Failed to create a new consumer!");
return NS_ERROR_OUT_OF_MEMORY;;
}
NS_ADDREF(callbacks);
// Async reading thru the calls of the event sink interface
rv = pService->NewChannelFromURI("load", pURL, nsnull, callbacks,
getter_AddRefs(pChannel));
NS_RELEASE(callbacks);
if (NS_FAILED(rv)) {
printf("ERROR: NewChannelFromURI failed for %s\n", aUrlString);
return rv;
}
/*
You may optionally add/set other headers on this
request object. This is done by QI for the specific
protocolConnection.
*/
nsCOMPtr<nsIHTTPChannel> pHTTPCon(do_QueryInterface(pChannel));
if (pHTTPCon) {
// Setting a sample user agent string.
nsCOMPtr<nsIAtom> userAgent;
userAgent = NS_NewAtom("user-agent");
rv = pHTTPCon->SetRequestHeader(userAgent, "Mozilla/5.0 [en] (Win98; U)");
if (NS_FAILED(rv)) return rv;
}
InputTestConsumer* listener;
listener = new InputTestConsumer;
NS_IF_ADDREF(listener);
if (!listener) {
NS_ERROR("Failed to create a new stream listener!");
return NS_ERROR_OUT_OF_MEMORY;;
}
URLLoadInfo* info;
info = new URLLoadInfo(aUrlString);
NS_IF_ADDREF(info);
if (!info) {
NS_ERROR("Failed to create a load info!");
return NS_ERROR_OUT_OF_MEMORY;;
}
rv = pChannel->AsyncRead(0, // staring position
-1, // number of bytes to read
info, // ISupports context
listener); // IStreamListener consumer
if (NS_SUCCEEDED(rv)) {
gKeepRunning += 1;
}
NS_RELEASE(listener);
NS_RELEASE(info);
}
return rv;
}
nsresult LoadURLsFromFile(char *aFileName)
{
nsresult rv = NS_OK;
PRInt32 len, offset;
PRFileDesc* fd;
char buffer[1024];
nsString fileBuffer;
nsAutoString urlString(eOneByte);
fd = PR_Open(aFileName, PR_RDONLY, 777);
if (!fd) {
return NS_ERROR_FAILURE;
}
// Keep reading the file until EOF (or an error) is reached...
do {
len = PR_Read(fd, buffer, sizeof(buffer));
if (len>0) {
fileBuffer.Append(buffer, len);
// Treat each line as a URL...
while ((offset = fileBuffer.FindChar('\n')) != -1) {
fileBuffer.Left(urlString, offset);
fileBuffer.Cut(0, offset+1);
urlString.StripChars("\r");
if (urlString.Length()) {
printf("\t%s\n", urlString.GetBuffer());
rv = StartLoadingURL(urlString.GetBuffer());
}
}
}
} while (len>0);
// If anything is left in the fileBuffer, treat it as a URL...
fileBuffer.StripChars("\r");
if (fileBuffer.Length()) {
printf("\t%s\n", fileBuffer.GetBuffer());
StartLoadingURL(fileBuffer.GetBuffer());
}
PR_Close(fd);
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup, NULL /* default */);
return rv;
}
int
main(int argc, char* argv[])
{
nsresult rv= (nsresult)-1;
if (argc < 2) {
printf("usage: %s [-verbose] [-file <name>] <url> <url> ... \n", argv[0]);
return -1;
}
/*
The following code only deals with XPCOM registration stuff. and setting
up the event queues. Copied from TestSocketIO.cpp
*/
rv = NS_AutoregisterComponents();
if (NS_FAILED(rv)) return rv;
// Create the Event Queue for this thread...
NS_WITH_SERVICE(nsIEventQueueService, eventQService, kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = eventQService->CreateThreadEventQueue();
if (NS_FAILED(rv)) return rv;
eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &gEventQ);
#if 0 // Jud sez
// fire up an instance of the cookie manager.
// I'm doing this using the serviceManager for convenience's sake.
// Presumably an application will init it's own cookie service a
// different way (this way works too though).
NS_WITH_SERVICE(nsICookieService, cookieService, nsCookieServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
#endif // NECKO
int i;
printf("\nTrying to load:\n");
for (i=1; i<argc; i++) {
// Turn on verbose printing...
if (PL_strcasecmp(argv[i], "-verbose") == 0) {
gVerbose = PR_TRUE;
continue;
}
// Turn on netlib tracing...
if (PL_strcasecmp(argv[i], "-file") == 0) {
LoadURLsFromFile(argv[++i]);
continue;
}
printf("\t%s\n", argv[i]);
rv = StartLoadingURL(argv[i]);
}
// Enter the message pump to allow the URL load to proceed.
while ( gKeepRunning ) {
#ifdef WIN32
MSG msg;
if (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} else {
gKeepRunning = 0;
}
#else
#ifdef XP_MAC
/* Mac stuff is missing here! */
#else
PLEvent *gEvent;
rv = gEventQ->GetEvent(&gEvent);
rv = gEventQ->HandleEvent(gEvent);
#endif /* XP_UNIX */
#endif /* !WIN32 */
}
return rv;
}