Compare commits

..

18 Commits

Author SHA1 Message Date
waterson%netscape.com
43f83c6887 Added JS and DOM libs to link.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20813 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 19:23:21 +00:00
waterson%netscape.com
8362cce878 Changed itoa() to PR_snprintf() because there is no itoa() on a Mac.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20812 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 19:17:12 +00:00
waterson%netscape.com
ec2d371258 Added precondition on GetParentNode().
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20770 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 07:22:03 +00:00
waterson%netscape.com
feece20aab Exposed fns that convert indicies to ordinal resources and back.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20769 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 07:20:41 +00:00
waterson%netscape.com
262c8520bf Fixed buggy GetPredicate(), made some stuff into pseudo-constants to reduce overhead.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20768 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 07:20:12 +00:00
waterson%netscape.com
6c64aec9da Altered XUL representation to use RDF:Seq containers so that DOM node ordering is preserved.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20763 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 04:40:25 +00:00
waterson%netscape.com
bc0d43c97d Added more utility routines to manipulate RDF containers.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20762 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 04:39:06 +00:00
waterson%netscape.com
2866975b2e Moved check to ensure that resource is a container to the factory function (so we can return an intelligent error code instead of just asserting).
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20753 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-16 01:25:11 +00:00
waterson%netscape.com
eba763e6b7 Made sure that dtor was virtual.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20742 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 21:20:59 +00:00
waterson%netscape.com
c29d2e26b5 Moved some of the utility routines into nsRDFParserUtils. Made this work more like the XML content sink; that is, got rid of the nsIRDFXMLDataSource interface, which really isn't appropriate for XUL.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20741 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:19:33 +00:00
waterson%netscape.com
c88ea6ae58 Added nsIXULContentSink interface.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20740 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:16:44 +00:00
waterson%netscape.com
2065767bc6 Started implementing DOM functionality in a big way.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20739 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:15:23 +00:00
waterson%netscape.com
8c4c803e8f Added nsIDOMNodeObserver interface.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20738 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:12:16 +00:00
waterson%netscape.com
2c4d514bc0 Added JS libs to link.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20737 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:10:54 +00:00
waterson%netscape.com
a1a2c4e5fe Renamed nsIRDFContentSink to nsIXULContentSink.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20736 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:10:47 +00:00
waterson%netscape.com
601c74c421 Added IsJavaScriptLanguage() routine.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20735 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:10:02 +00:00
waterson%netscape.com
755fd8300e Renamed RDF content sink to XUL content sink.
git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20734 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-15 20:09:30 +00:00
(no author)
56495a3530 This commit was manufactured by cvs2svn to create branch
'RDFDOM_19990215_BRANCH'.

git-svn-id: svn://10.0.0.236/branches/RDFDOM_19990215_BRANCH@20684 18797224-902f-48f8-a5cc-f745e15eee43
1999-02-14 06:20:54 +00:00
241 changed files with 55211 additions and 24452 deletions

View File

@@ -0,0 +1,305 @@
/* -*- 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.0 (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.
*/
/*
Helper class to implement the nsIDOMNodeList interface.
XXX It's probably wrong in some sense, as it uses the "naked"
content interface to look for kids. (I assume in general this is
bad because there may be pseudo-elements created for presentation
that aren't visible to the DOM.)
*/
#include "nsDOMCID.h"
#include "nsIDOMNode.h"
#include "nsIDOMHTMLCollection.h"
#include "nsIDOMScriptObjectFactory.h"
#include "nsIScriptGlobalObject.h"
#include "nsIServiceManager.h"
#include "nsISupportsArray.h"
#include "nsRDFDOMNodeList.h"
////////////////////////////////////////////////////////////////////////
// GUID definitions
static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID);
static NS_DEFINE_IID(kIDOMScriptObjectFactoryIID, NS_IDOM_SCRIPT_OBJECT_FACTORY_IID);
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
////////////////////////////////////////////////////////////////////////
//
class RDFHTMLCollectionImpl : public nsIDOMHTMLCollection
{
private:
nsRDFDOMNodeList* mOuter;
public:
RDFHTMLCollectionImpl(nsRDFDOMNodeList* aOuter);
virtual ~RDFHTMLCollectionImpl();
// nsISupports interface
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aResult);
// nsIDOMHTMLCollection interface
NS_DECL_IDOMHTMLCOLLECTION
};
RDFHTMLCollectionImpl::RDFHTMLCollectionImpl(nsRDFDOMNodeList* aOuter)
: mOuter(aOuter)
{
}
RDFHTMLCollectionImpl::~RDFHTMLCollectionImpl(void)
{
}
NS_IMETHODIMP_(nsrefcnt)
RDFHTMLCollectionImpl::AddRef(void)
{
return mOuter->AddRef();
}
NS_IMETHODIMP_(nsrefcnt)
RDFHTMLCollectionImpl::Release(void)
{
return mOuter->Release();
}
NS_IMETHODIMP
RDFHTMLCollectionImpl::QueryInterface(REFNSIID aIID, void** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIDOMHTMLCollection::IID())) {
*aResult = NS_STATIC_CAST(nsIDOMHTMLCollection*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
return mOuter->QueryInterface(aIID, aResult);
}
}
NS_IMETHODIMP
RDFHTMLCollectionImpl::GetLength(PRUint32* aLength)
{
return mOuter->GetLength(aLength);
}
NS_IMETHODIMP
RDFHTMLCollectionImpl::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
return mOuter->Item(aIndex, aReturn);
}
NS_IMETHODIMP
RDFHTMLCollectionImpl::NamedItem(const nsString& aName, nsIDOMNode** aReturn)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////
// ctors & dtors
nsRDFDOMNodeList::nsRDFDOMNodeList(void)
: mInner(nsnull),
mElements(nsnull),
mScriptObject(nsnull)
{
NS_INIT_REFCNT();
}
nsRDFDOMNodeList::~nsRDFDOMNodeList(void)
{
NS_IF_RELEASE(mElements);
delete mInner;
}
nsresult
nsRDFDOMNodeList::Create(nsRDFDOMNodeList** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
nsRDFDOMNodeList* list = new nsRDFDOMNodeList();
if (! list)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv;
if (NS_FAILED(rv = list->Init())) {
delete list;
return rv;
}
NS_ADDREF(list);
*aResult = list;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// nsISupports interface
NS_IMPL_ADDREF(nsRDFDOMNodeList);
NS_IMPL_RELEASE(nsRDFDOMNodeList);
nsresult
nsRDFDOMNodeList::QueryInterface(REFNSIID aIID, void** aResult)
{
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(nsIDOMNodeList::IID()) ||
aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsIDOMNodeList*, this);
NS_ADDREF(this);
return NS_OK;
}
else if (aIID.Equals(kIScriptObjectOwnerIID)) {
*aResult = NS_STATIC_CAST(nsIScriptObjectOwner*, this);
NS_ADDREF(this);
return NS_OK;
}
else if (aIID.Equals(nsIDOMHTMLCollection::IID())) {
// Aggregate this interface
if (! mInner) {
if (! (mInner = new RDFHTMLCollectionImpl(this)))
return NS_ERROR_OUT_OF_MEMORY;
}
return mInner->QueryInterface(aIID, aResult);
}
return NS_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////////
// nsIDOMNodeList interface
NS_IMETHODIMP
nsRDFDOMNodeList::GetLength(PRUint32* aLength)
{
NS_ASSERTION(aLength != nsnull, "null ptr");
if (! aLength)
return NS_ERROR_NULL_POINTER;
*aLength = mElements->Count();
return NS_OK;
}
NS_IMETHODIMP
nsRDFDOMNodeList::Item(PRUint32 aIndex, nsIDOMNode** aReturn)
{
NS_PRECONDITION(aReturn != nsnull, "null ptr");
if (! aReturn)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(aIndex < (PRUint32) mElements->Count(), "invalid arg");
if (aIndex >= (PRUint32) mElements->Count())
return NS_ERROR_INVALID_ARG;
// Cast is okay because we're in a closed system.
*aReturn = (nsIDOMNode*) mElements->ElementAt(aIndex);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// nsIScriptObjectOwner interface
NS_IMETHODIMP
nsRDFDOMNodeList::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject)
{
nsresult rv = NS_OK;
nsIScriptGlobalObject* global = aContext->GetGlobalObject();
if (nsnull == mScriptObject) {
nsIDOMScriptObjectFactory *factory;
if (NS_SUCCEEDED(rv = nsServiceManager::GetService(kDOMScriptObjectFactoryCID,
kIDOMScriptObjectFactoryIID,
(nsISupports **)&factory))) {
rv = factory->NewScriptHTMLCollection(aContext,
(nsISupports*)(nsIDOMNodeList*)this,
global,
(void**)&mScriptObject);
nsServiceManager::ReleaseService(kDOMScriptObjectFactoryCID, factory);
}
}
*aScriptObject = mScriptObject;
NS_RELEASE(global);
return rv;
}
NS_IMETHODIMP
nsRDFDOMNodeList::SetScriptObject(void* aScriptObject)
{
mScriptObject = aScriptObject;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// Implementation methods
nsresult
nsRDFDOMNodeList::Init(void)
{
nsresult rv;
if (NS_FAILED(rv = NS_NewISupportsArray(&mElements))) {
NS_ERROR("unable to create elements array");
return rv;
}
return NS_OK;
}
nsresult
nsRDFDOMNodeList::AppendNode(nsIDOMNode* aNode)
{
NS_PRECONDITION(aNode != nsnull, "null ptr");
if (! aNode)
return NS_ERROR_NULL_POINTER;
return mElements->AppendElement(aNode);
}

View File

@@ -0,0 +1,58 @@
/* -*- 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.0 (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.
*/
#ifndef nsRDFDOMNodeList_h__
#define nsRDFDOMNodeList_h__
#include "nsIDOMNodeList.h"
#include "nsIScriptObjectOwner.h"
class nsIDOMNode;
class nsISupportsArray;
class nsRDFDOMNodeList : public nsIDOMNodeList,
public nsIScriptObjectOwner
{
private:
nsISupports* mInner;
nsISupportsArray* mElements;
void* mScriptObject;
nsRDFDOMNodeList(void);
nsresult Init(void);
public:
static nsresult Create(nsRDFDOMNodeList** aResult);
virtual ~nsRDFDOMNodeList(void);
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIDOMNodeList interface
NS_DECL_IDOMNODELIST
// nsIScriptObjectOwner interface
NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject);
NS_IMETHOD SetScriptObject(void* aScriptObject);
// Implementation methods
nsresult AppendNode(nsIDOMNode* aNode);
};
#endif // nsRDFDOMNodeList_h__

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +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 = \
public \
memcache \
filecache \
mgr \
build \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -1,33 +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= \
public \
mgr \
memcache \
filecache \
build \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,51 +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.
#
DEPTH=..\..\..
MODULE=nkcache
MAKE_OBJ_TYPE=DLL
DLLNAME=nkcache
DLL=.\$(OBJDIR)\$(DLLNAME).dll
CPP_OBJS= \
.\$(OBJDIR)\nsNetDataCacheModule.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)
INCS = $(INCS) \
-I$(DEPTH)\netwerk\cache\memcache \
-I$(DEPTH)\netwerk\cache\filecache \
-I$(DEPTH)\netwerk\cache\mgr \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib

View File

@@ -1,49 +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 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

@@ -1,60 +0,0 @@
#
# 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 \
nsNetDiskCache.h \
nsIDBAccessor.h \
nsDBAccessor.h \
$(NULL)
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

@@ -1,416 +0,0 @@
/* -*- 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>
*/
/*
* This file is part of filecache implementation.
*
* nsIDBAccessor is a interface that shields all the direct database access
* method from nsNetDiskCache.
*
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
* uses dbm(Berkely) as the database.
*
* a nsDiskCacheRecord is mapped into two entries in the database,
* key->recordID
* recordID->metadata
*/
#include "nsDBAccessor.h"
#include "nscore.h"
#include "prtypes.h"
#include "plhash.h"
#include "nsCRT.h"
nsDBAccessor::nsDBAccessor() :
mDB(0) ,
mDBFile(0) ,
mSessionID(0) ,
mSessionCntr(0) ,
mDBFilesize(0)
{
mLastSyncTime = PR_IntervalNow() ;
NS_INIT_REFCNT();
}
nsDBAccessor::~nsDBAccessor()
{
Shutdown() ;
}
//
// Implement nsISupports methods
//
NS_IMPL_ISUPPORTS(nsDBAccessor, NS_GET_IID(nsIDBAccessor))
///////////////////////////////////////////////////////////
// nsIDBAccessor methods
NS_IMETHODIMP
nsDBAccessor::Init(nsIFileSpec* dbfile)
{
char* dbname ;
// this should cover all platforms.
dbfile->GetNativePath(&dbname) ;
mDBFile = dbfile ;
// 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 */
mDB = dbopen(dbname,
O_RDWR | O_CREAT ,
0600 ,
DB_HASH ,
& hash_info) ;
nsCRT::free(dbname) ;
if(!mDB)
return NS_ERROR_FAILURE ;
// set mSessionID
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SessionKey) ;
db_key.size = PL_strlen(SessionKey) ;
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 ;
}
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) ;
// initialize database filesize
return mDBFile->GetFileSize(&mDBFilesize) ;
}
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 ;
}
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") ;
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") ;
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)) {
return Sync() ;
}
else {
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") ;
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) {
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) {
return NS_ERROR_FAILURE ;
}
return Sync() ;
}
NS_IMETHODIMP
nsDBAccessor::GetID(const char* key, PRUint32 length, PRInt32* aID)
{
NS_ASSERTION(mDB, "no database") ;
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 ;
}
*aID = id ;
return Sync() ;
}
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 ;
DBT db_key, db_data ;
PRUint32 len = PL_strlen(SessionKey) ;
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 ;
}
/*
* returns the cached database file size.
* mDBFilesize will be updated during Sync().
*/
NS_IMETHODIMP
nsDBAccessor::GetDBFilesize(PRUint32* aSize)
{
*aSize = mDBFilesize ;
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::GetSpecialEntry(void** anEntry, PRUint32* aLength)
{
if(!anEntry)
return NS_ERROR_NULL_POINTER ;
*anEntry = nsnull ;
*aLength = 0 ;
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
db_key.size = PL_strlen(SpecialEntry) ;
int status = (*mDB->get)(mDB, &db_key, &db_data, 0) ;
if(status == -1) {
NS_ERROR("ERROR: failed get special entry in database.") ;
return NS_ERROR_FAILURE ;
}
if(status == 0) {
*anEntry = db_data.data ;
*aLength = db_data.size ;
}
return NS_OK ;
}
NS_IMETHODIMP
nsDBAccessor::SetSpecialEntry(void* anEntry, PRUint32 aLength)
{
DBT db_key, db_data ;
db_key.data = NS_CONST_CAST(char*, SpecialEntry) ;
db_key.size = PL_strlen(SpecialEntry) ;
db_data.data = anEntry ;
db_data.size = aLength ;
if(0 == (*mDB->put)(mDB, &db_key, &db_data, 0)) {
(*mDB->sync)(mDB, 0) ;
return NS_OK ;
}
else {
return NS_ERROR_FAILURE ;
}
}
/*
* sync routine is only called when the SyncInterval is reached. Otherwise
* it just returns. If db synced, the filesize will be updated at the
* same time.
*/
nsresult
nsDBAccessor::Sync(void)
{
PRIntervalTime time = PR_IntervalNow() ;
PRIntervalTime duration = time - mLastSyncTime ;
if (PR_IntervalToMilliseconds(duration) > SyncInterval) {
int status = (*mDB->sync)(mDB, 0) ;
if(status == 0) {
// printf("\tsynced\n") ;
mLastSyncTime = time ;
// update db filesize here
return mDBFile->GetFileSize(&mDBFilesize) ;
} else
return NS_ERROR_FAILURE ;
} else {
// printf("\tnot synced\n") ;
return NS_OK ;
}
}

View File

@@ -1,93 +0,0 @@
/*- 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>
*/
/*
* This file is part of filecache implementation.
*
* nsIDBAccessor is a interface that shields all the direct database access
* method from nsNetDiskCache.
*
* nsDBAccessor is a implementation of the nsIDBAccessor interface. It
* uses dbm(Berkely) as the database.
*
*/
#ifndef _NSIDBACCESSOR_H_
#define _NSIDBACCESSOR_H_
#include "nsIDBAccessor.h"
#include "mcom_db.h"
#include "prinrval.h"
#include "nsCOMPtr.h"
// bogus string for the key of session id
static const char * const SessionKey = "SK" ;
// bogus string for the size
static const char * const SpecialEntry = "SE" ;
// initial session id number
static const PRInt16 ini_sessionID = 0xff ;
static const PRUint16 SyncInterval = 1000 ;
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) ;
NS_IMETHOD GetDBFilesize(PRUint32* aSize) ;
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) ;
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) ;
protected:
nsresult Sync(void) ;
private:
DB * mDB ;
nsCOMPtr<nsIFileSpec> mDBFile ;
PRInt16 mSessionID ;
PRInt16 mSessionCntr ;
PRIntervalTime mLastSyncTime ;
PRUint32 mDBFilesize ; // cached DB filesize,
// updated on every sync for now
} ;
#endif // _NSIDBACCESSOR_H_

View File

@@ -1,108 +0,0 @@
/* -*- 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>
*/
/*
* This file is part of filecache implementation.
*
* It implements a simple iterator for the database, see nsDBAccessor.
*/
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
nsDBEnumerator::nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) :
m_DB(aDB) ,
m_DiskCache(aCache) ,
m_tempEntry(0) ,
m_tempEntry_length(0) ,
m_CacheEntry(0) ,
m_bReset(PR_TRUE)
{
NS_INIT_REFCNT();
}
nsDBEnumerator::~nsDBEnumerator()
{
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 ;
nsresult rv = m_DB->EnumEntry(&m_tempEntry, &m_tempEntry_length, m_bReset) ;
if(NS_FAILED(rv)) {
// do some error recovery
m_DiskCache->DBRecovery() ;
return rv ;
}
m_bReset = PR_FALSE ;
if(m_tempEntry && m_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(m_tempEntry, m_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

@@ -1,60 +0,0 @@
/* -*- 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>
*/
/*
* This file is part of filecache implementation.
*
* It implements a simple iterator for the database, see nsDBAccessor.
*/
#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
NS_DECL_NSISIMPLEENUMERATOR
nsDBEnumerator(nsIDBAccessor* aDB, nsNetDiskCache* aCache) ;
virtual ~nsDBEnumerator() ;
private:
nsCOMPtr<nsIDBAccessor> m_DB ;
nsCOMPtr<nsNetDiskCache> m_DiskCache ;
void * m_tempEntry ;
PRUint32 m_tempEntry_length ;
nsDiskCacheRecord* m_CacheEntry ;
PRBool m_bReset ;
};
#endif // _NS_DBENUMERATOR_H_

View File

@@ -1,456 +0,0 @@
/* -*- 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 "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();
NS_ASSERTION(mDiskCache, "Must have an nsNetDiskCache");
NS_ADDREF(mDiskCache);
}
// mem alloced. so caller should do free() on key.
NS_IMETHODIMP
nsDiskCacheRecord::Init(const char* key, PRUint32 length, PRInt32 ID)
{
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
mRecordID = ID ;
// 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] ;
PR_snprintf(dirName, 3, "%02x", (((PRUint32)mRecordID) % 32)) ;
mFile->AppendRelativeUnixPath(dirName) ;
PR_snprintf(filename, 9, "%08x", mRecordID) ;
mFile->AppendRelativeUnixPath(filename) ;
return NS_OK ;
}
nsDiskCacheRecord::~nsDiskCacheRecord()
{
if(mKey)
nsAllocator::Free(mKey) ;
if(mMetaData)
nsAllocator::Free(mMetaData) ;
if(mInfo)
nsAllocator::Free(mInfo) ;
NS_IF_RELEASE(mDiskCache);
}
//
// 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) ;
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 {
rv = mFile->Truncate(aStoredContentLength) ;
if(NS_FAILED(rv))
return rv ;
mDiskCache->m_StorageInUse -= (len - aStoredContentLength) ;
return NS_OK ;
}
}
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

@@ -1,71 +0,0 @@
/* -*- 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>
*/
#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, PRInt32 ID) ;
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 ;
nsNetDiskCache* mDiskCache ;
friend class nsDiskCacheRecordChannel ;
friend class nsDBEnumerator ;
friend class nsNetDiskCache ;
} ;
#endif // _NET_CACHEDDISKDATA_H_

View File

@@ -1,552 +0,0 @@
/* -*- 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>
*/
/*
* Most of the code are taken from nsFileChannel.
*/
#include "nsDiskCacheRecordChannel.h"
#include "nsIFileTransportService.h"
//#include "nsIIOService.h"
#include "nsIServiceManager.h"
#include "nsIURL.h"
#include "nsIOutputStream.h"
#include "netCore.h"
#include "nsIMIMEService.h"
#include "nsISupportsUtils.h"
//static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
static NS_DEFINE_CID(kFileTransportServiceCID, NS_FILETRANSPORTSERVICE_CID);
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kMIMEServiceCID, NS_MIMESERVICE_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() ;
NS_ADDREF(mRecord);
mRecord->mNumChannels++ ;
}
nsDiskCacheRecordChannel::~nsDiskCacheRecordChannel()
{
mRecord->mNumChannels-- ;
NS_RELEASE(mRecord);
}
// 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)
{
nsresult rv = mRecord->mFile->GetFileSpec(&mSpec) ;
#ifdef XP_MAC
// Don't assume we actually created a good file spec
FSSpec theSpec = mSpec.GetFSSpec();
if (!theSpec.name[0]) {
NS_ERROR("failed to create a file spec");
// Since we didn't actually create the file spec
// we return an error
return NS_ERROR_MALFORMED_URI;
}
#endif
return rv ;
}
nsresult
nsDiskCacheRecordChannel::NotifyStorageInUse(PRInt32 aBytesUsed)
{
return mRecord->mDiskCache->m_StorageInUse += aBytesUsed ;
}
// implement nsISupports
NS_IMPL_ISUPPORTS4(nsDiskCacheRecordChannel,
nsIChannel,
nsIRequest,
nsIStreamListener,
nsIStreamObserver)
// 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::GetOriginalURI(nsIURI* *aURI)
{
// FUR - might need to implement this - not sure
return NS_ERROR_NOT_IMPLEMENTED ;
}
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)
{
nsresult rv ;
if(mFileTransport)
return NS_ERROR_IN_PROGRESS ;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
if(NS_FAILED(rv)) return rv ;
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
if(NS_FAILED(rv))
return rv ;
// we don't need to worry about notification callbacks
rv = mFileTransport->OpenInputStream(aStartPosition, aReadCount, aResult) ;
if(NS_FAILED(rv))
mFileTransport = nsnull ;
return rv ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OpenOutputStream(PRUint32 startPosition,
nsIOutputStream* *aResult)
{
nsresult rv ;
NS_ENSURE_ARG(aResult) ;
if(mFileTransport)
return NS_ERROR_IN_PROGRESS ;
nsCOMPtr<nsIOutputStream> outputStream ;
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv) ;
if(NS_FAILED(rv)) return rv ;
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport)) ;
if(NS_FAILED(rv))
return rv ;
// we don't need to worry about notification callbacks
rv = mFileTransport->OpenOutputStream(startPosition, getter_AddRefs(outputStream)) ;
if(NS_FAILED(rv)) {
mFileTransport = nsnull ;
return rv ;
}
return WriteStreamWrapper::Create(this, outputStream, aResult) ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncOpen(nsIStreamObserver *observer,
nsISupports *ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED ;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::AsyncRead(PRUint32 aStartPosition,
PRInt32 aReadCount,
nsISupports *aContext,
nsIStreamListener *aListener)
{
nsresult rv ;
if(mFileTransport)
return NS_ERROR_IN_PROGRESS ;
mRealListener = aListener;
nsCOMPtr<nsIStreamListener> tempListener = this;
if (mLoadGroup) {
nsCOMPtr<nsILoadGroupListenerFactory> factory;
//
// Create a load group "proxy" listener...
//
rv = mLoadGroup->GetGroupListenerFactory(getter_AddRefs(factory));
if (factory) {
nsIStreamListener *newListener;
rv = factory->CreateLoadGroupListener(mRealListener, &newListener);
if (NS_SUCCEEDED(rv)) {
mRealListener = newListener;
NS_RELEASE(newListener);
}
}
rv = mLoadGroup->AddChannel(this, nsnull);
if (NS_FAILED(rv)) return rv;
}
NS_WITH_SERVICE(nsIFileTransportService, fts, kFileTransportServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = fts->CreateTransport(mSpec, "load", 0, 0, getter_AddRefs(mFileTransport));
if (NS_FAILED(rv)) return rv;
// no callbacks
rv = mFileTransport->AsyncRead(aStartPosition,
aReadCount,
aContext,
tempListener);
if (NS_FAILED(rv)) {
// release the transport so that we don't think we're in progress
mFileTransport = nsnull;
}
return rv;
}
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)
{
// 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::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
// Not required to be implemented, since it is implemented by cache manager
NS_ASSERTION(0, "nsDiskCacheRecordChannel method unexpectedly called");
return NS_ERROR_NOT_IMPLEMENTED;
}
#define DUMMY_TYPE "text/html"
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentType(char * *aContentType)
{
nsresult rv ;
if (mSpec.IsDirectory()) {
*aContentType = nsCRT::strdup("application/http-index-format");
return *aContentType ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
else {
// I wish I can make this simplier
char* urlStr ;
mRecord->mFile->GetURLString(&urlStr) ;
// file: URLs (currently) have no additional structure beyond that provided by standard
// URLs, so there is no "outer" given to CreateInstance
nsCOMPtr<nsIURI> url;
rv = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
NS_GET_IID(nsIURI),
//(void**)&url);
getter_AddRefs(url)) ;
if (NS_FAILED(rv)) return rv;
rv = url->SetSpec((char*)urlStr);
if (NS_FAILED(rv))
return rv;
NS_WITH_SERVICE(nsIMIMEService, MIMEService, kMIMEServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
rv = MIMEService->GetTypeFromURI(url, aContentType);
if (NS_SUCCEEDED(rv)) return rv;
}
// if all else fails treat it as text/html?
*aContentType = nsCRT::strdup(DUMMY_TYPE);
if (!*aContentType) {
return NS_ERROR_OUT_OF_MEMORY;
} else {
return NS_OK;
}
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::GetContentLength(PRInt32 *aContentLength)
{
nsresult rv;
PRUint32 length;
rv = mRecord->mFile->GetFileSize(&length);
if (NS_SUCCEEDED(rv)) {
*aContentLength = (PRInt32)length;
} else {
*aContentLength = -1;
}
return rv;
}
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::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;
}
////////////////////////////////////////////////////////////////////////////////
// nsIStreamListener methods:
////////////////////////////////////////////////////////////////////////////////
NS_IMETHODIMP
nsDiskCacheRecordChannel::OnStartRequest(nsIChannel* transportChannel, nsISupports* context)
{
NS_ASSERTION(mRealListener, "No listener...");
return mRealListener->OnStartRequest(this, context);
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OnStopRequest(nsIChannel* transportChannel, nsISupports* context,
nsresult aStatus, const PRUnichar* aMsg)
{
nsresult rv;
rv = mRealListener->OnStopRequest(this, context, aStatus, aMsg);
if (mLoadGroup) {
if (NS_SUCCEEDED(rv)) {
mLoadGroup->RemoveChannel(this, context, aStatus, aMsg);
}
}
// Release the reference to the consumer stream listener...
mRealListener = null_nsCOMPtr();
mFileTransport = null_nsCOMPtr();
return rv;
}
NS_IMETHODIMP
nsDiskCacheRecordChannel::OnDataAvailable(nsIChannel* transportChannel, nsISupports* context,
nsIInputStream *aIStream, PRUint32 aSourceOffset,
PRUint32 aLength)
{
nsresult rv;
rv = mRealListener->OnDataAvailable(this, context, aIStream,
aSourceOffset, aLength);
//
// If the connection is being aborted cancel the transport. This will
// insure that the transport will go away even if it is blocked waiting
// for the consumer to empty the pipe...
//
if (NS_FAILED(rv)) {
mFileTransport->Cancel();
}
return rv;
}

View File

@@ -1,76 +0,0 @@
/* -*- 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>
*/
#ifndef _ns_DiskCacheRecordChannel_h_
#define _ns_DiskCacheRecordChannel_h_
#include "nsIChannel.h"
#include "nsCOMPtr.h"
#include "nsDiskCacheRecord.h"
#include "nsIStreamListener.h"
/*
* This class is plagiarized from nsMemCacheChannel
*/
class nsDiskCacheRecordChannel : public nsIChannel,
public nsIStreamListener
{
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
// Declare nsIStreamObserver methods
NS_DECL_NSISTREAMOBSERVER
// Declare nsIStreamListener methods
NS_DECL_NSISTREAMLISTENER
nsresult Init(void) ;
private:
nsresult NotifyStorageInUse(PRInt32 aBytesUsed) ;
nsDiskCacheRecord* mRecord ;
nsCOMPtr<nsILoadGroup> mLoadGroup ;
nsCOMPtr<nsISupports> mOwner ;
nsCOMPtr<nsIChannel> mFileTransport ;
nsFileSpec mSpec ;
nsCOMPtr<nsIStreamListener> mRealListener;
friend class WriteStreamWrapper ;
} ;
#endif // _ns_DiskCacheRecordChannel_h_

View File

@@ -1,66 +0,0 @@
/* -*- 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>
*/
#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 ;
NS_IMETHOD GetDBFilesize(PRUint32* aSize) = 0 ;
NS_IMETHOD GetSpecialEntry(void** anEntry, PRUint32 *aLength) = 0 ;
NS_IMETHOD SetSpecialEntry(void* anEntry, PRUint32 aLength) = 0 ;
} ;
#endif // _NS_IDBACCESSOR_H_

View File

@@ -1,704 +0,0 @@
/* -*- 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 "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 "prlog.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsIPref.h"
#include "mcom_db.h"
#include "nsDBEnumerator.h"
#include "nsDiskCacheRecord.h"
#include "netCore.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
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_DBCorrupted(PR_FALSE)
{
// set it to INF for now
m_MaxEntries = (PRUint32)-1 ;
NS_INIT_REFCNT();
}
nsNetDiskCache::~nsNetDiskCache()
{
SetSpecialEntry() ;
NS_IF_RELEASE(m_DB) ;
// 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_DBCorrupted) {
nsFileSpec cacheFolder ;
m_pDiskCacheFolder->GetFileSpec(&cacheFolder) ;
char nameInt[6] ;
for(nsDirectoryIterator di(cacheFolder, PR_FALSE); di.Exists(); di++) {
char* filename = di.Spec().GetLeafName() ;
char* pname = nameInt ;
pname = PL_strncpyz(pname, filename, 6) ;
if(PL_strcmp(pname, "trash") == 0)
RemoveFolder(di.Spec()) ;
nsCRT::free(filename) ;
}
}
}
NS_IMETHODIMP
nsNetDiskCache::Init(void)
{
nsresult rv ;
// don't initialize if no cache folder is set.
if(!m_pDiskCacheFolder) return NS_OK ;
if(!m_DB) {
m_DB = new nsDBAccessor() ;
if(!m_DB)
return NS_ERROR_OUT_OF_MEMORY ;
else
NS_ADDREF(m_DB) ;
}
// create cache sub directories
nsCOMPtr<nsIFileSpec> cacheSubDir;
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) ;
CreateDir(cacheSubDir);
}
return InitDB() ;
}
NS_IMETHODIMP
nsNetDiskCache::InitDB(void)
{
nsresult rv ;
if(!m_DBFile) {
NS_NewFileSpec(getter_AddRefs(m_DBFile)) ;
if(!m_DBFile)
return NS_ERROR_OUT_OF_MEMORY ;
}
rv = m_DBFile->FromFileSpec(m_pDiskCacheFolder) ;
if(NS_FAILED(rv))
return rv ;
m_DBFile->AppendRelativeUnixPath("cache.db") ;
rv = m_DB->Init(m_DBFile) ;
if(rv == NS_ERROR_FAILURE) {
// try recovery if error
DBRecovery() ;
}
rv = GetSpecialEntry() ;
if(rv == NS_ERROR_FAILURE) {
// try recovery if error
DBRecovery() ;
}
return rv ;
}
//////////////////////////////////////////////////////////////////////////
// nsISupports methods
NS_IMPL_ISUPPORTS3(nsNetDiskCache,
nsINetDataDiskCache,
nsINetDataCache,
nsISupports)
///////////////////////////////////////////////////////////////////////////
// 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 ;
nsresult rv = m_DB->GetID(key, length, &id) ;
if(NS_FAILED(rv)) {
// try recovery if error
DBRecovery() ;
return rv ;
}
void* info = 0 ;
PRUint32 info_size = 0 ;
rv = m_DB->Get(id, &info, &info_size) ;
if(NS_SUCCEEDED(rv) && info)
*_retval = PR_TRUE ;
if(NS_FAILED(rv)) {
// try recovery if error
DBRecovery() ;
}
return rv ;
}
/* 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 ;
rv = m_DB->GetID(key, length, &id) ;
if(NS_FAILED(rv)) {
// try recovery if error
DBRecovery() ;
return rv ;
}
// construct an empty record
nsDiskCacheRecord* newRecord = new nsDiskCacheRecord(m_DB, this) ;
if(!newRecord)
return NS_ERROR_OUT_OF_MEMORY ;
rv = newRecord->Init(key, length, id) ;
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) {
// this is a previously cached record
nsresult r1 ;
r1 = newRecord->RetrieveInfo(info, info_size) ;
if(NS_SUCCEEDED(rv))
return NS_OK ;
else {
// probably a bad one
NS_RELEASE(newRecord) ;
*_retval = nsnull ;
return r1;
}
} else if (NS_SUCCEEDED(rv) && !info) {
// this is a new record.
m_NumEntries ++ ;
return NS_OK ;
} else {
// database error.
DBRecovery() ;
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") ;
DBRecovery() ;
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)
{
NS_ASSERTION(m_DB, "no db.") ;
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)
{
NS_ASSERTION(m_DB, "no db.") ;
PRUint32 total_size = m_StorageInUse ;
/*
PRUint32 len = 0 ;
// add the size of the db.
m_DB->GetDBFilesize(&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)
{
NS_ASSERTION(m_DB, "no db.") ;
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
// remove all the sub folders
nsFileSpec cacheSubDir;
for (int i=0; i < 32; i++) {
m_pDiskCacheFolder->GetFileSpec(&cacheSubDir) ;
char dirName[3];
PR_snprintf (dirName, 3, "%0.2x", i);
cacheSubDir += dirName ;
RemoveFolder(cacheSubDir) ;
}
// don't forget the db file itself
m_DB->Shutdown() ;
nsFileSpec dbfile ;
m_DBFile->GetFileSpec(&dbfile) ;
dbfile.Delete(PR_TRUE) ;
// reinitilize
return Init() ;
}
//////////////////////////////////////////////////////////////////
// nsINetDataDiskCache methods
NS_IMETHODIMP
nsNetDiskCache::GetDiskCacheFolder(nsIFileSpec * *aDiskCacheFolder)
{
*aDiskCacheFolder = nsnull ;
NS_ASSERTION(m_pDiskCacheFolder, "no cache folder.") ;
*aDiskCacheFolder = m_pDiskCacheFolder ;
NS_ADDREF(*aDiskCacheFolder) ;
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetDiskCacheFolder(nsIFileSpec * aDiskCacheFolder)
{
if(!m_pDiskCacheFolder) {
NS_NewFileSpec(getter_AddRefs(m_pDiskCacheFolder));
if(!m_pDiskCacheFolder)
return NS_ERROR_OUT_OF_MEMORY ;
m_pDiskCacheFolder = aDiskCacheFolder ;
return Init() ;
}
else {
char *newfolder, *oldfolder ;
m_pDiskCacheFolder->GetNativePath(&oldfolder) ;
aDiskCacheFolder->GetNativePath(&newfolder) ;
if(PL_strcmp(newfolder, oldfolder) != 0) {
m_pDiskCacheFolder = aDiskCacheFolder ;
// do we need to blow away old cache before building a new one?
// return RemoveAll() ;
m_DB->Shutdown() ;
return Init() ;
} else
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 ;
nsresult rv = dir_spec->GetParent(getter_AddRefs(p_spec)) ;
if(NS_FAILED(rv))
return rv ;
p_spec->Exists(&does_exist) ;
if(!does_exist) {
CreateDir(p_spec) ;
rv = dir_spec->CreateDir() ;
if(NS_FAILED(rv))
return rv ;
}
else {
rv = dir_spec->CreateDir() ;
if(NS_FAILED(rv))
return rv ;
}
return NS_OK ;
}
// 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.
NS_IMETHODIMP
nsNetDiskCache::GetSpecialEntry(void)
{
void* pInfo ;
PRUint32 InfoSize ;
nsresult rv = m_DB->GetSpecialEntry(&pInfo, &InfoSize) ;
if(NS_FAILED(rv))
return rv ;
if(!pInfo && InfoSize == 0) {
// must be a new DB
m_NumEntries = 0 ;
m_StorageInUse = 0 ;
}
else {
char * cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
// get m_NumEntries
COPY_INT32(&m_NumEntries, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
// get m_StorageInUse
COPY_INT32(&m_StorageInUse, cur_ptr) ;
cur_ptr += sizeof(PRUint32) ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
}
return NS_OK ;
}
NS_IMETHODIMP
nsNetDiskCache::SetSpecialEntry(void)
{
PRUint32 InfoSize ;
InfoSize = sizeof m_NumEntries ;
InfoSize += sizeof m_StorageInUse ;
void* pInfo = nsAllocator::Alloc(InfoSize*sizeof(char)) ;
if(!pInfo)
return NS_ERROR_OUT_OF_MEMORY ;
char* cur_ptr = NS_STATIC_CAST(char*, pInfo) ;
COPY_INT32(cur_ptr, &m_NumEntries) ;
cur_ptr += sizeof(PRUint32) ;
COPY_INT32(cur_ptr, &m_StorageInUse) ;
cur_ptr += sizeof(PRUint32) ;
PR_ASSERT(cur_ptr == NS_STATIC_CAST(char*, pInfo) + InfoSize);
return m_DB->SetSpecialEntry(pInfo, InfoSize) ;
}
// this routine will be called everytime we have a db corruption.
// m_DB will be re-initialized, m_StorageInUse and m_NumEntries will
// be reset.
NS_IMETHODIMP
nsNetDiskCache::DBRecovery(void)
{
// rename all the sub cache dirs and remove them later during dtor.
nsresult rv = RenameCacheSubDirs() ;
if(NS_FAILED(rv))
return rv ;
// remove corrupted db file, don't care if db->shutdown fails or not.
m_DB->Shutdown() ;
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 DB
return InitDB() ;
}
// this routine will add string "trash" to current CacheSubDir names.
// e.g. 00->trash00, 1f->trash1f. and update the m_DBCorrupted.
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 oldName[3], newName[8];
PR_snprintf(oldName, 3, "%0.2x", i) ;
cacheSubDir->AppendRelativeUnixPath(oldName) ;
// re-name the directory
PR_snprintf(newName, 8, "trash%0.2x", i) ;
rv = cacheSubDir->Rename(newName) ;
if(NS_FAILED(rv))
// TODO, error checking
return NS_ERROR_FAILURE ;
}
// update m_DBCorrupted
m_DBCorrupted = PR_TRUE ;
return NS_OK ;
}
// this routine is used by dtor and RemoveAll() to clean up dirs.
NS_IMETHODIMP
nsNetDiskCache::RemoveFolder(nsFileSpec aFolder)
{
for(nsDirectoryIterator di(aFolder, PR_FALSE); di.Exists(); di++) {
di.Spec().Delete(PR_TRUE) ;
}
aFolder.Delete(PR_FALSE) ; // recursive delete
return NS_OK ;
}

View File

@@ -1,91 +0,0 @@
/* -*- 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>
*/
/*
* This file is part of filecache implementation.
*
* nsNetDiskCache is the main disk cache module that will create
* the cache database, and then store and retrieve nsDiskCacheRecord
* objects from it. It also contains some basic error recovery procedure.
*/
#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 GetSpecialEntry(void) ;
NS_IMETHOD SetSpecialEntry(void) ;
NS_IMETHOD RenameCacheSubDirs(void) ;
NS_IMETHOD DBRecovery(void) ;
NS_IMETHOD RemoveFolder(nsFileSpec aFolder) ;
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
PRBool m_DBCorrupted ;
friend class nsDiskCacheRecord ;
friend class nsDiskCacheRecordChannel ;
friend class nsDBEnumerator ;
} ;
#endif /* __gen_nsNetDiskCache_h__ */

View File

@@ -1,32 +0,0 @@
/*
* 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

@@ -1,836 +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.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,334 +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 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

@@ -1,83 +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 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

@@ -1,36 +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 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

@@ -1,462 +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 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), mAvailable(0), mChannel(aChannel), mAborted(PR_FALSE), mSuspended(PR_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 = PR_TRUE;
return mStreamListener->OnStopRequest(mChannel, mContext, NS_BINDING_ABORTED, nsnull);
}
nsresult
Suspend(void) { mSuspended = PR_TRUE; return NS_OK; }
nsresult
Resume(void) {
if (!mSuspended)
return NS_ERROR_FAILURE;
mSuspended = PR_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 = PR_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
PRBool mAborted; // Abort() has been called
PRBool 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");
return NS_ERROR_NOT_IMPLEMENTED;
}
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

@@ -1,61 +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 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

@@ -1,164 +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 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

@@ -1,65 +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 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 "nsIStorageStream.h"
#include "nsCOMPtr.h"
class nsMemCache;
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

@@ -1,55 +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 = nkcache
LIBRARY_NAME = nkcachemgr_s
REQUIRES = nspr
EXPORTS = \
nsCacheManager.h \
$(NULL)
CPPSRCS = \
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

@@ -1,45 +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 = nkcache
LIBRARY_NAME = nkcachemgr_s
CPP_OBJS = \
.\$(OBJDIR)\nsCacheManager.obj \
.\$(OBJDIR)\nsCachedNetData.obj \
.\$(OBJDIR)\nsReplacementPolicy.obj \
.\$(OBJDIR)\nsCacheEntryChannel.obj \
$(NULL)
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

@@ -1,261 +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 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() {
mCacheEntry->NoteDownloadTime(mStartTime, PR_Now());
mCacheEntry->ClearFlag(nsCachedNetData::UPDATE_IN_PROGRESS);
}
NS_DECL_ISUPPORTS
NS_IMETHOD Close() {
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.get() : NS_STATIC_CAST(nsIChannel*, 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

@@ -1,82 +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 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_

View File

@@ -1,497 +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 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 "nsINetDataCache.h"
#include "nsCacheManager.h"
#include "nsCachedNetData.h"
#include "nsReplacementPolicy.h"
#include "nsString.h"
#include "nsIURI.h"
#include "nsHashtable.h"
#include "nsIComponentManager.h"
#include "nsINetDataDiskCache.h"
// Limit the number of entries in the cache to conserve memory space
// in the nsReplacementPolicy code
#define MAX_MEM_CACHE_ENTRIES 800
#define MAX_DISK_CACHE_ENTRIES 3200
// Cache capacities in MB, overridable via APIs
#define DEFAULT_MEMORY_CACHE_CAPACITY 1024
#define DEFAULT_DISK_CACHE_CAPACITY 10000
#define CACHE_HIGH_WATER_MARK(capacity) ((PRUint32)(0.98 * (capacity)))
#define CACHE_LOW_WATER_MARK(capacity) ((PRUint32)(0.97 * (capacity)))
nsCacheManager* gCacheManager = 0;
NS_IMPL_ISUPPORTS(nsCacheManager, NS_GET_IID(nsINetDataCacheManager))
nsCacheManager::nsCacheManager()
: mActiveCacheRecords(0),
mDiskCacheCapacity(DEFAULT_DISK_CACHE_CAPACITY),
mMemCacheCapacity(DEFAULT_MEMORY_CACHE_CAPACITY)
{
NS_ASSERTION(!gCacheManager, "Multiple cache managers created");
gCacheManager = this;
NS_INIT_REFCNT();
}
nsCacheManager::~nsCacheManager()
{
gCacheManager = 0;
delete mActiveCacheRecords;
delete mMemSpaceManager;
delete mDiskSpaceManager;
}
nsresult
nsCacheManager::Init()
{
nsresult rv;
mActiveCacheRecords = new nsHashtable(64);
if (!mActiveCacheRecords)
return NS_ERROR_OUT_OF_MEMORY;
// Instantiate the memory cache component
rv = nsComponentManager::CreateInstance(NS_NETWORK_MEMORY_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mMemCache));
if (NS_FAILED(rv))
return rv;
rv = nsComponentManager::CreateInstance(NS_NETWORK_FLAT_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mFlatCache));
if (NS_FAILED(rv)) {
// For now, we don't require a flat cache module to be present
if (rv != NS_ERROR_FACTORY_NOT_REGISTERED)
return rv;
}
#ifdef FILE_CACHE_IS_READY
// Instantiate the file cache component
rv = nsComponentManager::CreateInstance(NS_NETWORK_FILE_CACHE_PROGID,
nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(mFileCache));
if (NS_FAILED(rv)) {
NS_WARNING("No disk cache present");
}
#endif
// Set up linked list of caches in search order
mCacheSearchChain = mMemCache;
if (mFlatCache) {
mMemCache->SetNextCache(mFlatCache);
mFlatCache->SetNextCache(mFileCache);
} else {
mMemCache->SetNextCache(mFileCache);
}
// TODO - Load any extension caches here
// Initialize replacement policy for memory cache module
mMemSpaceManager = new nsReplacementPolicy;
if (!mMemSpaceManager)
return NS_ERROR_OUT_OF_MEMORY;
rv = mMemSpaceManager->Init(MAX_MEM_CACHE_ENTRIES);
if (NS_FAILED(rv)) return rv;
rv = mMemSpaceManager->AddCache(mMemCache);
// Initialize replacement policy for disk cache modules (file
// cache and flat cache)
mDiskSpaceManager = new nsReplacementPolicy;
if (!mDiskSpaceManager)
return NS_ERROR_OUT_OF_MEMORY;
rv = mDiskSpaceManager->Init(MAX_DISK_CACHE_ENTRIES);
if (NS_FAILED(rv)) return rv;
if (mFileCache) {
rv = mDiskSpaceManager->AddCache(mFileCache);
if (NS_FAILED(rv)) return rv;
}
if (mFlatCache) {
rv = mDiskSpaceManager->AddCache(mFlatCache);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetCachedNetData(const char *aUriSpec, const char *aSecondaryKey,
PRUint32 aSecondaryKeyLength,
PRUint32 aFlags, nsICachedNetData* *aResult)
{
nsCachedNetData *cachedData;
nsresult rv;
nsINetDataCache *cache;
nsReplacementPolicy *spaceManager;
if (aFlags & CACHE_AS_FILE) {
cache = mFileCache;
spaceManager = mDiskSpaceManager;
// Ensure that cache is initialized
if (mDiskCacheCapacity == (PRUint32)-1)
return NS_ERROR_NOT_AVAILABLE;
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
cache = mMemCache;
spaceManager = mMemSpaceManager;
} else {
cache = mFlatCache ? mFlatCache : mFileCache;
spaceManager = mDiskSpaceManager;
}
// Construct the cache key by appending the secondary key to the URI spec
nsCAutoString cacheKey(aUriSpec);
// Insert NUL at end of URI spec
cacheKey += '\0';
if (aSecondaryKey)
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
nsStringKey key(cacheKey);
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
// There is no existing instance of nsCachedNetData for this URL.
// Make one from the corresponding record in the cache module.
if (cachedData) {
NS_ASSERTION(cache == cachedData->mCache,
"Cannot yet handle simultaneously active requests for the "
"same URL using different caches");
NS_ADDREF(cachedData);
} else {
rv = spaceManager->GetCachedNetData(cacheKey.GetBuffer(), cacheKey.Length(),
cache, &cachedData);
if (NS_FAILED(rv)) return rv;
mActiveCacheRecords->Put(&key, cachedData);
}
*aResult = cachedData;
return NS_OK;
}
// Remove this cache entry from the list of active ones
nsresult
nsCacheManager::NoteDormant(nsCachedNetData* aEntry)
{
nsresult rv;
PRUint32 keyLength;
char* key;
nsCOMPtr<nsINetDataCacheRecord> record;
nsCachedNetData* deletedEntry;
rv = aEntry->GetRecord(getter_AddRefs(record));
if (NS_FAILED(rv)) return rv;
rv = record->GetKey(&keyLength, &key);
if (NS_FAILED(rv)) return rv;
nsStringKey hashTableKey(nsCString(key, keyLength));
deletedEntry = (nsCachedNetData*)gCacheManager->mActiveCacheRecords->Remove(&hashTableKey);
// NS_ASSERTION(deletedEntry == aEntry, "Hash table inconsistency");
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::Contains(const char *aUriSpec, const char *aSecondaryKey,
PRUint32 aSecondaryKeyLength,
PRUint32 aFlags, PRBool *aResult)
{
nsINetDataCache *cache;
nsReplacementPolicy *spaceManager;
nsCachedNetData *cachedData;
if (aFlags & CACHE_AS_FILE) {
cache = mFileCache;
spaceManager = mDiskSpaceManager;
} else if ((aFlags & BYPASS_PERSISTENT_CACHE) ||
(!mFileCache && !mFlatCache) || !mDiskCacheCapacity) {
cache = mMemCache;
spaceManager = mMemSpaceManager;
} else {
cache = mFlatCache ? mFlatCache : mFileCache;
spaceManager = mDiskSpaceManager;
}
// Construct the cache key by appending the secondary key to the URI spec
nsCAutoString cacheKey(aUriSpec);
// Insert NUL between URI spec and secondary key
cacheKey += '\0';
cacheKey.Append(aSecondaryKey, aSecondaryKeyLength);
// Locate the record using (URI + secondary key)
nsStringKey key(cacheKey);
cachedData = (nsCachedNetData*)mActiveCacheRecords->Get(&key);
if (cachedData && (cache == cachedData->mCache)) {
*aResult = PR_TRUE;
return NS_OK;
} else {
// No active cache entry, see if there is a dormant one
return cache->Contains(cacheKey.GetBuffer(), cacheKey.Length(), aResult);
}
}
NS_IMETHODIMP
nsCacheManager::GetNumEntries(PRUint32 *aNumEntries)
{
nsresult rv;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsISupports> cacheSupports;
nsCOMPtr<nsINetDataCache> cache;
PRUint32 totalEntries = 0;
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(cacheSupports));
cache = do_QueryInterface(cacheSupports);
PRUint32 numEntries;
rv = cache->GetNumEntries(&numEntries);
if (NS_FAILED(rv)) return rv;
totalEntries += numEntries;
}
*aNumEntries = totalEntries;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::NewCacheEntryIterator(nsISimpleEnumerator* *aResult)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
class CacheEnumerator : public nsISimpleEnumerator
{
public:
CacheEnumerator(nsINetDataCache* aFirstCache):mCache(aFirstCache)
{ NS_INIT_REFCNT(); }
virtual ~CacheEnumerator() {};
NS_DECL_ISUPPORTS
NS_IMETHODIMP
HasMoreElements(PRBool* aMoreElements) {
*aMoreElements = (mCache != 0);
return NS_OK;
}
NS_IMETHODIMP
GetNext(nsISupports* *aSupports) {
*aSupports = mCache;
if (!mCache)
return NS_ERROR_FAILURE;
NS_ADDREF(*aSupports);
nsCOMPtr<nsINetDataCache> nextCache;
nsresult rv = mCache->GetNextCache(getter_AddRefs(nextCache));
mCache = nextCache;
return rv;
}
private:
nsCOMPtr<nsINetDataCache> mCache;
};
NS_IMPL_ISUPPORTS(CacheEnumerator, NS_GET_IID(nsISimpleEnumerator))
NS_IMETHODIMP
nsCacheManager::NewCacheModuleIterator(nsISimpleEnumerator* *aResult)
{
*aResult = new CacheEnumerator(mCacheSearchChain);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::RemoveAll(void)
{
nsresult rv, result;
nsCOMPtr<nsISimpleEnumerator> iterator;
nsCOMPtr<nsINetDataCache> cache;
nsCOMPtr<nsISupports> iSupports;
result = NS_OK;
rv = NewCacheModuleIterator(getter_AddRefs(iterator));
if (NS_FAILED(rv)) return rv;
while (1) {
PRBool notDone;
rv = iterator->HasMoreElements(&notDone);
if (NS_FAILED(rv)) return rv;
if (!notDone)
break;
iterator->GetNext(getter_AddRefs(iSupports));
cache = do_QueryInterface(iSupports);
PRUint32 cacheFlags;
rv = cache->GetFlags(&cacheFlags);
if (NS_FAILED(rv)) return rv;
if ((cacheFlags & nsINetDataCache::READ_ONLY) == 0) {
rv = cache->RemoveAll();
if (NS_FAILED(rv))
result = rv;
}
}
return result;
}
nsresult
nsCacheManager::LimitMemCacheSize()
{
nsresult rv;
nsReplacementPolicy* spaceManager;
NS_ASSERTION(gCacheManager, "No cache manager");
spaceManager = gCacheManager->mMemSpaceManager;
PRUint32 occupancy;
rv = spaceManager->GetStorageInUse(&occupancy);
if (NS_FAILED(rv)) return rv;
PRUint32 memCacheCapacity = gCacheManager->mMemCacheCapacity;
if (occupancy > CACHE_HIGH_WATER_MARK(memCacheCapacity))
return spaceManager->Evict(CACHE_LOW_WATER_MARK(memCacheCapacity));
return NS_OK;
}
nsresult
nsCacheManager::LimitDiskCacheSize()
{
nsresult rv;
nsReplacementPolicy* spaceManager;
NS_ASSERTION(gCacheManager, "No cache manager");
spaceManager = gCacheManager->mDiskSpaceManager;
PRUint32 occupancy;
rv = spaceManager->GetStorageInUse(&occupancy);
if (NS_FAILED(rv)) return rv;
PRUint32 diskCacheCapacity = gCacheManager->mDiskCacheCapacity;
if (occupancy > CACHE_HIGH_WATER_MARK(diskCacheCapacity))
return spaceManager->Evict(CACHE_LOW_WATER_MARK(diskCacheCapacity));
return NS_OK;
}
nsresult
nsCacheManager::LimitCacheSize()
{
nsresult rv;
rv = LimitDiskCacheSize();
if (NS_FAILED(rv)) return rv;
rv = LimitMemCacheSize();
if (NS_FAILED(rv)) return rv;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetMemCacheCapacity(PRUint32 aCapacity)
{
mMemCacheCapacity = aCapacity;
LimitCacheSize();
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetMemCacheCapacity(PRUint32* aCapacity)
{
NS_ENSURE_ARG_POINTER(aCapacity);
*aCapacity = mMemCacheCapacity;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetDiskCacheCapacity(PRUint32 aCapacity)
{
mDiskCacheCapacity = aCapacity;
LimitCacheSize();
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::GetDiskCacheCapacity(PRUint32* aCapacity)
{
NS_ENSURE_ARG_POINTER(aCapacity);
*aCapacity = mDiskCacheCapacity;
return NS_OK;
}
NS_IMETHODIMP
nsCacheManager::SetDiskCacheFolder(nsIFileSpec* aFolder)
{
NS_ENSURE_ARG(aFolder);
if (!mFileCache)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsINetDataDiskCache> fileCache;
fileCache = do_QueryInterface(mFileCache);
return fileCache->SetDiskCacheFolder(aFolder);
}
NS_IMETHODIMP
nsCacheManager::GetDiskCacheFolder(nsIFileSpec* *aFolder)
{
NS_ENSURE_ARG(aFolder);
if (!mFileCache)
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsINetDataDiskCache> fileCache;
fileCache = do_QueryInterface(mFileCache);
return fileCache->GetDiskCacheFolder(aFolder);
}

View File

@@ -1,100 +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 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 "nsINetDataCache.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

@@ -1,242 +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 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(PRBool 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,666 +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 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;
// If the data arrives so fast that it can not be timed due to the clock
// granularity, assume a data arrival duration of 10 ms
if (!duration)
duration = 10000;
// Compute download rate in kB/s
rate = mLogicalLength / (duration * (1e-6 * 1024.0));
if (mDownloadRate) {
// Exponentially smooth download rate
const double alpha = 0.5;
mDownloadRate = (float)(mDownloadRate * alpha + rate * (1.0 - alpha));
} else {
mDownloadRate = (float)rate;
}
}
// 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;
PRBool 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 = PR_TRUE;
halfLife = mStaleTime - docTime;
} else {
potentiallyStale = PR_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);
if (mDownloadRate)
mProfit /= 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

@@ -1,136 +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 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,43 +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@
MODULE = nkcache
include $(DEPTH)/config/autoconf.mk
XPIDLSRCS = \
nsICachedNetData.idl \
nsINetDataCacheManager.idl \
nsINetDataCache.idl \
nsINetDataCacheRecord.idl \
nsINetDataDiskCache.idl \
nsIStreamAsFile.idl \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/rules.mk

View File

@@ -1,41 +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):
MODULE = nkcache
DEPTH = ..\..\..
include <$(DEPTH)/config/config.mak>
EXPORTS = \
$(NULL)
XPIDLSRCS = \
.\nsICachedNetData.idl \
.\nsINetDataCacheManager.idl \
.\nsINetDataCache.idl \
.\nsINetDataCacheRecord.idl \
.\nsINetDataDiskCache.idl \
.\nsIStreamAsFile.idl \
$(NULL)
include <$(DEPTH)/config/rules.mak>

View File

@@ -1,229 +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 "nsrootidl.idl"
#include "nsISupports.idl"
interface nsIFileSpec;
interface nsIURI;
interface nsIObserver;
interface nsIChannel;
interface nsINetDataCache;
interface nsINetDataCacheRecord;
interface nsILoadGroup;
interface nsIStreamListener;
/**
* The nsICachedNetData interface represents a single entry in a database that
* caches data retrieved from the network. This interface is implemented by the
* cache manager on top of the low-level nsINetDataCacheRecord and
* nsINetDataCache interfaces that are implemented by the database.
*
* Each cache record may contain both content and metadata. The content may
* be, for example, GIF image data or HTML, and it is accessed through
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
* headers among other things, is stored as a byte array. Each entry in the
* cache is indexed by two different keys: a record id number and a key created
* by combining the URI with a "secondary key", e.g. HTTP post data.
*
* @See nsINetDataCacheRecord
* @See nsINetDataCache
* @See nsINetDataDiskCache
* @See nsINetDataCacheManager
*/
[scriptable, uuid(6aeb2a40-6d43-11d3-90c8-000064657374)]
interface nsICachedNetData : nsISupports
{
/**
* String form of the URI provided as an argument to the call to
* nsINetDataCacheManager::GetCachedNetData() that created this record.
*/
readonly attribute string uriSpec;
/**
* Getter for the opaque secondary database key provided as an argument to
* the call to nsINetDataCacheManager::GetCachedNetData() that created this
* record.
*/
void getSecondaryKey(out unsigned long length,
[retval, size_is(length)] out string secondaryKey);
/**
* This flag may be set by a protocol handler to indicate that it supports
* partial fetching of data. In that case, the cache manager is permitted
* to truncate the entry's content to accommodate incoming data for other
* cache entries rather than deleting it wholesale.
*/
attribute boolean allowPartial;
/**
* This flag indicates that the write stream supplying content data for the
* cache did not complete normally and, therefore, the content may be
* truncated.
*/
readonly attribute boolean partialFlag;
/**
* This flag can be set and cleared by a protocol handler as a form of
* self-notification, so as to avoid race conditions in which a protocol
* handler issues two identical network requests to fill the same cache
* entry. The cache manager itself largely ignores this flag.
*/
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
* cache replacement policy, i.e. it is not used for validation. If the
* protocol can't supply a last-modified time, this attribute should remain
* unset. When unset, the value of this attribute is zero.
*
* FIXME: Should use nsIDateTime interface, once it's created
* instead of PRTime, for improved scriptability ?
*/
attribute PRTime lastModifiedTime;
/**
* Supplied by the protocol handler, the expirationTime attribute specifies
* the time until which the document is guaranteed fresh, i.e. the document
* does not have to be validated with the server and, therefore, any data
* in cache is definitely usable. The value of this attribute serves as a
* hint to the cache replacement policy. Only one of either staleTime or
* expirationTime may be set for a single cache record. When unset, the
* value of this attribute is zero.
*/
attribute PRTime expirationTime;
/**
* Date/time supplied by the protocol handler, at which point the content
* is *likely* to be stale, i.e. the data in the cache may be out-of-date
* with respect to the data on the server. This heuristic date does not
* necessarily correspond to the HTTP Expires header, as it does not
* determine when cached network data must be validated with the origin
* server, but only serves as a hint to the cache replacement policy. Only
* one of either staleTime or expirationTime may be set for a single cache
* record. When unset, the value of this attribute is zero.
*/
attribute PRTime staleTime;
/**
* Date/time of last access of the data in this cache record, as determined
* by the cache manager.
*/
readonly attribute PRTime lastAccessTime;
/**
* Number of times this record has been accessed since it was first stored.
*/
readonly attribute PRUint16 numberAccesses;
/**
* 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 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,
* i.e. via the nsIChannel streaming APIs. This may be less than the
* complete content length if a partial cache fill occurred. The cached
* content can be truncated by setting the value of this attribute. The
* value of the attribute represents a logical, not a physical, length. If
* compression has been used, the content may consume less storage than
* indicated by this attribute.
*
* When this attribute is set to zero the associated cache disk file, if
* any, should be deleted.
*/
attribute PRUint32 storedContentLength;
/**
* Notify any observers associated with this cache entry of the deletion
* request. If all observers drop their reference to the cache entry,
* proceed to delete the underlying cache database record and associated
* content storage.
*/
void delete();
/**
* Flush any changes in this entry's data to the cache database. This
* method will automatically be called when the last reference to the cache
* is dropped, but it can also be called explicitly for a synchronous
* effect.
*/
void commit();
/**
* Parent container cache for this entry.
*/
readonly attribute nsINetDataCache cache;
/**
* Create a channel for reading or writing a stream of content into the
* entry. It is expected that many of the nsIChannel methods return
* NS_NOT_IMPLEMENTED, including:
*
* + GetURI()
* + GetContentType()
* + GetContentLength()
*
* Though nsIChannel provides for both async and synchronous I/O APIs, both
* may not be implemented. Only AsyncRead() and OpenOutputStream() is
* 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 aLoadGroup,
in nsIChannel aProxyChannel);
/**
* This method can be used by a caching protocol handler to store data in
* the cache by forking an asynchronous read stream so that it is
* simultaneously sent to a requester and written into the cache. This
* method implicitly sets the updateInProgress flag, if it has not already
* been set.
*/
nsIStreamListener interceptAsyncRead(in nsIStreamListener aOriginalListener,
in PRUint32 aStartOffset);
};

View File

@@ -1,143 +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 "nsISupports.idl"
interface nsIURI;
interface nsINetDataCacheRecord;
interface nsISimpleEnumerator;
interface nsIFileSpec;
/**
* The nsINetDataCache defines the low-level API for a network-data
* cache, used to cache the responses to network retrieval commands.
* This interface, along with nsINetDataCacheRecord, is implemented by
* the memory cache, the file cache and, optionally, by some extension
* caches. This interface is essentially a pseudo-private API for the
* cache manager. Other clients should never use this interface.
*
* 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 a key created by combining the URI
* with a "secondary key", e.g. HTTP post data.
*
* The nsINetDataCache interface is agnostic as to where the data is
* stored and whether the storage is volatile or persistent. The
* memory cache, any disk caches and any extension caches must all
* implement this interface.
*
*/
[scriptable, uuid(ccfc58c0-6dde-11d3-90c8-000064657374)]
interface nsINetDataCache : nsISupports
{
/**
* Human-readable description of the cache module, e.g. "Disk Cache"
*/
readonly attribute wstring description;
/**
* Returns true if cached data is available for the given opaque key,
* even if only partial data is stored.
*/
boolean contains([size_is(length)] in string key, in PRUint32 length);
/**
* Fetch the cache entry record for the given opaque key. If one does not
* exist, create a new, empty record.
*/
nsINetDataCacheRecord getCachedNetData([size_is(length)] in string key,
in PRUint32 length);
/**
* Fetch the cache entry record for the given URI using the record ID as a key.
*/
nsINetDataCacheRecord getCachedNetDataByID(in PRInt32 RecordID);
/**
* False indicates that this cache is entirely bypassed.
*/
attribute boolean enabled;
/**
* Constants for flags attribute, below
*/
// Used for extension caches, e.g. a CD-ROM cache
const long READ_ONLY = 1 << 0;
// One of these bits must be set
const long MEMORY_CACHE = 1 << 1;
const long FLAT_FILE_CACHE = 1 << 2;
const long FILE_PER_URL_CACHE = 1 << 3;
/**
* See constants defined above.
*/
readonly attribute PRUint32 flags;
/**
* Total number of URI entries stored in the cache.
*/
readonly attribute PRUint32 numEntries;
/**
* Maximum number of URI entries that may be stored in the cache.
*/
readonly attribute PRUint32 maxEntries;
/**
* Enumerate the URI entries stored in the cache.
*/
nsISimpleEnumerator newCacheEntryIterator();
/**
* Contains a reference to the next cache in search order. For the memory
* cache, this attribute always references the disk cache. For the disk
* cache, it contains a reference to the first extension cache.
*/
attribute nsINetDataCache nextCache;
/**
* 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
* and heap fragmentation (in the memory cache) or block quantization (in
* the disk cache).
*/
readonly attribute PRUint32 storageInUse;
/**
* Remove all entries from a writable cache. This could be used, for
* example, after a guest ends a browser session. This is equivalent to
* setting the cache's Capacity to zero, except that all cache entries,
* even those in active use, will be deleted. Also, any global cache
* database files will be deleted.
*/
void removeAll();
};
%{ C++
// ProgID prefix for Components that implement this interface
#define NS_NETWORK_CACHE_PROGID "component://netscape/network/cache"
#define NS_NETWORK_MEMORY_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=memory-cache"
#define NS_NETWORK_FLAT_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=flat-cache"
#define NS_NETWORK_FILE_CACHE_PROGID NS_NETWORK_CACHE_PROGID "?name=file-cache"
%}

View File

@@ -1,163 +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 "nsISupports.idl"
interface nsISimpleEnumerator;
interface nsICachedNetData;
interface nsINetDataCache;
interface nsINetDataDiskCache;
interface nsIURI;
interface nsIFileSpec;
/**
* The network-response cache manager is partly responsible for the caching of
* content and associated metadata that has been retrieved via the network.
* (The remaining responsibility for caching lies with individual network
* protocol handlers.)
*
* 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.
*
* @See nsINetDataCache
* @See nsICachedNetData
*/
[scriptable, uuid(71c8ab00-6d5c-11d3-90c8-000064657374)]
interface nsINetDataCacheManager : nsISupports
{
/**
* Flag for the GetCachedNetData() method: If set, the memory cache is
* neither searched nor will any data be stored into it. This might be
* appropriate, for example, with images, because they have their own
* cache for storing *decoded* images.
*/
const unsigned long BYPASS_MEMORY_CACHE = 1 << 0;
/**
* Flag for the GetCachedNetData() method: If set, the disk cache
* is neither searched nor will any be data stored into it.
* However, read-only extension caches may be searched. This
* might be used to avoid leaving persistent records of secure
* data.
*/
const unsigned long BYPASS_PERSISTENT_CACHE = 1 << 1;
/**
* Flag for the GetCachedNetData() method: If set, any stream
* content is stored in the cache as a single disk file. Content
* will not be cached in the memory cache nor is it cached in a
* flat-file cache database. This is used to implement the jar
* protocol handler and to provide the stream-as-file semantics
* required by the classic bowser plugin API.
*/
const unsigned long CACHE_AS_FILE = 1 << 2;
/**
* Fetch the cache entry record for the given URI. If one does not exist,
* create a new, empty record. The normal search order for caches is:
* + Memory cache
* + Disk cache
* + File cache (stream-as-file cache)
* + All extension caches
*
* When writing, data is typically stored in both the memory cache and the
* disk cache. Both the search order and this write policy can be modified by
* setting one or more of the flag argument bits, as defined above.
*
* 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 string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
/**
* Returns true if cached content is available for the given URI, even if
* only partial data is stored. The flags argument behaves the same as for
* the GetCachedNetData() method, above.
*/
boolean contains(in string uri,
[size_is(secondaryKeyLength)] in string secondaryKey,
in PRUint32 secondaryKeyLength,
in PRUint32 flags);
/**
* Total number of unexpired URI entries stored in all caches. This number
* does not take into account duplicate URIs, e.g. because the memory cache
* and the disk cache might each contain an entry for the same URI.
*/
readonly attribute PRUint32 numEntries;
/**
* Enumerate the unexpired URI entries stored in all caches. Some URIs may
* be enumerated more than once, e.g. because the the memory cache and the
* disk cache might each contain an entry for the same URI.
*/
nsISimpleEnumerator newCacheEntryIterator();
/*
* Enumerate all the loaded nsINetDataCache-implementing cache modules.
* The first module enumerated will be the memory cache, the second will be
* the disk cache, then the file cache, followed by all the extension
* caches, in search order.
*/
nsISimpleEnumerator newCacheModuleIterator();
/**
* Remove all entries from all writable caches. This could be used, for
* example, after a guest ends a browser session. This is equivalent to
* setting the DiskCacheCapacity to zero, except that all cache entries,
* even those in active use, will be deleted. Also, any global cache
* database files will be deleted.
*/
void RemoveAll();
/**
* The disk cache is made up of the file cache (for stream-as-file
* requests) and a (possibly independent) persistent cache that handles all
* other cache requests. This attribute sets/gets the combined capacity of
* these caches, measured in KBytes. Setting the capacity lower than the
* current amount of space currently in use may cause cache entries to be
* evicted from the cache to accomodate the requested capacity.
*/
attribute PRUint32 diskCacheCapacity;
/**
* This attribute sets/gets the capacity of the memory cache, measured in
* KBytes. Setting the capacity lower than the current amount of space
* currently in use may cause cache entries to be evicted from the cache to
* 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,125 +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 "nsISupports.idl"
#include "nsrootidl.idl"
interface nsIFileSpec;
interface nsIChannel;
interface nsINetDataCache;
/**
* The nsINetDataCacheRecord represents a single entry in a database that
* caches data retrieved from the network. On top of this low-level interface
* to the raw record data, the cache manager implements a higher-level record
* interface, nsICachedNetData. Each instance of nsINetDataCacheRecord is
* (internally) associated with a parent database, an instance of the
* nsINetDataCache interface. This interface is essentially a pseudo-private
* API for the cache manager. Other clients should never use this interface.
*
* Each cache record may contain both content and metadata. The content may
* be, for example, GIF image data or HTML, and it is accessed through
* nsIChannel's streaming API. The opaque metadata, which may contain HTTP
* headers among other things, is accessed as a contiguous byte array. Each
* entry in the cache is indexed by two different keys: a unique record id
* number, generated by the cache, and an opaque string. The latter contains
* the URI and other secondary key information, e.g. HTTP form post key/value
* pairs.
*
* The nsINetDataCacheRecord interface is agnostic as to where the data is
* stored and whether the storage is volatile or persistent. The memory cache,
* the disk cache, a flat-file cache and any read-only extension caches must
* all implement this interface.
*
* @See nsICachedNetData
* @See nsINetDataCache
* @See nsINetDataDiskCache
* @See nsINetDataCacheManager
*/
interface nsILoadGroup;
[scriptable, uuid(fdcdd6a0-7461-11d3-90ca-0040056a906e)]
interface nsINetDataCacheRecord : nsISupports
{
/**
* As far as the nsINetDataCacheRecord implementation is concerned, the
* cache entry database key is an opaque blob, but it's intended to contain
* both the URI and any secondary keys, such as HTTP post data.
*/
void getKey(out unsigned long length, [size_is(length), retval] out string key);
/**
* A persistent record number assigned by the cache which must be unique
* among all entries stored within the same cache. The record ID serves as
* an alternate key to the cache record. Providing that they satisfy the
* afforementioned uniqueness requirement, record IDs can be assigned any
* value by the database except that they may never be zero.
*/
readonly attribute PRInt32 recordID;
/**
* Opaque data which can be updated for each cache entry independently of
* the content data. This data is a combination of protocol-independent
* data provided by the cache manager and protocol-specific meta-data,
* e.g. HTTP headers.
*/
void getMetaData(out PRUint32 length, [size_is(length), retval] out string metaData);
void setMetaData(in PRUint32 length, [size_is(length)] in string data);
/**
* Number of content bytes stored in the cache, i.e. via the nsIChannel
* streaming APIs. This may be less than the complete content length if a
* partial cache fill occurred. Additionally, the cached content can be
* truncated by reducing the value of this attribute. When this attribute
* is set to zero the associated cache disk file, if any, should be
* deleted.
*/
attribute PRUint32 storedContentLength;
/**
* Delete this cache entry and its associated content.
*/
void delete();
/**
* Create a channel for reading or writing a stream of content into the
* entry. However, many of the nsIChannel methods may return
* NS_NOT_IMPLEMENTED, including:
*
* + GetURI()
* + GetContentType()
* + GetContentLength()
*/
nsIChannel newChannel(in nsILoadGroup loadGroup);
/**
* If a cache is implemented such that it stores each URI's content in an
* individual disk file, this method will identify the file corresponding
* to this record. This may be used to implement the "stream-as-file"
* semantics required by some plugins and by the 'jar:' protocol handler.
* However, not all cache implementations are *required* to store the data
* from each URI in an individual file, so it is acceptable for an
* implementation of this method to signal NS_NOT_IMPLEMENTED.
*/
readonly attribute nsIFileSpec filename;
};

View File

@@ -1,42 +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 "nsINetDataCache.idl"
interface nsIFileSpec;
/**
/**
* A network-data disk cache is used to persistently 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.
*/
[scriptable, uuid(6408e390-6f13-11d3-90c8-000064657374)]
interface nsINetDataDiskCache : nsINetDataCache
{
/**
* This attribute must be set before calling any other methods of this
* interface.
*/
attribute nsIFileSpec diskCacheFolder;
};

View File

@@ -1,106 +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 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 "nsrootidl.idl"
#include "nsISupports.idl"
interface nsIFileSpec;
interface nsIStreamAsFileObserver;
/**
* In addition to enhancing effective network response time via caching, the
* cache manager serves a second purpose by providing the stream-as-file
* service required by traditional browser plugins and the jar: protocol
* handler. The interface below provides a means for a client to determine the
* filename associated with a stream and to detect modification/deletion of
* that file.
*/
[scriptable, uuid(0eedbbf0-92d9-11d3-90d3-0040056a906e)]
interface nsIStreamAsFile : nsISupports
{
/**
* Filename containing stream-as-file
*/
readonly attribute nsIFileSpec fileSpec;
/**
* Add an observer for this cache record. When the cache wants to delete
* or truncate a record, so as to make space for another cache entry's
* content data, it will call <code>aObserver</code>'s Observe() method,
* passing the nsIStreamAsFile instance as the <code>aSubject</code>
* argument and an appropriate message. If the observer does not wish to
* inhibit deletion/truncation, it should Release() any references it has to the
* cache record.
*
* @See nsIStreamAsFileObserver
*/
void addObserver(in nsIStreamAsFileObserver aObserver);
/**
* Delete an observer that was added by the AddObserver() method.
*/
void removeObserver(in nsIStreamAsFileObserver aObserver);
};
/**
* This interface can be implemented by a client to receive notifications of
* either modification or deletion of a file created by the cache manager using
* the stream-as-file semantics.
*/
[scriptable, uuid(a26e27c0-92da-11d3-90d3-0040056a906e)]
interface nsIStreamAsFileObserver : nsISupports
{
/**
* Flag bits for argument to Observe() method.
*/
const long NOTIFY_AVAILABLE = 1 << 0; // Stream-as-file now available for reading
const long NOTIFY_ERROR = 1 << 1; // Error while loading stream / creating file
const long REQUEST_DELETION = 1 << 2; // Cache manager wishes to delete/truncate file
const long INVALIDATE = 1 << 3; // File is out-of-date
// Convenience value
const long MAKE_UNAVAILABLE = REQUEST_DELETION | INVALIDATE;
/**
* Receive either a notification or a request concerning a file that has
* been opened using stream-as-file. The aMessage and aError arguments
* have varying values depending on the nature of the notification.
* aMessage is set to NOTIFY_AVAILABLE when a complete stream has been read
* and stored on disk in a file. At that point, and no sooner, may the
* filename attribute of the associated nsIStreamAsFile be accessed via the
* associated nsIStreamAsFile interface. If the aMessage argument is
* NOTIFY_ERROR, the aError argument contains the relevant error code. If
* the aMessage argument is either REQUEST_DELETION or REQUEST_TRUNCATION,
* the callee should immediately Release() all references to the
* nsIStreamAsFile (and any references to its associated nsICachedNetData
* instances), unless it wishes to inhibit the requested file modification.
* If the aMessage argument is INVALIDATE, the cache manager is replacing
* the file with a more recent version. If a client wants to continue
* using the (now out-of-date) file, it must delete it when it has finished,
* as the cache manager will effectively relinquished ownership of the
* file.
*/
void ObserveStreamAsFile(in nsIStreamAsFile aStreamAsFile,
in PRUint32 aMessage,
in nsresult aError);
};

View File

@@ -1,39 +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 = ..
MODULE = necko
DIRS= \
base \
dns \
build \
protocol \
socket \
util \
mime \
streamconv \
cache \
test \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -1,32 +0,0 @@
/* -*- Mode: IDL; 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 "nsISupports.idl"
interface nsIAtom;
[scriptable, uuid(a3ec67f0-465a-11d3-9a89-0080c7cb1080)]
interface nsIHTTPHeader : nsISupports
{
nsIAtom GetField();
string GetValue();
};

View File

@@ -1,603 +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.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 "nsINetDataCache.h"
#include "nsINetDataCacheManager.h"
#include "nsICachedNetData.h"
// Number of test entries to be placed in the cache
// FIXME - temporary
#define NUM_CACHE_ENTRIES 25
// Cache content stream length will have random length between zero and
// MAX_CONTENT_LENGTH bytes
#define MAX_CONTENT_LENGTH 20000
// Limits, converted to KB
#define DISK_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 4) >> 10)
#define MEM_CACHE_CAPACITY ((MAX_CONTENT_LENGTH * 3) >> 10)
// Length of random-data cache entry URI key
#define CACHE_KEY_LENGTH 13
// Length of random-data cache entry secondary key
#define CACHE_SECONDARY_KEY_LENGTH 10
// Length of random-data cache entry meta-data
#define CACHE_PROTOCOL_PRIVATE_LENGTH 10
// 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 void ReadString(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool Match(char* aBuf, PRUint32 aCount) = 0;
virtual PRBool MatchString(char* aBuf, PRUint32 aCount) = 0;
virtual void Skip(PRUint32 aCount) = 0;
virtual void SkipString(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 ^ (mState >> 16);
return mState;
}
PRUint8 NextChar() {
PRUint8 c;
do {
c = Next();
} while (!isalnum(c));
return c;
}
void Read(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = Next();
}
}
// Same as Read(), but using only printable chars and
// with a terminating NUL
void ReadString(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
*aBuf++ = NextChar();
}
*aBuf = 0;
}
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;
}
PRBool
MatchString(char* aBuf, PRUint32 aCount) {
PRUint32 i;
for (i = 0; i < aCount; i++) {
if (*aBuf++ != (char)(NextChar() & 0xff))
return PR_FALSE;
}
// Check for terminating NUL character
if (*aBuf)
return PR_FALSE;
return PR_TRUE;
}
void
Skip(PRUint32 aCount) {
while (aCount--)
Next();
}
void
SkipString(PRUint32 aCount) {
while (aCount--)
NextChar();
}
protected:
PRUint32 mState;
PRUint32 mStartSeed;
};
static int gNumReaders = 0;
static PRUint32 gTotalBytesRead = 0;
static PRUint32 gTotalBytesWritten = 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(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
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);
//FIXME NS_ASSERTION(mBytesRead == mExpectedStreamLength,
// "Stream in cache is wrong length");
gTotalBytesRead += mBytesRead;
gTotalDuration += duration;
return NS_OK;
}
protected:
PRIntervalTime mStartTime;
PRUint32 mBytesRead;
nsITestDataStream* mTestDataStream;
PRUint32 mExpectedStreamLength;
};
NS_IMPL_ISUPPORTS2(nsReader, nsIStreamListener, nsIStreamObserver)
static nsIEventQueue* eventQueue;
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
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(nsICachedNetData *cacheEntry, nsITestDataStream *testDataStream,
PRUint32 expectedStreamLength)
{
nsCOMPtr<nsIChannel> channel;
nsresult rv;
PRUint32 actualContentLength;
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = cacheEntry->GetStoredContentLength(&actualContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// FIXME NS_ASSERTION(actualContentLength == expectedStreamLength,
// "nsICachedNetData::GetContentLength() busted ?");
nsReader *reader = new nsReader;
reader->AddRef();
rv = reader->Init(testDataStream, expectedStreamLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->AsyncRead(0, -1, 0, reader);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
reader->Release();
return NS_OK;
}
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
static PRUint32
convertPRTimeToSeconds(PRTime aTime64)
{
double fpTime;
LL_L2D(fpTime, aTime64);
return (PRUint32)(fpTime * 1e-6 + 0.5);
}
// Convert unix-style time_t, i.e. seconds since the epoch, to PRTime
static PRTime
convertSecondsToPRTime(PRUint32 aSeconds)
{
PRInt64 t64;
LL_L2I(t64, aSeconds);
LL_MUL(t64, t64, 1000000);
return t64;
}
// Read the test data that was written in FillCache(), checking for
// corruption, truncation.
nsresult
TestRead(nsINetDataCacheManager *aCache, PRUint32 aFlags)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsICachedNetData> cacheEntry;
RandomStream *randomStream;
char uriCacheKey[CACHE_KEY_LENGTH];
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
char *storedUriKey;
PRUint32 testNum;
gTotalBytesRead = 0;
gTotalDuration = 0;
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->ReadString(uriCacheKey, sizeof uriCacheKey - 1);
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
// Ensure that entry is in the cache
rv = aCache->Contains(uriCacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
rv = aCache->GetCachedNetData(uriCacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags,
getter_AddRefs(cacheEntry));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
// Test GetUriSpec() method
rv = cacheEntry->GetUriSpec(&storedUriKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
!memcmp(storedUriKey, &uriCacheKey[0], sizeof uriCacheKey),
"nsICachedNetData::GetKey failed");
nsAllocator::Free(storedUriKey);
// Test GetSecondaryKey() method
PRUint32 storedSecondaryKeyLength;
char* storedSecondaryKey;
rv = cacheEntry->GetSecondaryKey(&storedSecondaryKeyLength, &storedSecondaryKey);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
!memcmp(storedSecondaryKey, &secondaryCacheKey[0],
sizeof secondaryCacheKey),
"nsICachedNetData::GetSecondaryKey failed");
// Compare against stored protocol data
char *storedProtocolData;
PRUint32 storedProtocolDataLength;
rv = cacheEntry->GetAnnotation("test data", &storedProtocolDataLength, &storedProtocolData);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
storedProtocolDataLength == CACHE_PROTOCOL_PRIVATE_LENGTH,
"nsICachedNetData::GetAnnotation() failed");
randomStream->Match(storedProtocolData, storedProtocolDataLength);
// Test GetAllowPartial()
PRBool allowPartial;
rv = cacheEntry->GetAllowPartial(&allowPartial);
NS_ASSERTION(NS_SUCCEEDED(rv) &&
(allowPartial == (PRBool)(randomStream->Next() & 1)),
"nsICachedNetData::GetAllowPartial() failed");
// Test GetExpirationTime()
PRTime expirationTime;
PRTime expectedExpirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
rv = cacheEntry->GetExpirationTime(&expirationTime);
NS_ASSERTION(NS_SUCCEEDED(rv) && LL_EQ(expirationTime, expectedExpirationTime),
"nsICachedNetData::GetExpirationTime() failed");
PRUint32 expectedStreamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
TestReadStream(cacheEntry, 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 %7d bytes at a rate of %5.1f MB per second \n",
gTotalBytesRead, rate);
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(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
{
nsresult rv;
PRBool inCache;
nsCOMPtr<nsICachedNetData> cacheEntry;
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsIOutputStream> outStream;
nsCOMPtr<nsINetDataCache> containingCache;
char buf[1000];
PRUint32 protocolDataLength;
char cacheKey[CACHE_KEY_LENGTH];
char secondaryCacheKey[CACHE_SECONDARY_KEY_LENGTH];
char protocolData[CACHE_PROTOCOL_PRIVATE_LENGTH];
PRUint32 testNum;
RandomStream *randomStream;
gTotalBytesWritten = 0;
PRIntervalTime startTime = PR_IntervalNow();
for (testNum = 0; testNum < NUM_CACHE_ENTRIES; testNum++) {
randomStream = new RandomStream(testNum);
randomStream->ReadString(cacheKey, sizeof cacheKey - 1);
randomStream->Read(secondaryCacheKey, sizeof secondaryCacheKey);
// No entry should be in cache until we add it
rv = aCache->Contains(cacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(!inCache, "nsINetDataCacheManager::Contains error");
rv = aCache->GetCachedNetData(cacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags,
getter_AddRefs(cacheEntry));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't access cacheEntry via cache key");
// Test nsINetDataCacheManager::GetNumEntries()
PRUint32 numEntries = (PRUint32)-1;
rv = aCache->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
char *protocolDatap;
rv = cacheEntry->GetAnnotation("test data", &protocolDataLength, &protocolDatap);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
if ((protocolDataLength != 0) || (protocolDatap != 0))
return NS_ERROR_FAILURE;
// Store random data as meta-data
randomStream->Read(protocolData, sizeof protocolData);
cacheEntry->SetAnnotation("test data", sizeof protocolData, protocolData);
// Store random data as allow-partial flag
PRBool allowPartial = randomStream->Next() & 1;
rv = cacheEntry->SetAllowPartial(allowPartial);
NS_ASSERTION(NS_SUCCEEDED(rv),
"nsICachedNetData::SetAllowPartial() failed");
// Store random data as expiration time
PRTime expirationTime = convertSecondsToPRTime(randomStream->Next() & 0xffffff);
rv = cacheEntry->SetExpirationTime(expirationTime);
NS_ASSERTION(NS_SUCCEEDED(rv),
"nsICachedNetData::SetExpirationTime() failed");
// Cache manager complains if expiration set without setting last-modified time
rv = cacheEntry->SetLastModifiedTime(expirationTime);
rv = cacheEntry->NewChannel(0, 0, getter_AddRefs(channel));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = cacheEntry->GetCache(getter_AddRefs(containingCache));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
rv = channel->OpenOutputStream(0, getter_AddRefs(outStream));
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
int streamLength = randomStream->Next() % MAX_CONTENT_LENGTH;
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;
PRUint32 storageInUse;
rv = containingCache->GetStorageInUse(&storageInUse);
NS_ASSERTION(NS_SUCCEEDED(rv) && (storageInUse <= aCacheCapacity),
"Cache manager failed to limit cache growth");
}
outStream->Close();
gTotalBytesWritten += streamLength;
// *Now* there should be an entry in the cache
rv = aCache->Contains(cacheKey,
secondaryCacheKey, sizeof secondaryCacheKey,
aFlags, &inCache);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(inCache, "nsINetDataCacheManager::Contains error");
delete randomStream;
}
PRIntervalTime endTime = PR_IntervalNow();
// Compute rate in MB/s
double rate = gTotalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
rate *= 1000;
rate /= (1024 * 1024);
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
gTotalBytesWritten, rate);
return NS_OK;
}
nsresult NS_AutoregisterComponents()
{
nsresult rv = nsComponentManager::AutoRegister(nsIComponentManager::NS_Startup,
NULL /* default */);
return rv;
}
nsresult
Test(nsINetDataCacheManager *aCache, PRUint32 aFlags, PRUint32 aCacheCapacity)
{
nsresult rv;
rv = aCache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
PRUint32 numEntries = (PRUint32)-1;
rv = aCache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
rv = FillCache(aCache, aFlags, aCacheCapacity);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't fill cache with random test data");
rv = TestRead(aCache, aFlags);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't read random test data from cache");
rv = aCache->RemoveAll();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't clear cache");
rv = aCache->GetNumEntries(&numEntries);
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't get number of cache entries");
NS_ASSERTION(numEntries == 0, "Couldn't clear cache");
return 0;
}
int
main(int argc, char* argv[])
{
nsresult rv;
nsCOMPtr<nsINetDataCacheManager> cache;
rv = NS_AutoregisterComponents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
rv = nsComponentManager::CreateInstance(NS_NETWORK_CACHE_MANAGER_PROGID,
nsnull,
NS_GET_IID(nsINetDataCacheManager),
getter_AddRefs(cache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create cache manager factory") ;
cache->SetDiskCacheCapacity(DISK_CACHE_CAPACITY);
cache->SetMemCacheCapacity(MEM_CACHE_CAPACITY);
InitQueue();
Test(cache, nsINetDataCacheManager::BYPASS_PERSISTENT_CACHE, MEM_CACHE_CAPACITY);
Test(cache, nsINetDataCacheManager::BYPASS_MEMORY_CACHE, DISK_CACHE_CAPACITY);
return 0;
}

View File

@@ -1,820 +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.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 "nsINetDataCache.h"
#include "nsINetDataDiskCache.h"
#include "nsINetDataCacheRecord.h"
#include "nsMemCacheCID.h"
// file cache include
#include "nsNetDiskCacheCID.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);
// file cache 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(nsITestDataStream* aRandomStream, PRUint32 aExpectedStreamLength) {
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;
return NS_OK;
}
protected:
PRIntervalTime mStartTime;
PRUint32 mBytesRead;
nsITestDataStream* mTestDataStream;
PRUint32 mExpectedStreamLength;
};
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;
rv = reader->Init(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() % MAX_CONTENT_LENGTH;
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() % MAX_CONTENT_LENGTH;
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);
PRUint32 afterContentLength;
rv = record->GetStoredContentLength(&afterContentLength);
NS_ASSERTION(NS_SUCCEEDED(rv), " ");
NS_ASSERTION(afterContentLength == expectedStreamLength,
"nsINetDataCacheRecord::SetContentLength() failed to truncate record");
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");
// Write buffer-fulls of data at random offsets into the cache entry.
// Data written is (offset % 0xff)
PRUint32 startingOffset;
PRUint32 streamLength = 0;
CounterStream *counterStream;
int i;
for (i = 0; i < 100; 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), " ");
counterStream = new CounterStream(startingOffset);
counterStream->Read(buf, sizeof buf);
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;
}
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;
PRUint32 totalBytesWritten = 0;
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() % MAX_CONTENT_LENGTH;
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();
totalBytesWritten += streamLength;
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();
// Compute rate in MB/s
double rate = totalBytesWritten / PR_IntervalToMilliseconds(endTime - startTime);
rate *= 1000;
rate /= (1024 * 1024);
printf("Wrote %7d bytes at a rate of %5.1f MB per second \n",
totalBytesWritten, rate);
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[])
{
nsresult rv;
if(argc <2) {
printf(" %s -f to test filecache\n", argv[0]) ;
printf(" %s -m to test memcache\n", argv[0]) ;
return -1 ;
}
rv = NS_AutoregisterComponents();
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't register XPCOM components");
nsCOMPtr<nsINetDataCache> cache;
if (PL_strcasecmp(argv[1], "-m") == 0) {
rv = nsComponentManager::CreateInstance(kMemCacheCID, nsnull,
NS_GET_IID(nsINetDataCache),
getter_AddRefs(cache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create memory cache factory");
} else if (PL_strcasecmp(argv[1], "-f") == 0) {
nsCOMPtr<nsINetDataDiskCache> diskcache ;
rv = nsComponentManager::CreateInstance(kDiskCacheCID, nsnull,
NS_GET_IID(nsINetDataDiskCache),
getter_AddRefs(diskcache));
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create disk cache factory") ;
nsCOMPtr<nsIFileSpec> folder ;
NS_NewFileSpec(getter_AddRefs(folder)) ;
folder->SetUnixStyleFilePath("/tmp") ;
diskcache->SetDiskCacheFolder(folder) ;
cache = diskcache ;
} else {
printf(" %s -f to test filecache\n", argv[0]) ;
printf(" %s -m to test memcache\n", argv[0]) ;
return -1 ;
}
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,82 +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)\TestFileInput.exe
PROG2 = .\$(OBJDIR)\TestSocketInput.exe
PROG3 = .\$(OBJDIR)\TestSocketIO.exe
PROG4 = .\$(OBJDIR)\TestProtocols.exe
PROG5 = .\$(OBJDIR)\TestSocketTransport.exe
PROG6 = .\$(OBJDIR)\urltest.exe
PROG7 = .\$(OBJDIR)\TestFileInput2.exe
PROG8 = .\$(OBJDIR)\TestFileTransport.exe
PROG9 = .\$(OBJDIR)\TestRes.exe
PROGA = .\$(OBJDIR)\TestRawCache.exe
PROGB = .\$(OBJDIR)\TestCacheMgr.exe
PROGRAMS = \
#$(PROG1) $(PROG2) $(PROG3) $(PROG4) $(PROG5) $(PROG6) $(PROG7) $(PROG8) $(PROG9)\
$(PROGA) $(PROGB)
LCFLAGS=-DUSE_NSREG -GX
REQUIRES=libreg
INCS = $(INCS) \
-I$(DEPTH)\dist\include \
$(NULL)
LLIBS= \
$(DIST)\lib\xpcom.lib \
$(LIBNSPR) \
$(NULL)
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) TestFileInput.cpp
$(PROG2): $(OBJDIR) TestSocketInput.cpp
$(PROG3): $(OBJDIR) TestSocketIO.cpp
$(PROG4): $(OBJDIR) TestProtocols.cpp
$(PROG5): $(OBJDIR) TestSocketTransport.cpp
$(PROG6): $(OBJDIR) urltest.cpp
$(PROG7): $(OBJDIR) TestFileInput2.cpp
$(PROG8): $(OBJDIR) TestFileTransport.cpp
$(PROG9): $(OBJDIR) TestRes.cpp
$(PROGA): $(OBJDIR) TestRawCache.cpp
$(PROGB): $(OBJDIR) TestCacheMgr.cpp

33
mozilla/rdf/Makefile.in Normal file
View File

@@ -0,0 +1,33 @@
#!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 = ..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = base content datasource build
ifdef ENABLE_TESTS
DIRS += tests
endif
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,29 @@
#!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 = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -1,4 +1,4 @@
#!nmake
#!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
@@ -15,28 +15,13 @@
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
DEPTH=..\..\..
DEPTH=..\..
include <$(DEPTH)/config/config.mak>
MODULE = rdf
MODULE = nkcache
LIBRARY_NAME = nkmemcache_s
CPP_OBJS = \
.\$(OBJDIR)\nsMemCache.obj \
.\$(OBJDIR)\nsMemCacheRecord.obj \
.\$(OBJDIR)\nsMemCacheChannel.obj \
DIRS=\
public \
src \
$(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,11 @@
rdf.h
nsIRDFCompositeDataSource.h
nsIRDFContentSink.h
nsIRDFCursor.h
nsIRDFDataSource.h
nsIRDFNode.h
nsIRDFObserver.h
nsIRDFResourceFactory.h
nsIRDFService.h
nsIRDFXMLDataSource.h
nsIRDFXMLSource.h

View File

@@ -0,0 +1,46 @@
#!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=../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = rdf
EXPORTS = \
rdf.h \
nsIRDFCompositeDataSource.h \
nsIRDFContentSink.h \
nsIRDFCursor.h \
nsIRDFDataSource.h \
nsIRDFNode.h \
nsIRDFObserver.h \
nsIRDFResourceFactory.h \
nsIRDFService.h \
nsIRDFXMLDataSource.h \
nsIRDFXMLSource.h \
nsRDFResource.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -15,30 +15,26 @@
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
MODULE=rdf
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 \
EXPORTS=\
rdf.h \
nsIRDFCompositeDataSource.h \
nsIRDFContentSink.h \
nsIRDFCursor.h \
nsIRDFDataSource.h \
nsIRDFNode.h \
nsIRDFObserver.h \
nsIRDFResourceFactory.h \
nsIRDFService.h \
nsIRDFXMLDataSource.h \
nsIRDFXMLSource.h \
nsRDFResource.h \
$(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
include <$(DEPTH)/config/rules.mak>

View File

@@ -0,0 +1,60 @@
/* -*- 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.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.
*/
/*
RDF composite data source interface. A composite data source
aggregates individual RDF data sources.
*/
#ifndef nsIRDFCompositeDataSource_h__
#define nsIRDFCompositeDataSource_h__
#include "nsISupports.h"
#include "nsIRDFDataSource.h"
class nsIRDFDataSource;
// 96343820-307c-11d2-bc15-00805f912fe7
#define NS_IRDFCOMPOSITEDATASOURCE_IID \
{ 0x96343820, 0x307c, 0x11d2, { 0xb, 0x15, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } }
/**
* An <tt>nsIRDFCompositeDataSource</tt> composes individual data sources, providing
* the illusion of a single, coherent RDF graph.
*/
class nsIRDFCompositeDataSource : public nsIRDFDataSource {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFCOMPOSITEDATASOURCE_IID; return iid; }
/**
* Add a datasource the the database.
*/
NS_IMETHOD AddDataSource(nsIRDFDataSource* source) = 0;
/**
* Remove a datasource from the database
*/
NS_IMETHOD RemoveDataSource(nsIRDFDataSource* source) = 0;
};
extern nsresult
NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result);
#endif /* nsIRDFCompositeDataSource_h__ */

View File

@@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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.
*/
/*
An RDF-specific content sink. The content sink is targeted by the
parser for building the RDF content model.
*/
#ifndef nsIRDFContentSink_h___
#define nsIRDFContentSink_h___
#include "nsIXMLContentSink.h"
class nsIDocument;
class nsIRDFXMLDataSource;
class nsINameSpaceManager;
class nsIURL;
// {751843E2-8309-11d2-8EAC-00805F29F370}
#define NS_IRDFCONTENTSINK_IID \
{ 0x751843e2, 0x8309, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
/**
* This interface represents a content sink for RDF files.
*/
class nsIRDFContentSink : public nsIXMLContentSink {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFCONTENTSINK_IID; return iid; }
/**
* Initialize the content sink.
*/
NS_IMETHOD Init(nsIURL* aURL, nsINameSpaceManager* aNameSpaceManager) = 0;
/**
* Set the content sink's RDF Data source
*/
NS_IMETHOD SetDataSource(nsIRDFXMLDataSource* aDataSource) = 0;
/**
* Retrieve the content sink's RDF data source.
*/
NS_IMETHOD GetDataSource(nsIRDFXMLDataSource*& rDataSource) = 0;
};
/**
* This constructs a content sink that can be used without a
* document, say, to create a stand-alone in-memory graph.
*/
nsresult
NS_NewRDFContentSink(nsIRDFContentSink** aResult);
#endif // nsIRDFContentSink_h___

View File

@@ -0,0 +1,174 @@
/* -*- 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.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.
*/
/*
Interfaces for RDF cursors, including nsIRDFCursor,
nsIRDFAssertionCursor, nsIRDFArcsInCursor, nsIRDFArcsOutCursor,
nad nsIRDFResourceCursor.
*/
#ifndef nsIRDFCursor_h__
#define nsIRDFCursor_h__
#include "nsISupports.h"
#include "prtypes.h"
#include "rdf.h" // for error codes
class nsIRDFDataSource;
class nsIRDFNode;
class nsIRDFResource;
// 1c2abdb0-4cef-11d2-bc16-00805f912fe7
#define NS_IRDFCURSOR_IID \
{ 0x1c2abdb0, 0x4cef, 0x11d2, { 0xbc, 0x16, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } }
/**
* An abstract base interface that is the basis for all RDF cursors.
*/
class nsIRDFCursor : public nsISupports {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFCURSOR_IID; return iid; }
/**
* Advance the cursor to the next element.
* @return NS_ERROR_RDF_CURSOR_EMPTY if the cursor has reached the end
* and there are no more elements to enumerate; otherwise, NS_OK
* unless a catastrophic error occurs.
*/
NS_IMETHOD Advance(void) = 0;
/* Retrieve the data source from which the current item was obtained.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) = 0;
/**
* Irrespective of the query, a cursor is an interator over a set.
* This allows you to obtain the current value.
*/
NS_IMETHOD GetValue(nsIRDFNode** aValue) = 0;
};
// {1ED57100-9904-11d2-8EBA-00805F29F370}
#define NS_IRDFASSERTIONCURSOR_IID \
{ 0x1ed57100, 0x9904, 0x11d2, { 0x8e, 0xba, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
/**
* A cursor that enumerates assertions
* @seealso nsIRDFDataSource::GetTargetS(), nsIRDFDataSource::GetSources()
*/
class nsIRDFAssertionCursor : public nsIRDFCursor {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFASSERTIONCURSOR_IID; return iid; }
/**
* Retrieve the assertion's subject resource.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetSubject(nsIRDFResource** aSubject) = 0;
/**
* Retrieve the assertion's predicate resource.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
/**
* Retrieve the assertion's object node.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetObject(nsIRDFNode** aObject) = 0;
/**
* Retrieve the assertion's truth value.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) = 0;
};
// {1ED57101-9904-11d2-8EBA-00805F29F370}
#define NS_IRDFARCSOUTCURSOR_IID \
{ 0x1ed57101, 0x9904, 0x11d2, { 0x8e, 0xba, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
/**
* A cursor that enumerates the outbound arcs from a resource node.
* @seealso nsIRDFDataSource::ArcsOut()
*/
class nsIRDFArcsOutCursor : public nsIRDFCursor {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFARCSOUTCURSOR_IID; return iid; }
/**
* Retrieve the "subject" node from which the arcs originate.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetSubject(nsIRDFResource** aSubject) = 0;
/**
* Retrieve the predicate label of the arc.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
};
// {1ED57102-9904-11d2-8EBA-00805F29F370}
#define NS_IRDFARCSINCURSOR_IID \
{ 0x1ed57102, 0x9904, 0x11d2, { 0x8e, 0xba, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
/**
* A cursor that enumerates the inbound arcs to a node.
* @seealso nsIRDFDataSource::ArcsIn()
*/
class nsIRDFArcsInCursor : public nsIRDFCursor {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFARCSINCURSOR_IID; return iid; }
/**
* Retrieve the "object" node in which the arc terminates.
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetObject(nsIRDFNode** aObject) = 0;
/**
* Retrieve the predicate label of the arc
* @return NS_OK, unless a catastrophic error occurs.
*/
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) = 0;
};
// {C2850C10-B0CF-11d2-A684-00104BDE6048}
#define NS_IRDFRESOURCECURSOR_IID \
{ 0xc2850c10, 0xb0cf, 0x11d2, { 0xa6, 0x84, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } }
/**
* A cursor that enumerates all of the resources in a data source.
*/
class nsIRDFResourceCursor : public nsIRDFCursor {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFRESOURCECURSOR_IID; return iid; }
NS_IMETHOD GetResource(nsIRDFResource** aResource) = 0;
};
#endif /* nsIRDFCursor_h__ */

View File

@@ -0,0 +1,210 @@
/* -*- 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.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.
*/
/*
The RDF data source interface. An RDF data source presents a
graph-like interface to a back-end service.
*/
#ifndef nsIRDFDataSource_h__
#define nsIRDFDataSource_h__
#include "nsISupports.h"
// {0F78DA58-8321-11d2-8EAC-00805F29F370}
#define NS_IRDFDATASOURCE_IID \
{ 0xf78da58, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFAssertionCursor;
class nsIRDFArcsInCursor;
class nsIRDFArcsOutCursor;
class nsIRDFDataBase;
class nsIRDFNode;
class nsIRDFObserver;
class nsIRDFResource;
class nsIRDFResourceCursor;
/**
* An RDF data source.
*/
class nsIRDFDataSource : public nsISupports {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFDATASOURCE_IID; return iid; }
// XXX I didn't make some of these methods "const" because it's
// probably pretty likely that many data sources will just make
// stuff up at runtime to answer queries.
/**
* Specify the URI for the data source: this is the prefix
* that will be used to register the data source in the
* data source registry.
*/
NS_IMETHOD Init(const char* uri) = 0;
/**
* Retrieve the URI of the data source.
*/
NS_IMETHOD GetURI(const char* *uri) const = 0;
/**
* Find an RDF resource that points to a given node over the
* specified arc & truth value
*
* @return NS_ERROR_FAILURE if there is no source that leads
* to the target with the specified property.
*/
NS_IMETHOD GetSource(nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
nsIRDFResource** source /* out */) = 0;
/**
* Find all RDF resources that point to a given node over the
* specified arc & truth value
*
* @return NS_OK unless a catastrophic error occurs. If the
* method returns NS_OK, you may assume that nsIRDFCursor points
* to a valid (but possibly empty) cursor.
*/
NS_IMETHOD GetSources(nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
nsIRDFAssertionCursor** sources /* out */) = 0;
/**
* Find a child of that is related to the source by the given arc
* arc and truth value
*
* @return NS_ERROR_FAILURE if there is no target accessable from the
* source via the specified property.
*/
NS_IMETHOD GetTarget(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsIRDFNode** target /* out */) = 0;
/**
* Find all children of that are related to the source by the given arc
* arc and truth value.
*
* @return NS_OK unless a catastrophic error occurs. If the
* method returns NS_OK, you may assume that nsIRDFCursor points
* to a valid (but possibly empty) cursor.
*/
NS_IMETHOD GetTargets(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsIRDFAssertionCursor** targets /* out */) = 0;
/**
* Add an assertion to the graph.
*/
NS_IMETHOD Assert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv) = 0;
/**
* Remove an assertion from the graph.
*/
NS_IMETHOD Unassert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target) = 0;
/**
* Query whether an assertion exists in this graph.
*
* @return NS_OK unless a catastrophic error occurs.
*/
NS_IMETHOD HasAssertion(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
PRBool* hasAssertion /* out */) = 0;
/**
* Add an observer to this data source.
*/
NS_IMETHOD AddObserver(nsIRDFObserver* n) = 0;
/**
* Remove an observer from this data source
*/
NS_IMETHOD RemoveObserver(nsIRDFObserver* n) = 0;
// XXX individual resource observers?
/**
* Get a cursor to iterate over all the arcs that point into a node.
*
* @return NS_OK unless a catastrophic error occurs. If the method
* returns NS_OK, you may assume that labels points to a valid (but
* possible empty) nsIRDFCursor object.
*/
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
nsIRDFArcsInCursor** labels /* out */) = 0;
/**
* Get a cursor to iterate over all the arcs that originate in
* a resource.
*
* @return NS_OK unless a catastrophic error occurs. If the method
* returns NS_OK, you may assume that labels points to a valid (but
* possible empty) nsIRDFCursor object.
*/
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
nsIRDFArcsOutCursor** labels /* out */) = 0;
/**
* Retrieve all of the resources that the data source currently
* refers to.
*/
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor) = 0;
/**
* Request that a data source write it's contents out to
* permanent storage if applicable.
*/
NS_IMETHOD Flush(void) = 0;
/**
* Determine whether the specified command is enabled for the
* resource.
*
* XXX We will probably need to make this interface much more intricate
* to handle arbitrary arguments and selection sets.
*/
NS_IMETHOD IsCommandEnabled(const char* aCommand,
nsIRDFResource* aCommandTarget,
PRBool* aResult) = 0;
/**
* Perform the specified command on the resource.
*
* XXX We will probably need to make this interface much more intricate
* to handle arbitrary arguments and selection sets.
*/
NS_IMETHOD DoCommand(const char* aCommand,
nsIRDFResource* aCommandTarget) = 0;
};
#endif /* nsIRDFDataSource_h__ */

View File

@@ -0,0 +1,116 @@
/* -*- 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.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.
*/
/*
RDF node interfaces, including nsIRDFNode, nsIRDFResource, and
nsIRDFLiteral. Nodes are the elements that appear in RDF graphs.
*/
#ifndef nsIRDFNode_h__
#define nsIRDFNode_h__
#include "nscore.h"
#include "nsISupports.h"
// {0F78DA50-8321-11d2-8EAC-00805F29F370}
#define NS_IRDFNODE_IID \
{ 0xf78da50, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
/**
*
* Nodes are created using an instance of nsIRDFService, which
* should be obtained from the service manager:
*
* nsIRDFService* service;
* if (NS_SUCCEEDED(nsServiceManager::GetService(kCRDFServiceCID,
* kIRDFServiceIID,
* (nsISupports**) &service))) {
* nsIRDFNode* node;
* if (NS_SUCCEEDED(service->GetResource("http://foo.bar/", node))) {
* // do something useful here...
* NS_IF_RELEASE(node);
* }
* nsServiceManager::ReleaseService(kCRDFServiceCID, mgr);
* }
*
*/
class nsIRDFNode : public nsISupports {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFNODE_IID; return iid; }
/**
* Determine if two nodes are identical
*/
NS_IMETHOD EqualsNode(nsIRDFNode* that, PRBool* result) const = 0;
};
/**
* A resource node, which has unique object identity.
*/
// {E0C493D1-9542-11d2-8EB8-00805F29F370}
#define NS_IRDFRESOURCE_IID \
{ 0xe0c493d1, 0x9542, 0x11d2, { 0x8e, 0xb8, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFResource : public nsIRDFNode {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFRESOURCE_IID; return iid; }
/**
* Get the 8-bit string value of the node.
*/
NS_IMETHOD GetValue(const char* *uri) const = 0;
/**
* Determine if two resources are identical.
*/
NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const = 0;
/**
* Determine if two resources are identical.
*/
NS_IMETHOD EqualsString(const char* uri, PRBool* result) const = 0;
};
// {E0C493D2-9542-11d2-8EB8-00805F29F370}
#define NS_IRDFLITERAL_IID \
{ 0xe0c493d2, 0x9542, 0x11d2, { 0x8e, 0xb8, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFLiteral : public nsIRDFNode {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFLITERAL_IID; return iid; }
/**
* Get the Unicode string value of the node.
*/
NS_IMETHOD GetValue(const PRUnichar* *value) const = 0;
/**
* Determine if two resources are identical.
*/
NS_IMETHOD EqualsLiteral(const nsIRDFLiteral* literal, PRBool* result) const = 0;
};
#endif // nsIRDFNode_h__

View File

@@ -0,0 +1,64 @@
/* -*- 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.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.
*/
/*
The RDF data source observer interface. Data source observers are
notified when the contents of the graph change.
*/
#ifndef nsIRDFObserver_h__
#define nsIRDFObserver_h__
#include "nsISupports.h"
class nsIRDFDataSource;
class nsIRDFResource;
class nsIRDFNode;
/**
* An observer on an nsIRDFDataSource.
*/
// 3cc75360-484a-11d2-bc16-00805f912fe7
#define NS_IRDFOBSERVER_IID \
{ 0x3cc75360, 0x484a, 0x11d2, { 0xbc, 0x16, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } }
class nsIRDFObserver : public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFOBSERVER_IID; return iid; }
/**
* Called whenever a new assertion is made in the data source.
*/
NS_IMETHOD OnAssert(nsIRDFResource* subject,
nsIRDFResource* predicate,
nsIRDFNode* object) = 0;
/**
* Called whenever an assertion is removed from the data source.
*/
NS_IMETHOD OnUnassert(nsIRDFResource* subject,
nsIRDFResource* predicate,
nsIRDFNode* object) = 0;
};
#endif /* nsIRDFObserver_h__ */

View File

@@ -0,0 +1,74 @@
/* -*- 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.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.
*/
/*
The RDF resource factory interface. A resource factory produces
nsIRDFResource objects for a specified URI prefix.
*/
#ifndef nsIRDFResourceFactory_h__
#define nsIRDFResourceFactory_h__
#include "nsISupports.h"
class nsIRDFResource;
// {8CE57A20-A02C-11d2-8EBF-00805F29F370}
#define NS_IRDFRESOURCEFACTORY_IID \
{ 0x8ce57a20, 0xa02c, 0x11d2, { 0x8e, 0xbf, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
/**
* A resource factory can be registered with <tt>nsIRDFService</tt> to produce
* resources with a certain <i>URI prefix</i>. The resource factory will be called
* upon to create a new resource, which the resource manager will cache.
*
* @see nsIRDFService::RegisterResourceFactory
* @see nsIRDFService::UnRegisterResourceFactory
*/
class nsIRDFResourceFactory : public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFRESOURCEFACTORY_IID; return iid; }
/**
* This method is called by the RDF service to create a new
* resource.
*
* NOTE. After constructing a new resource via a call to
* nsIRDFResourceFactory::CreateResource(), the implementation of
* the RDF service calls nsIRDFResource::GetValue() on the
* resulting resource. The resulting <tt>const char*</tt> is used
* as a key for the resource cache. (The assumption is that the
* custom resource implementation needs to store this information,
* anyway.)
*
* This has important implications for a custom resource's
* destructor; namely, that you must call
* nsIRDFService::UnCacheResource() <b>before</b> releasing the
* storage for the resource's URI. See
* nsIRDFService::UnCacheResource() for more information.
*/
NS_IMETHOD CreateResource(const char* aURI, nsIRDFResource** aResult) = 0;
};
#endif // nsIRDFResourceFactory_h__

View File

@@ -0,0 +1,176 @@
/* -*- 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.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.
*/
/*
The RDF service interface. This is a singleton object, and should be
obtained from the <tt>nsServiceManager</tt>.
XXX I'm not particularly happy with the current APIs for named data
sources. The idea is that you want "rdf:bookmarks" to always map to
the "bookmarks" data store. The thing that bothers me now is that
the implementation has to pre-load all of the data sources: that
means you need to parse the bookmarks file, read the history, etc.,
rather than doing this on-demand. With a little thought, it may be
able to enormously improve these APIs so that pre-loading data
sources is unnecessary.
*/
#ifndef nsIRDFService_h__
#define nsIRDFService_h__
#include "nscore.h"
#include "nsISupports.h"
class nsIRDFDataBase;
class nsIRDFDataSource;
class nsIRDFLiteral;
class nsIRDFResource;
class nsIRDFResourceFactory;
typedef nsresult (*NSDataSourceConstructorCallback)(nsIRDFDataSource** aResult);
// {BFD05261-834C-11d2-8EAC-00805F29F370}
#define NS_IRDFSERVICE_IID \
{ 0xbfd05261, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFService : public nsISupports {
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFSERVICE_IID; return iid; }
// Resource management routines
/**
* Construct an RDF resource from a single-byte URI. <tt>nsIRDFSerivce</tt>
* caches resources that are in-use, so multiple calls to <tt>GetResource()</tt>
* for the same <tt>uri</tt> will return identical pointers.
*/
NS_IMETHOD GetResource(const char* uri, nsIRDFResource** resource) = 0;
/**
* Construct an RDF resource from a Unicode URI. This is provided
* as a convenience method, allowing automatic, in-line C++
* conversion from <tt>nsString</tt> objects. The <tt>uri</tt> will
* be converted to a single-byte representation internally.
*/
NS_IMETHOD GetUnicodeResource(const PRUnichar* uri, nsIRDFResource** resource) = 0;
/**
* Construct an RDF literal from a Unicode string.
*/
NS_IMETHOD GetLiteral(const PRUnichar* value, nsIRDFLiteral** literal) = 0;
/**
* Called to notify the resource manager that a resource is no
* longer in use. This method should only be called from the
* destructor of a "custom" resource implementation to notify the
* RDF service that the last reference to the resource has been
* released, so the resource is no longer valid.
*
* NOTE. As mentioned in nsIRDFResourceFactory::CreateResource(),
* the RDF service will use the result of
* nsIRDFResource::GetValue() as a key into its cache. For this
* reason, you must always un-cache the resource <b>before</b>
* releasing the storage for the <tt>const char*</tt> URI.
*/
NS_IMETHOD UnCacheResource(nsIRDFResource* resource) = 0;
/**
* Registers the specified resource factory as the producer for resources that
* have the specified <i>URI prefix</i>.
*/
NS_IMETHOD RegisterResourceFactory(const char* aURIPrefix, nsIRDFResourceFactory* aFactory) = 0;
/**
* Unregsters the specified resource factory from producing resources that have
* the specified <i>URI prefix</i>.
*/
NS_IMETHOD UnRegisterResourceFactory(const char* aURIPrefix) = 0;
// Data source management routines
/**
* Register a <i>named data source</i>. The RDF service will call
* <tt>nsIRDFDataSource::GetURI()</tt> to determine the URI under which to
* register the data source.
*
* Note that the data source will <i>not</i> be refcounted by the
* RDF service! The assumption is that an RDF data source registers
* with the service once it is initialized (via <tt>nsIRDFDataSource::Init()</tt>),
* and unregisters when the last reference to the data source is
* released.
*/
NS_IMETHOD RegisterDataSource(nsIRDFDataSource* dataSource) = 0;
/**
* Unregister a <i>named data source</i>. The RDF service will call
* <tt>nsIRDFDataSource::GetURI()</tt> to determine the URI under which the
* data source was registered.
*/
NS_IMETHOD UnregisterDataSource(nsIRDFDataSource* dataSource) = 0;
/**
* Register a constructor function that will create a named data source.
* The RDF service will call this function to attempt to create a
* named data source.
*/
NS_IMETHOD RegisterDataSourceConstructor(const char* aURI, NSDataSourceConstructorCallback aFn) = 0;
/**
* Unregister the constructor function for a named data source.
*/
NS_IMETHOD UnregisterDataSourceConstructor(const char* aURI) = 0;
/**
* Get the <i>named data source</i> corresponding to the URI. If a data
* source has been registered via <tt>RegisterDataSource()</tt>, that
* data source will be returned.
*
* If no data source is currently
* registered for the specified URI, and a data source <i>constructor</i>
* function has been registered via <tt>RegisterDatasourceConstructor()</tt>,
* the RDF service will call the constructor to attempt to construct a
* new data source. If construction is successful, the data source will
* be initialized via <tt>nsIRDFDataSource::Init()</tt>.
*/
NS_IMETHOD GetDataSource(const char* uri, nsIRDFDataSource** dataSource) = 0;
/**
* Create a database that contains the specified named data
* sources. This is a convenience method whose functionality is
* equivalent to (1) constructing a new nsIRDFDataBase object from
* the repository, and (2) iteratively adding the named data sources
* to it, in order.
*/
NS_IMETHOD CreateDatabase(const char** uris, nsIRDFDataBase** dataBase) = 0;
/**
* Get the database aggregating all the stuff that Navigator sees as a default,
* including a "local" store.
*/
NS_IMETHOD CreateBrowserDatabase(nsIRDFDataBase** dataBase) = 0;
};
extern nsresult
NS_NewRDFService(nsIRDFService** result);
#endif // nsIRDFService_h__

View File

@@ -0,0 +1,60 @@
/* -*- 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.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.
*/
#ifndef nsIRDFTree_h__
#define nsIRDFTree_h__
#include "nscore.h"
#include "nsISupports.h"
#include "prtypes.h"
#include "rdf.h" // for error codes
/*
An interface for presenting a tree view of an rdf datasource (or
database).
Any datasource can also support nsIRDFTree. The interface is purely
syntactic sugar for traversing simple tree where the child relation
corresponds to the property type nc:child (nc = http://home.netscape.com/NC-rdf#).
Each leaf is assumed to have a certain predefined set of properties
such as creationDate, size, lastModificationDate, lastVisitDate, etc.
This interface is substantially less general than nsIRDFDataSource,
but is adequate for bookmarks, the file system, history and a few
other very commonly used data sources.
*/
// {7D7EEBD1-AA41-11d2-80B7-006097B76B8E}
#define NS_IRDFTREE_IID \
{ 0x7d7eebd1, 0xaa41, 0x11d2, { 0x80, 0xb7, 0x0, 0x60, 0x97, 0xb7, 0x6b, 0x8e } };
class nsIRDFTree : public nsISupports {
public:
NS_IMETHOD ListChildren (nsIRDFResource* folder, nsVoidArray** result);
// XXX should define something called nsResourceArray and use that
NS_IMETHOD IsFolder (nsIRDFResource* node, PRBool* result);
NS_IMETHOD GetProperty (nsIRDFResource* node, nsIRDFResource* property,
nsIRDFNode** result);
}
#endif

View File

@@ -0,0 +1,200 @@
/* -*- 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.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.
*/
/*
This interface encapsulates information about an RDF/XML file,
including the root resource, CSS style sheets, and named data
sources.
This file also includes an observer interface for nsIRDFXMLDataSource
objects.
*/
#ifndef nsIRDFXMLDataSource_h__
#define nsIRDFXMLDataSource_h__
#include "nsIRDFDataSource.h"
class nsIAtom;
class nsIOutputStream;
class nsIURL;
class nsString;
// {EB1A5D30-AB33-11d2-8EC6-00805F29F370}
#define NS_IRDFXMLDOCUMENTOBSERVER_IID \
{ 0xeb1a5d30, 0xab33, 0x11d2, { 0x8e, 0xc6, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFXMLDataSource;
class nsIRDFXMLDataSourceObserver : public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFXMLDOCUMENTOBSERVER_IID; return iid; }
/**
* Called when the RDF/XML document begins to load.
*/
NS_IMETHOD OnBeginLoad(nsIRDFXMLDataSource* aStream) = 0;
/**
* Called when the RDF/XML document load is interrupted for some reason.
*/
NS_IMETHOD OnInterrupt(nsIRDFXMLDataSource* aStream) = 0;
/**
* Called when an interrupted RDF/XML document load is resumed.
*/
NS_IMETHOD OnResume(nsIRDFXMLDataSource* aStream) = 0;
/**
* Called whtn the RDF/XML document load is complete.
*/
NS_IMETHOD OnEndLoad(nsIRDFXMLDataSource* aStream) = 0;
/**
* Called when the root resource of the RDF/XML document is found
*/
NS_IMETHOD OnRootResourceFound(nsIRDFXMLDataSource* aStream, nsIRDFResource* aResource) = 0;
/**
* Called when a CSS style sheet is included (via XML processing
* instruction) to the document.
*/
NS_IMETHOD OnCSSStyleSheetAdded(nsIRDFXMLDataSource* aStream, nsIURL* aCSSStyleSheetURL) = 0;
/**
* Called when a named data source is included (via XML processing
* instruction) to the document.
*/
NS_IMETHOD OnNamedDataSourceAdded(nsIRDFXMLDataSource* aStream, const char* aNamedDataSourceURI) = 0;
};
// {EB1A5D31-AB33-11d2-8EC6-00805F29F370}
#define NS_IRDFXMLDATASOURCE_IID \
{ 0xeb1a5d31, 0xab33, 0x11d2, { 0x8e, 0xc6, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFXMLDataSource : public nsIRDFDataSource
{
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFXMLDATASOURCE_IID; return iid; }
/**
* Sets the RDF/XML stream to load either synchronously or
* asynchronously when nsIRDFDataSource::Init() is called.
* By default, the stream will load <em>asynchronously</em>.
*/
NS_IMETHOD SetSynchronous(PRBool aIsSynchronous) = 0;
/**
* Sets the RDF/XML stream's read-only status. By default,
* the stream will be read/write if the URL on which
* nsIRDFDataSource::Init() is called is writable.
*/
NS_IMETHOD SetReadOnly(PRBool aIsReadOnly) = 0;
/**
* Notify the document that the load is beginning.
*/
NS_IMETHOD BeginLoad(void) = 0;
/**
* Notify the document that the load is being interrupted.
*/
NS_IMETHOD Interrupt(void) = 0;
/**
* Notify the document that an interrupted load is being resumed.
*/
NS_IMETHOD Resume(void) = 0;
/**
* Notify the document that the load is ending.
*/
NS_IMETHOD EndLoad(void) = 0;
/**
* Set the root resource for the document.
*/
NS_IMETHOD SetRootResource(nsIRDFResource* aResource) = 0;
/**
* Retrieve the root resource for the document.
*/
NS_IMETHOD GetRootResource(nsIRDFResource** aResource) = 0;
/**
* Add a CSS style sheet to the document.
* @param aStyleSheetURL An nsIURL object that is the URL of the style
* sheet to add to the document.
*/
NS_IMETHOD AddCSSStyleSheetURL(nsIURL* aStyleSheetURL) = 0;
/**
* Get the set of style sheets that have been included in the
* document.
* @param aStyleSheetURLs (out) A pointer to an array of pointers to nsIURL objects.
* @param aCount (out) The number of nsIURL objects returned.
*/
NS_IMETHOD GetCSSStyleSheetURLs(nsIURL*** aStyleSheetURLs, PRInt32* aCount) = 0;
/**
* Add a named data source to the document.
* @param aNamedDataSoruceURI A URI identifying the data source.
*/
NS_IMETHOD AddNamedDataSourceURI(const char* aNamedDataSourceURI) = 0;
/**
* Get the set of named data sources that have been included in
* the document
* @param aNamedDataSourceURIs (out) A pointer to an array of C-style character
* strings.
* @param aCount (out) The number of named data sources in the array.
*/
NS_IMETHOD GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount) = 0;
/**
* Add a new namespace declaration to the RDF/XML document.
*/
NS_IMETHOD AddNameSpace(nsIAtom* aPrefix, const nsString& aURI) = 0;
/**
* Add an observer to the document. The observer will be notified of
* RDF/XML events via the nsIRDFXMLDataSourceObserver interface. Note that
* the observer is <em>not</em> reference counted.
*/
NS_IMETHOD AddXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver) = 0;
/**
* Remove an observer from the document.
*/
NS_IMETHOD RemoveXMLStreamObserver(nsIRDFXMLDataSourceObserver* aObserver) = 0;
};
// Two different kinds of XML data sources exist for RDF: serialized RDF and XUL.
// These are the methods that make these data sources.
extern nsresult
NS_NewRDFXMLDataSource(nsIRDFXMLDataSource** result);
extern nsresult
NS_NewXULDataSource(nsIRDFXMLDataSource** result);
#endif // nsIRDFXMLDataSource_h__

View File

@@ -0,0 +1,165 @@
/* -*- 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.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.
*/
/*
This interface encapsulates information about an RDF/XML file,
including the root resource, CSS style sheets, and named data
sources.
This file also includes an observer interface for nsIRDFXMLDocument
objects.
*/
#ifndef nsIRDFXMLDocument_h__
#define nsIRDFXMLDocument_h__
#include "nsISupports.h"
class nsIOutputStream;
class nsIURL;
// {EB1A5D30-AB33-11d2-8EC6-00805F29F370}
#define NS_IRDFXMLDOCUMENTOBSERVER_IID \
{ 0xeb1a5d30, 0xab33, 0x11d2, { 0x8e, 0xc6, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFXMLDocumentObserver : public nsISupports
{
public:
/**
* Called when the RDF/XML document begins to load.
*/
NS_IMETHOD OnBeginLoad(void) = 0;
/**
* Called when the RDF/XML document load is interrupted for some reason.
*/
NS_IMETHOD OnInterrupt(void) = 0;
/**
* Called when an interrupted RDF/XML document load is resumed.
*/
NS_IMETHOD OnResume(void) = 0;
/**
* Called whtn the RDF/XML document load is complete.
*/
NS_IMETHOD OnEndLoad(void) = 0;
/**
* Called when the root resource of the RDF/XML document is found
*/
NS_IMETHOD OnRootResourceFound(nsIRDFResource* aResource) = 0;
/**
* Called when a CSS style sheet is included (via XML processing
* instruction) to the document.
*/
NS_IMETHOD OnCSSStyleSheetAdded(nsIURL* aCSSStyleSheetURL) = 0;
/**
* Called when a named data source is included (via XML processing
* instruction) to the document.
*/
NS_IMETHOD OnNamedDataSourceAdded(const char* aNamedDataSourceURI) = 0;
};
// {EB1A5D31-AB33-11d2-8EC6-00805F29F370}
#define NS_IRDFXMLDOCUMENT_IID \
{ 0xeb1a5d31, 0xab33, 0x11d2, { 0x8e, 0xc6, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFXMLDocument : public nsISupports
{
public:
/**
* Notify the document that the load is beginning.
*/
NS_IMETHOD BeginLoad(void) = 0;
/**
* Notify the document that the load is being interrupted.
*/
NS_IMETHOD Interrupt(void) = 0;
/**
* Notify the document that an interrupted load is being resumed.
*/
NS_IMETHOD Resume(void) = 0;
/**
* Notify the document that the load is ending.
*/
NS_IMETHOD EndLoad(void) = 0;
/**
* Set the root resource for the document.
*/
NS_IMETHOD SetRootResource(nsIRDFResource* aResource) = 0;
/**
* Retrieve the root resource for the document.
*/
NS_IMETHOD GetRootResource(nsIRDFResource** aResource) = 0;
/**
* Add a CSS style sheet to the document.
* @param aStyleSheetURL An nsIURL object that is the URL of the style
* sheet to add to the document.
*/
NS_IMETHOD AddCSSStyleSheetURL(nsIURL* aStyleSheetURL) = 0;
/**
* Get the set of style sheets that have been included in the
* document.
* @param aStyleSheetURLs (out) A pointer to an array of pointers to nsIURL objects.
* @param aCount (out) The number of nsIURL objects returned.
*/
NS_IMETHOD GetCSSStyleSheetURLs(nsIURL*** aStyleSheetURLs, PRInt32* aCount) = 0;
/**
* Add a named data source to the document.
* @param aNamedDataSoruceURI A URI identifying the data source.
*/
NS_IMETHOD AddNamedDataSourceURI(const char* aNamedDataSourceURI) = 0;
/**
* Get the set of named data sources that have been included in
* the document
* @param aNamedDataSourceURIs (out) A pointer to an array of C-style character
* strings.
* @param aCount (out) The number of named data sources in the array.
*/
NS_IMETHOD GetNamedDataSourceURIs(const char* const** aNamedDataSourceURIs, PRInt32* aCount) = 0;
/**
* Add an observer to the document. The observer will be notified of
* RDF/XML events via the nsIRDFXMLDocumentObserver interface. Note that
* the observer is <em>not</em> reference counted.
*/
NS_IMETHOD AddDocumentObserver(nsIRDFXMLDocumentObserver* aObserver) = 0;
/**
* Remove an observer from the document.
*/
NS_IMETHOD RemoveDocumentObserver(nsIRDFXMLDocumentObserver* aObserver) = 0;
};
#endif // nsIRDFXMLDocument_h__

View File

@@ -0,0 +1,44 @@
/* -*- 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.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.
*/
/*
The RDF/XML source interface. An RDF/XML source is capable of
producing serialized RDF/XML to an output stream.
*/
#ifndef nsIRDFXMLSource_h__
#define nsIRDFXMLSource_h__
class nsIOutputStream;
// {4DA56F10-99FE-11d2-8EBB-00805F29F370}
#define NS_IRDFXMLSOURCE_IID \
{ 0x4da56f10, 0x99fe, 0x11d2, { 0x8e, 0xbb, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
class nsIRDFXMLSource : public nsISupports
{
public:
static const nsIID& IID() { static nsIID iid = NS_IRDFXMLSOURCE_IID; return iid; }
NS_IMETHOD Serialize(nsIOutputStream* aStream) = 0;
};
#endif // nsIRDFXMLSource_h__

View File

@@ -0,0 +1,50 @@
/* -*- 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.
*/
#ifndef nsRDFResource_h__
#define nsRDFResource_h__
#include "nsIRDFNode.h"
/**
* This simple base class implements nsIRDFResource, and can be used as a
* superclass for more sophisticated resource implementations.
*/
class nsRDFResource : public nsIRDFResource {
public:
NS_DECL_ISUPPORTS
// nsIRDFNode methods:
NS_IMETHOD EqualsNode(nsIRDFNode* node, PRBool* result) const;
// nsIRDFResource methods:
NS_IMETHOD GetValue(const char* *uri) const;
NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const;
NS_IMETHOD EqualsString(const char* uri, PRBool* result) const;
// nsRDFResource methods:
nsRDFResource(const char* uri);
virtual ~nsRDFResource(void);
protected:
const char* mURI;
};
#endif // nsRDFResource_h__

View File

@@ -0,0 +1,71 @@
/* -*- 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.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.
*/
/*
A catch-all header file for miscellaneous RDF stuff. Currently
contains error codes and vocabulary macros.
*/
#ifndef rdf_h___
#define rdf_h___
#include "nsError.h"
/*
* The following macros are to aid in vocabulary definition.
* They creates const char*'s for "kURI[prefix]_[name]" and
* "kTag[prefix]_[name]", with appropriate complete namespace
* qualification on the URI, e.g.,
*
* #define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
* DEFINE_RDF_ELEMENT(RDF_NAMESPACE_URI, RDF, ID);
*
* will define:
*
* kURIRDF_ID to be "http://www.w3.org/TR/WD-rdf-syntax#ID", and
* kTagRDF_ID to be "ID"
*/
#define DEFINE_RDF_VOCAB(namespace, prefix, name) \
static const char* kURI##prefix##_##name = ##namespace #name ;\
static const char* kTag##prefix##_##name = kURI##prefix##_##name## + sizeof(##namespace) - 1
/**
* Core RDF vocabularies that we use to infer semantic actions
*/
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
#define WEB_NAMESPACE_URI "http://home.netscape.com/WEB-rdf#"
#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#"
/**
* @name Standard RDF error codes
*/
/*@{*/
/* Returned from nsIRDFCursor::Advance() if the cursor has no more
elements to enuemrate */
#define NS_ERROR_RDF_CURSOR_EMPTY NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_RDF, 1)
#define NS_ERROR_RDF_NO_VALUE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_RDF, 2)
/*@}*/
#endif /* rdf_h___ */

View File

@@ -1,3 +1,4 @@
#!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
@@ -13,42 +14,44 @@
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All Rights
# Reserved.
#
DEPTH = ../../..
DEPTH=../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = nkcacke
LIBRARY_NAME = necko_cache
IS_COMPONENT = 1
include $(topsrcdir)/config/config.mk
CPPSRCS = nsNetDataCacheModule.cpp
LIBRARY_NAME = rdfbase_s
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)
CPPSRCS = \
nsCompositeDataSource.cpp \
nsContainerCursor.cpp \
nsDefaultResourceFactory.cpp \
nsEmptyCursor.cpp \
nsInMemoryDataSource.cpp \
nsRDFContentSink.cpp \
nsRDFParserUtils.cpp \
nsRDFService.cpp \
nsRDFXMLDataSource.cpp \
rdfutil.cpp \
nsRDFResource.cpp \
$(NULL)
LOCAL_INCLUDES = \
-I$(DEPTH)/netwerk/cache/memcache \
-I$(DEPTH)/netwerk/cache/filecache \
-I$(DEPTH)/netwerk/cache/mgr \
$(NULL)
EXPORTS = \
$(NULL)
EXTRA_DSO_LDOPTS = \
$(MKSHLIB_FORCE_ALL) \
$(SHARED_LIBRARY_LIBS) \
$(MKSHLIB_UNFORCE_ALL) \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
MODULE = rdfbase
REQUIRES = netlib rdf raptor xpcom
MKSHLIB :=
# we don't want the shared lib
NO_SHARED_LIB=1
include $(topsrcdir)/config/rules.mk
$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile

View File

@@ -0,0 +1,48 @@
#!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=..\..\..
MODULE=rdf
LIBRARY_NAME=rdfbase_s
CPP_OBJS=\
.\$(OBJDIR)\nsCompositeDataSource.obj \
.\$(OBJDIR)\nsContainerCursor.obj \
.\$(OBJDIR)\nsDefaultResourceFactory.obj \
.\$(OBJDIR)\nsEmptyCursor.obj \
.\$(OBJDIR)\nsInMemoryDataSource.obj \
.\$(OBJDIR)\nsRDFContentSink.obj \
.\$(OBJDIR)\nsRDFParserUtils.obj \
.\$(OBJDIR)\nsRDFService.obj \
.\$(OBJDIR)\nsRDFXMLDataSource.obj \
.\$(OBJDIR)\rdfutil.obj \
.\$(OBJDIR)\nsRDFResource.obj \
$(NULL)
LINCS= -I$(PUBLIC)\rdf \
-I$(PUBLIC)\xpcom \
-I$(PUBLIC)\raptor \
-I$(PUBLIC)\netlib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
libs:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,887 @@
/* -*- 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.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.
*/
/*
A simple composite data source implementation. A composit data
source is just a strategy for combining individual data sources into
a collective graph.
1) A composite data source holds a sequence of data sources. The set
of data sources can be specified during creation of the
database. Data sources can also be added/deleted from a database
later.
2) The aggregation mechanism is based on simple super-positioning of
the graphs from the datasources. If there is a conflict (i.e.,
data source A has a true arc from foo to bar while data source B
has a false arc from foo to bar), the data source that it earlier
in the sequence wins.
The implementation below doesn't really do this and needs to be
fixed.
*/
#include "nsIRDFCursor.h"
#include "nsIRDFNode.h"
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFObserver.h"
#include "nsRepository.h"
#include "nsVoidArray.h"
#include "prlog.h"
static NS_DEFINE_IID(kIRDFArcsInCursorIID, NS_IRDFARCSINCURSOR_IID);
static NS_DEFINE_IID(kIRDFArcsOutCursorIID, NS_IRDFARCSOUTCURSOR_IID);
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
static NS_DEFINE_IID(kIRDFCompositeDataSourceIID, NS_IRDFCOMPOSITEDATASOURCE_IID);
static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID);
static NS_DEFINE_IID(kIRDFObserverIID, NS_IRDFOBSERVER_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
////////////////////////////////////////////////////////////////////////
// CompositeDataSourceImpl
class CompositeDataSourceImpl : public nsIRDFCompositeDataSource,
public nsIRDFObserver
{
protected:
nsVoidArray* mObservers;
virtual ~CompositeDataSourceImpl(void);
public:
CompositeDataSourceImpl(void);
CompositeDataSourceImpl(char** dataSources);
nsVoidArray mDataSources;
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIRDFDataSource interface
NS_IMETHOD Init(const char* uri);
NS_IMETHOD GetURI(const char* *uri) const;
NS_IMETHOD GetSource(nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
nsIRDFResource** source);
NS_IMETHOD GetSources(nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
nsIRDFAssertionCursor** sources);
NS_IMETHOD GetTarget(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsIRDFNode** target);
NS_IMETHOD GetTargets(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsIRDFAssertionCursor** targets);
NS_IMETHOD Assert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv);
NS_IMETHOD Unassert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target);
NS_IMETHOD HasAssertion(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
PRBool* hasAssertion);
NS_IMETHOD AddObserver(nsIRDFObserver* n);
NS_IMETHOD RemoveObserver(nsIRDFObserver* n);
NS_IMETHOD ArcLabelsIn(nsIRDFNode* node,
nsIRDFArcsInCursor** labels);
NS_IMETHOD ArcLabelsOut(nsIRDFResource* source,
nsIRDFArcsOutCursor** labels);
NS_IMETHOD GetAllResources(nsIRDFResourceCursor** aCursor);
NS_IMETHOD Flush();
NS_IMETHOD IsCommandEnabled(const char* aCommand,
nsIRDFResource* aCommandTarget,
PRBool* aResult);
NS_IMETHOD DoCommand(const char* aCommand,
nsIRDFResource* aCommandTarget);
// nsIRDFCompositeDataSource interface
NS_IMETHOD AddDataSource(nsIRDFDataSource* source);
NS_IMETHOD RemoveDataSource(nsIRDFDataSource* source);
// nsIRDFObserver interface
NS_IMETHOD OnAssert(nsIRDFResource* subject,
nsIRDFResource* predicate,
nsIRDFNode* object);
NS_IMETHOD OnUnassert(nsIRDFResource* subject,
nsIRDFResource* predicate,
nsIRDFNode* object);
// Implementation methods
PRBool HasAssertionN(int n, nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv);
};
class DBArcsInOutCursor : public nsIRDFArcsOutCursor,
public nsIRDFArcsInCursor
{
CompositeDataSourceImpl* mCompositeDataSourceImpl;
nsIRDFResource* mSource;
nsIRDFNode* mTarget;
PRInt32 mCount;
nsIRDFArcsOutCursor* mOutCursor;
nsIRDFArcsInCursor* mInCursor;
nsVoidArray mResults;
public:
DBArcsInOutCursor(CompositeDataSourceImpl* db, nsIRDFNode* node, PRBool arcsOutp);
virtual ~DBArcsInOutCursor();
NS_DECL_ISUPPORTS
NS_IMETHOD Advance();
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
return (mInCursor ? mInCursor->GetDataSource(aDataSource) :
mOutCursor->GetDataSource(aDataSource));
}
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
return mOutCursor->GetSubject(aResource);
}
NS_IMETHOD GetObject(nsIRDFNode** aNode) {
return mInCursor->GetObject(aNode);
}
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
return (mInCursor ? mInCursor->GetPredicate(aPredicate) :
mOutCursor->GetPredicate(aPredicate));
}
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
return (mInCursor ? mInCursor->GetValue(aValue) :
mOutCursor->GetValue(aValue));
}
};
DBArcsInOutCursor::DBArcsInOutCursor(CompositeDataSourceImpl* db,
nsIRDFNode* node,
PRBool arcsOutp)
: mCompositeDataSourceImpl(db),
mTarget(0),
mSource(0),
mCount(0),
mInCursor(0),
mOutCursor(0)
{
NS_INIT_REFCNT();
NS_ADDREF(mCompositeDataSourceImpl);
if (arcsOutp) {
mSource = (nsIRDFResource*) node;
} else {
mTarget = node;
}
NS_IF_ADDREF(node);
// XXX there better be at least _one_ datasource in this here
// CompositeDataSourceImpl, else this'll be a real short ride...
PR_ASSERT(db->mDataSources.Count() > 0);
nsIRDFDataSource* ds = (nsIRDFDataSource*) db->mDataSources[mCount++];
if (mTarget) {
ds->ArcLabelsIn(mTarget, &mInCursor);
} else {
ds->ArcLabelsOut(mSource, &mOutCursor);
}
}
DBArcsInOutCursor::~DBArcsInOutCursor(void)
{
for (PRInt32 i = mResults.Count() - 1; i >= 0; --i) {
nsIRDFNode* node = (nsIRDFNode*) mResults[i];
NS_RELEASE(node);
}
NS_IF_RELEASE(mSource);
NS_IF_RELEASE(mTarget);
NS_IF_RELEASE(mInCursor);
NS_IF_RELEASE(mOutCursor);
NS_RELEASE(mCompositeDataSourceImpl);
}
NS_IMPL_ADDREF(DBArcsInOutCursor);
NS_IMPL_RELEASE(DBArcsInOutCursor);
NS_IMETHODIMP_(nsresult)
DBArcsInOutCursor::QueryInterface(REFNSIID iid, void** result) {
if (! result)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIRDFArcsOutCursorIID) ||
iid.Equals(kIRDFCursorIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFArcsOutCursor*, this);
NS_ADDREF(this);
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
DBArcsInOutCursor::Advance(void)
{
nsIRDFDataSource* ds;
while (mInCursor || mOutCursor) {
nsresult result = (mInCursor ? mInCursor->Advance() : mOutCursor->Advance());
while (NS_SUCCEEDED(result)) {
nsIRDFNode* obj ;
GetValue(&obj);
if (mResults.IndexOf(obj) < 0) {
mResults.AppendElement(obj);
return NS_OK;
}
result = (mInCursor ? mInCursor->Advance() : mOutCursor->Advance());
}
if (result != NS_ERROR_RDF_CURSOR_EMPTY)
return result;
NS_IF_RELEASE(mInCursor);
NS_IF_RELEASE(mOutCursor);
if (mCount >= mCompositeDataSourceImpl->mDataSources.Count())
break;
ds = (nsIRDFDataSource*) mCompositeDataSourceImpl->mDataSources[mCount];
++mCount;
if (mTarget) {
ds->ArcLabelsIn(mTarget, &mInCursor);
} else {
ds->ArcLabelsOut(mSource, &mOutCursor);
}
}
return NS_ERROR_RDF_CURSOR_EMPTY;
}
////////////////////////////////////////////////////////////////////////
// DBAssertionCursor
//
// An assertion cursor implementation for the db.
//
class DBGetSTCursor : public nsIRDFAssertionCursor
{
private:
CompositeDataSourceImpl* mCompositeDataSourceImpl;
nsIRDFResource* mSource;
nsIRDFResource* mLabel;
nsIRDFNode* mTarget;
PRInt32 mCount;
PRBool mTruthValue;
nsIRDFAssertionCursor* mCurrentCursor;
public:
DBGetSTCursor(CompositeDataSourceImpl* db, nsIRDFNode* u,
nsIRDFResource* property, PRBool inversep, PRBool tv);
virtual ~DBGetSTCursor();
// nsISupports interface
NS_DECL_ISUPPORTS
// nsIRDFAssertionCursor interface
NS_IMETHOD Advance();
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
return mCurrentCursor->GetDataSource(aDataSource);
}
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
return mCurrentCursor->GetSubject(aResource);
}
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
return mCurrentCursor->GetPredicate(aPredicate);
}
NS_IMETHOD GetObject(nsIRDFNode** aObject) {
return mCurrentCursor->GetObject(aObject);
}
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
return mCurrentCursor->GetTruthValue(aTruthValue);
}
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
return mCurrentCursor->GetValue(aValue);
}
};
//NS_IMPL_ISUPPORTS(DBGetSTCursor, kIRDFAssertionCursorIID);
DBGetSTCursor::DBGetSTCursor(CompositeDataSourceImpl* db,
nsIRDFNode* u,
nsIRDFResource* property,
PRBool inversep,
PRBool tv)
: mCompositeDataSourceImpl(db),
mSource(nsnull),
mLabel(property),
mTarget(nsnull),
mCount(0),
mTruthValue(tv),
mCurrentCursor(nsnull)
{
NS_INIT_REFCNT();
NS_ADDREF(mCompositeDataSourceImpl);
if (!inversep) {
mSource = (nsIRDFResource*) u;
} else {
mTarget = u;
}
NS_IF_ADDREF(mSource);
NS_IF_ADDREF(mTarget);
NS_IF_ADDREF(mLabel);
// XXX assume that at least one data source exists in the CompositeDataSourceImpl.
nsIRDFDataSource* ds = (nsIRDFDataSource*) db->mDataSources[mCount++];
if (mSource)
ds->GetTargets(mSource, mLabel, mTruthValue, &mCurrentCursor);
else
ds->GetSources(mLabel, mTarget, mTruthValue, &mCurrentCursor);
}
DBGetSTCursor::~DBGetSTCursor(void)
{
NS_IF_RELEASE(mCurrentCursor);
NS_IF_RELEASE(mLabel);
NS_IF_RELEASE(mSource);
NS_IF_RELEASE(mTarget);
NS_RELEASE(mCompositeDataSourceImpl);
}
NS_IMPL_ADDREF(DBGetSTCursor);
NS_IMPL_RELEASE(DBGetSTCursor);
NS_IMETHODIMP_(nsresult)
DBGetSTCursor::QueryInterface(REFNSIID iid, void** result)
{
if (! result)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIRDFAssertionCursorIID) ||
iid.Equals(kIRDFCursorIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFAssertionCursor*, this);
NS_ADDREF(this);
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
DBGetSTCursor::Advance(void)
{
nsIRDFDataSource* ds;
while (mCurrentCursor) {
nsresult result = mCurrentCursor->Advance();
while (NS_ERROR_RDF_CURSOR_EMPTY != result) {
nsIRDFResource* src;
nsIRDFNode* trg;
mCurrentCursor->GetSubject(&src);
mCurrentCursor->GetObject(&trg);
if (!mCompositeDataSourceImpl->HasAssertionN(mCount-1, src, mLabel, trg, !mTruthValue)) {
return NS_OK;
} else {
result = mCurrentCursor->Advance();
}
}
if (mCount >= mCompositeDataSourceImpl->mDataSources.Count())
break;
ds = (nsIRDFDataSource*) mCompositeDataSourceImpl->mDataSources[mCount];
++mCount;
NS_RELEASE(mCurrentCursor);
if (mSource)
ds->GetTargets(mSource, mLabel, mTruthValue, &mCurrentCursor);
else
ds->GetSources(mLabel, mTarget, mTruthValue, &mCurrentCursor);
}
return NS_ERROR_RDF_CURSOR_EMPTY;
}
////////////////////////////////////////////////////////////////////////
nsresult
NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result)
{
CompositeDataSourceImpl* db = new CompositeDataSourceImpl();
if (! db)
return NS_ERROR_OUT_OF_MEMORY;
*result = db;
NS_ADDREF(*result);
return NS_OK;
}
CompositeDataSourceImpl::CompositeDataSourceImpl(void)
: mObservers(nsnull)
{
NS_INIT_REFCNT();
}
CompositeDataSourceImpl::~CompositeDataSourceImpl(void)
{
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
ds->RemoveObserver(this);
NS_IF_RELEASE(ds);
}
delete mObservers;
}
////////////////////////////////////////////////////////////////////////
// nsISupports interface
NS_IMPL_ADDREF(CompositeDataSourceImpl);
NS_IMPL_RELEASE(CompositeDataSourceImpl);
NS_IMETHODIMP
CompositeDataSourceImpl::QueryInterface(REFNSIID iid, void** result)
{
if (! result)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIRDFCompositeDataSourceIID) ||
iid.Equals(kIRDFDataSourceIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFCompositeDataSource*, this);
NS_ADDREF(this);
return NS_OK;
}
else if (iid.Equals(kIRDFObserverIID)) {
*result = NS_STATIC_CAST(nsIRDFObserver*, this);
NS_ADDREF(this);
return NS_OK;
}
else {
*result = nsnull;
return NS_NOINTERFACE;
}
}
////////////////////////////////////////////////////////////////////////
// nsIRDFDataSource interface
NS_IMETHODIMP
CompositeDataSourceImpl::Init(const char* uri)
{
PR_ASSERT(0);
return NS_ERROR_UNEXPECTED; // XXX CompositeDataSourceImpl doesn't have a URI?
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetURI(const char* *uri) const
{
PR_ASSERT(0);
return NS_ERROR_UNEXPECTED; // XXX CompositeDataSourceImpl doesn't have a URI?
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetSource(nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
nsIRDFResource** source)
{
PRInt32 count = mDataSources.Count();
for (PRInt32 i = 0; i < count; ++i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
if (NS_FAILED(ds->GetSource(property, target, tv, source)))
continue;
// okay, found it. make sure we don't have the opposite
// asserted in a more local data source
if (!HasAssertionN(count-1, *source, property, target, !tv))
return NS_OK;
NS_RELEASE(*source);
return NS_ERROR_RDF_NO_VALUE;
}
return NS_ERROR_RDF_NO_VALUE;
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetSources(nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
nsIRDFAssertionCursor** result)
{
if (! result)
return NS_ERROR_NULL_POINTER;
*result = new DBGetSTCursor(this, target, property, 1, tv);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*result);
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetTarget(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsIRDFNode** target)
{
PRInt32 count = mDataSources.Count();
for (PRInt32 i = 0; i < count; ++i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
if (NS_FAILED(ds->GetTarget(source, property, tv, target)))
continue;
// okay, found it. make sure we don't have the opposite
// asserted in the "local" data source
if (!HasAssertionN(count-1, source, property, *target, !tv))
return NS_OK;
NS_RELEASE(*target);
return NS_ERROR_RDF_NO_VALUE;
}
return NS_ERROR_RDF_NO_VALUE;
}
PRBool
CompositeDataSourceImpl::HasAssertionN(int n,
nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv)
{
int m = 0;
PRBool result = 0;
while (m < n) {
nsIRDFDataSource* ds = (nsIRDFDataSource*) mDataSources[m];
ds->HasAssertion(source, property, target, tv, &result);
if (result) return 1;
m++;
}
return 0;
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetTargets(nsIRDFResource* source,
nsIRDFResource* property,
PRBool tv,
nsIRDFAssertionCursor** targets)
{
if (! targets)
return NS_ERROR_NULL_POINTER;
nsIRDFAssertionCursor* result;
result = new DBGetSTCursor(this, source, property, 0, tv);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(result);
*targets = result;
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::Assert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv)
{
// Need to add back the stuff for unblocking ...
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
if (NS_SUCCEEDED(ds->Assert(source, property, target, tv)))
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
CompositeDataSourceImpl::Unassert(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target)
{
nsresult rv;
PRInt32 count = mDataSources.Count();
for (PRInt32 i = 0; i < count; ++i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
if (NS_FAILED(rv = ds->Unassert(source, property, target)))
break;
}
if (NS_FAILED(rv)) {
nsIRDFDataSource* ds0 = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[0]);
rv = ds0->Assert(source, property, target, PR_FALSE);
}
return rv;
}
NS_IMETHODIMP
CompositeDataSourceImpl::HasAssertion(nsIRDFResource* source,
nsIRDFResource* property,
nsIRDFNode* target,
PRBool tv,
PRBool* hasAssertion)
{
nsresult rv;
// Otherwise, look through all the data sources to see if anyone
// has the positive...
PRInt32 count = mDataSources.Count();
PRBool hasNegation = 0;
for (PRInt32 i = 0; i < count; ++i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
if (NS_FAILED(rv = ds->HasAssertion(source, property, target, tv, hasAssertion)))
return rv;
if (*hasAssertion)
return NS_OK;
if (NS_FAILED(rv = ds->HasAssertion(source, property, target, !tv, &hasNegation)))
return rv;
if (hasNegation) {
*hasAssertion = 0;
return NS_OK;
}
}
// If we get here, nobody had the assertion at all
*hasAssertion = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::AddObserver(nsIRDFObserver* obs)
{
if (!mObservers) {
if ((mObservers = new nsVoidArray()) == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
}
// XXX ensure uniqueness?
mObservers->AppendElement(obs);
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::RemoveObserver(nsIRDFObserver* obs)
{
if (!mObservers)
return NS_OK;
mObservers->RemoveElement(obs);
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode* node,
nsIRDFArcsInCursor** labels)
{
if (! labels)
return NS_ERROR_NULL_POINTER;
nsIRDFArcsInCursor* result = new DBArcsInOutCursor(this, node, 0);
if (! result)
return NS_ERROR_NULL_POINTER;
NS_ADDREF(result);
*labels = result;
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* source,
nsIRDFArcsOutCursor** labels)
{
if (! labels)
return NS_ERROR_NULL_POINTER;
nsIRDFArcsOutCursor* result = new DBArcsInOutCursor(this, source, 1);
if (! result)
return NS_ERROR_NULL_POINTER;
NS_ADDREF(result);
*labels = result;
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetAllResources(nsIRDFResourceCursor** aCursor)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
CompositeDataSourceImpl::Flush()
{
for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
ds->Flush();
}
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::IsCommandEnabled(const char* aCommand,
nsIRDFResource* aCommandTarget,
PRBool* aResult)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
CompositeDataSourceImpl::DoCommand(const char* aCommand,
nsIRDFResource* aCommandTarget)
{
NS_NOTYETIMPLEMENTED("write me!");
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////
// nsIRDFCompositeDataSource methods
// XXX rvg We should make this take an additional argument specifying where
// in the sequence of data sources (of the db), the new data source should
// fit in. Right now, the new datasource gets stuck at the end.
// need to add the observers of the CompositeDataSourceImpl to the new data source.
NS_IMETHODIMP
CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* source)
{
NS_ASSERTION(source != nsnull, "null ptr");
if (! source)
return NS_ERROR_NULL_POINTER;
mDataSources.InsertElementAt(source, 0);
source->AddObserver(this);
NS_ADDREF(source);
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::RemoveDataSource(nsIRDFDataSource* source)
{
NS_ASSERTION(source != nsnull, "null ptr");
if (! source)
return NS_ERROR_NULL_POINTER;
if (mDataSources.IndexOf(source) >= 0) {
mDataSources.RemoveElement(source);
source->RemoveObserver(this);
NS_RELEASE(source);
}
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::OnAssert(nsIRDFResource* subject,
nsIRDFResource* predicate,
nsIRDFNode* object)
{
if (mObservers) {
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
obs->OnAssert(subject, predicate, object);
// XXX ignore return value?
}
}
return NS_OK;
}
NS_IMETHODIMP
CompositeDataSourceImpl::OnUnassert(nsIRDFResource* subject,
nsIRDFResource* predicate,
nsIRDFNode* object)
{
if (mObservers) {
for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) {
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
obs->OnUnassert(subject, predicate, object);
// XXX ignore return value?
}
}
return NS_OK;
}

View File

@@ -0,0 +1,339 @@
/* -*- 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.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.
*/
/*
A simple cursor that enumerates the elements of an RDF container
(RDF:Bag, RDF:Seq, or RDF:Alt).
Caveats
-------
1. This uses an implementation-specific detail to determine the
index of the last element in the container; specifically, the RDF
utilities maintain a counter attribute on the container that
holds the numeric value of the next value that is to be
assigned. So, this cursor will bust if you use it with a bag that
hasn't been created using the RDF utility routines.
2. This is sort of a continuation of (1), but -- it's not smart
enough to notice duplicates.
TODO. This is way too brain dead to handle aggregated RDF
databases. It needs to be upgraded in a big way.
*/
#include "nscore.h"
#include "nsIRDFCursor.h"
#include "nsIRDFDataSource.h"
#include "nsIRDFNode.h"
#include "nsIRDFService.h"
#include "nsIServiceManager.h"
#include "nsRDFCID.h"
#include "nsString.h"
#include "prlog.h"
#include "rdf.h"
#include "rdfutil.h"
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
////////////////////////////////////////////////////////////////////////
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, nextVal); // ad hoc way to make containers fast
////////////////////////////////////////////////////////////////////////
class ContainerCursorImpl : public nsIRDFAssertionCursor {
private:
// pseudo-constants
static nsrefcnt gRefCnt;
static nsIRDFResource* kRDF_nextVal;
nsIRDFDataSource* mDataSource;
nsIRDFResource* mContainer;
nsIRDFNode* mCurrent;
nsIRDFResource* mOrdinalProperty;
PRInt32 mNextIndex;
public:
ContainerCursorImpl(nsIRDFDataSource* ds, nsIRDFResource* container);
virtual ~ContainerCursorImpl(void);
NS_DECL_ISUPPORTS
NS_IMETHOD Advance(void);
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource);
NS_IMETHOD GetSubject(nsIRDFResource** aResource);
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate);
NS_IMETHOD GetObject(nsIRDFNode** aObject);
NS_IMETHOD GetTruthValue(PRBool* aTruthValue);
NS_IMETHOD GetValue(nsIRDFNode** aValue);
};
nsrefcnt ContainerCursorImpl::gRefCnt;
nsIRDFResource* ContainerCursorImpl::kRDF_nextVal;
ContainerCursorImpl::ContainerCursorImpl(nsIRDFDataSource* ds,
nsIRDFResource* container)
: mDataSource(ds),
mContainer(container),
mCurrent(nsnull),
mOrdinalProperty(nsnull),
mNextIndex(1)
{
NS_INIT_REFCNT();
NS_IF_ADDREF(mDataSource);
NS_IF_ADDREF(mContainer);
if (gRefCnt++ == 0) {
nsresult rv;
nsIRDFService* service;
rv = nsServiceManager::GetService(kRDFServiceCID,
kIRDFServiceIID,
(nsISupports**) &service);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to acquire resource manager");
if (! service)
return;
NS_VERIFY(NS_SUCCEEDED(rv = service->GetResource(kURIRDF_nextVal, &kRDF_nextVal)),
"unable to get resource");
}
}
ContainerCursorImpl::~ContainerCursorImpl(void)
{
NS_IF_RELEASE(mCurrent);
NS_IF_RELEASE(mOrdinalProperty);
NS_IF_RELEASE(mContainer);
NS_IF_RELEASE(mDataSource);
if (--gRefCnt == 0) {
NS_IF_RELEASE(kRDF_nextVal);
}
}
NS_IMPL_ADDREF(ContainerCursorImpl);
NS_IMPL_RELEASE(ContainerCursorImpl);
NS_IMETHODIMP_(nsresult)
ContainerCursorImpl::QueryInterface(REFNSIID iid, void** result) {
if (! result)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIRDFAssertionCursorIID) ||
iid.Equals(kIRDFCursorIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFAssertionCursor*, this);
/* AddRef(); // not necessary */
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
ContainerCursorImpl::Advance(void)
{
nsresult rv;
// release the last value that we were holding
NS_IF_RELEASE(mCurrent);
nsIRDFNode* nextNode = nsnull;
nsIRDFLiteral* nextVal = nsnull;
const PRUnichar* p;
nsAutoString s;
PRInt32 last;
PRInt32 err;
// Figure out the upper bound so we'll know when we're done.
// XXX we could cache all this crap when the cursor gets created.
if (NS_FAILED(rv = mDataSource->GetTarget(mContainer, kRDF_nextVal, PR_TRUE, &nextNode)))
goto done;
if (NS_FAILED(rv = nextNode->QueryInterface(kIRDFLiteralIID, (void**) &nextVal)))
goto done;
if (NS_FAILED(rv = nextVal->GetValue(&p)))
goto done;
s = p;
last = s.ToInteger(&err);
if (NS_FAILED(err))
goto done;
// initialize rv to the case where mNextIndex has advanced past the
// last element
rv = NS_ERROR_RDF_CURSOR_EMPTY;
while (mNextIndex < last) {
NS_IF_RELEASE(mOrdinalProperty);
if (NS_FAILED(rv = rdf_IndexToOrdinalResource(mNextIndex, &mOrdinalProperty)))
break;
rv = mDataSource->GetTarget(mContainer, mOrdinalProperty, PR_TRUE, &mCurrent);
++mNextIndex;
if (NS_SUCCEEDED(rv)) {
// Don't bother releasing mCurrent; we'll let the AddRef
// serve as the implicit addref that GetNext() should
// perform.
break;
}
}
done:
NS_IF_RELEASE(nextNode);
NS_IF_RELEASE(nextVal);
return rv;
}
NS_IMETHODIMP
ContainerCursorImpl::GetDataSource(nsIRDFDataSource** aDataSource)
{
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
if (! aDataSource)
return NS_ERROR_NULL_POINTER;
NS_ADDREF(mDataSource);
*aDataSource = mDataSource;
return NS_OK;
}
NS_IMETHODIMP
ContainerCursorImpl::GetSubject(nsIRDFResource** aSubject)
{
NS_PRECONDITION(aSubject != nsnull, "null ptr");
if (! aSubject)
return NS_ERROR_NULL_POINTER;
NS_ADDREF(mContainer);
*aSubject = mContainer;
return NS_OK;
}
NS_IMETHODIMP
ContainerCursorImpl::GetPredicate(nsIRDFResource** aPredicate)
{
NS_PRECONDITION(aPredicate != nsnull, "null ptr");
if (! aPredicate)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(mOrdinalProperty, "unexpected");
if (! mOrdinalProperty)
return NS_ERROR_UNEXPECTED;
NS_ADDREF(mOrdinalProperty);
*aPredicate = mOrdinalProperty;
return NS_OK;
}
NS_IMETHODIMP
ContainerCursorImpl::GetObject(nsIRDFNode** aObject)
{
NS_PRECONDITION(aObject != nsnull, "null ptr");
if (! aObject)
return NS_ERROR_NULL_POINTER;
NS_PRECONDITION(mCurrent, "unexpected");
if (! mCurrent)
return NS_ERROR_UNEXPECTED;
NS_ADDREF(mCurrent);
*aObject = mCurrent;
return NS_OK;
}
NS_IMETHODIMP
ContainerCursorImpl::GetValue(nsIRDFNode** aObject)
{
NS_PRECONDITION(aObject != nsnull, "null ptr");
if (! aObject)
return NS_ERROR_NULL_POINTER;
if (! mCurrent)
return NS_ERROR_UNEXPECTED;
NS_ADDREF(mCurrent);
*aObject = mCurrent;
return NS_OK;
}
NS_IMETHODIMP
ContainerCursorImpl::GetTruthValue(PRBool* aTruthValue)
{
NS_PRECONDITION(aTruthValue != nsnull, "null ptr");
if (! aTruthValue)
return NS_ERROR_NULL_POINTER;
*aTruthValue = PR_TRUE;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
nsresult
NS_NewContainerCursor(nsIRDFDataSource* ds,
nsIRDFResource* container,
nsIRDFAssertionCursor** cursor)
{
NS_PRECONDITION(ds != nsnull, "null ptr");
NS_PRECONDITION(container != nsnull, "null ptr");
NS_PRECONDITION(cursor != nsnull, "null ptr");
if (!ds || !container || !cursor)
return NS_ERROR_NULL_POINTER;
NS_ASSERTION(rdf_IsContainer(ds, container), "not a container");
if (! rdf_IsContainer(ds, container))
return NS_ERROR_ILLEGAL_VALUE;
ContainerCursorImpl* result = new ContainerCursorImpl(ds, container);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
*cursor = result;
NS_ADDREF(result);
return NS_OK;
}

View File

@@ -0,0 +1,229 @@
/* -*- 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.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.
*/
/*
The default resource factory implementation. This resource factory
produces nsIRDFResource objects for any URI prefix that is not
covered by some other factory.
*/
#include "nsIRDFNode.h"
#include "nsIRDFResourceFactory.h"
#include "nsIRDFService.h"
#include "nsIServiceManager.h"
#include "nsRDFCID.h"
#include "plstr.h"
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
static NS_DEFINE_IID(kIRDFResourceFactoryIID, NS_IRDFRESOURCEFACTORY_IID);
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
////////////////////////////////////////////////////////////////////////
class DefaultResourceImpl : public nsIRDFResource
{
public:
DefaultResourceImpl(const char* uri);
virtual ~DefaultResourceImpl(void);
// nsISupports
NS_DECL_ISUPPORTS
// nsIRDFNode
NS_IMETHOD EqualsNode(nsIRDFNode* node, PRBool* result) const;
// nsIRDFResource
NS_IMETHOD GetValue(const char* *uri) const;
NS_IMETHOD EqualsResource(const nsIRDFResource* resource, PRBool* result) const;
NS_IMETHOD EqualsString(const char* uri, PRBool* result) const;
// Implementation methods
const char* GetURI(void) const {
return mURI;
}
private:
char* mURI;
};
DefaultResourceImpl::DefaultResourceImpl(const char* uri)
{
NS_INIT_REFCNT();
mURI = PL_strdup(uri);
}
DefaultResourceImpl::~DefaultResourceImpl(void)
{
nsresult rv;
nsIRDFService* mgr;
rv = nsServiceManager::GetService(kRDFServiceCID,
kIRDFServiceIID,
(nsISupports**) &mgr);
PR_ASSERT(NS_SUCCEEDED(rv));
if (NS_SUCCEEDED(rv)) {
mgr->UnCacheResource(this);
nsServiceManager::ReleaseService(kRDFServiceCID, mgr);
}
// N.B. that we need to free the URI *after* we un-cache the resource,
// due to the way that the resource manager is implemented.
PL_strfree(mURI);
}
NS_IMPL_ADDREF(DefaultResourceImpl);
NS_IMPL_RELEASE(DefaultResourceImpl);
nsresult
DefaultResourceImpl::QueryInterface(REFNSIID iid, void** result)
{
if (! result)
return NS_ERROR_NULL_POINTER;
*result = nsnull;
if (iid.Equals(kIRDFResourceIID) ||
iid.Equals(kIRDFNodeIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFResource*, this);
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
DefaultResourceImpl::EqualsNode(nsIRDFNode* node, PRBool* result) const
{
nsresult rv;
nsIRDFResource* resource;
if (NS_SUCCEEDED(node->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
rv = EqualsResource(resource, result);
NS_RELEASE(resource);
}
else {
*result = PR_FALSE;
rv = NS_OK;
}
return rv;
}
NS_IMETHODIMP
DefaultResourceImpl::GetValue(const char* *uri) const
{
if (!uri)
return NS_ERROR_NULL_POINTER;
*uri = mURI;
return NS_OK;
}
NS_IMETHODIMP
DefaultResourceImpl::EqualsResource(const nsIRDFResource* resource, PRBool* result) const
{
if (!resource || !result)
return NS_ERROR_NULL_POINTER;
*result = (resource == this);
return NS_OK;
}
NS_IMETHODIMP
DefaultResourceImpl::EqualsString(const char* uri, PRBool* result) const
{
if (!uri || !result)
return NS_ERROR_NULL_POINTER;
*result = (PL_strcmp(uri, mURI) == 0);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
class DefaultResourceFactoryImpl : public nsIRDFResourceFactory
{
public:
DefaultResourceFactoryImpl(void);
virtual ~DefaultResourceFactoryImpl(void);
NS_DECL_ISUPPORTS
NS_IMETHOD CreateResource(const char* aURI, nsIRDFResource** aResult);
};
DefaultResourceFactoryImpl::DefaultResourceFactoryImpl(void)
{
NS_INIT_REFCNT();
}
DefaultResourceFactoryImpl::~DefaultResourceFactoryImpl(void)
{
}
NS_IMPL_ISUPPORTS(DefaultResourceFactoryImpl, kIRDFResourceFactoryIID);
NS_IMETHODIMP
DefaultResourceFactoryImpl::CreateResource(const char* aURI, nsIRDFResource** aResult)
{
NS_PRECONDITION(aResult != nsnull, "null ptr");
if (! aResult)
return NS_ERROR_NULL_POINTER;
DefaultResourceImpl* resource = new DefaultResourceImpl(aURI);
if (! resource)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(resource);
*aResult = resource;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
nsresult
NS_NewRDFDefaultResourceFactory(nsIRDFResourceFactory** result)
{
NS_PRECONDITION(result != nsnull, "null ptr");
if (! result)
return NS_ERROR_NULL_POINTER;
DefaultResourceFactoryImpl* factory = new DefaultResourceFactoryImpl();
if (! factory)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(factory);
*result = factory;
return NS_OK;
}

View File

@@ -0,0 +1,240 @@
/* -*- 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.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.
*/
/*
A set of "empty cursors" (nsIRDFAssertionCursor,
nsIRDFArcsOutCursor, nsIRDFArcsInCursor) that can be used to ensure
that the data source methods which return a cursor always return
*something*.
*/
#include "nscore.h"
#include "nsIRDFCursor.h"
static NS_DEFINE_IID(kIRDFArcsInCursorIID, NS_IRDFARCSINCURSOR_IID);
static NS_DEFINE_IID(kIRDFArcsOutCursorIID, NS_IRDFARCSOUTCURSOR_IID);
static NS_DEFINE_IID(kIRDFAssertionCursorIID, NS_IRDFASSERTIONCURSOR_IID);
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
////////////////////////////////////////////////////////////////////////
class EmptyAssertionCursorImpl : public nsIRDFAssertionCursor
{
public:
EmptyAssertionCursorImpl(void) {};
virtual ~EmptyAssertionCursorImpl(void) {};
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef(void) {
return 2;
}
NS_IMETHOD_(nsrefcnt) Release(void) {
return 1;
}
NS_IMETHOD QueryInterface(REFNSIID iid, void** result) {
if (! result)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIRDFAssertionCursorIID) ||
iid.Equals(kIRDFCursorIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFAssertionCursor*, this);
/* AddRef(); // not necessary */
return NS_OK;
}
return NS_NOINTERFACE;
}
// nsIRDFCursor
NS_IMETHOD Advance(void) {
return NS_ERROR_RDF_CURSOR_EMPTY;
}
// nsIRDFAssertionCursor
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetObject(nsIRDFNode** aObject) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
return NS_ERROR_UNEXPECTED;
}
};
nsresult
NS_NewEmptyRDFAssertionCursor(nsIRDFAssertionCursor** result)
{
static EmptyAssertionCursorImpl gEmptyAssertionCursor;
*result = &gEmptyAssertionCursor;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
class EmptyArcsOutCursorImpl : public nsIRDFArcsOutCursor
{
public:
EmptyArcsOutCursorImpl(void) {};
virtual ~EmptyArcsOutCursorImpl(void) {};
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef(void) {
return 2;
}
NS_IMETHOD_(nsrefcnt) Release(void) {
return 1;
}
NS_IMETHOD QueryInterface(REFNSIID iid, void** result) {
if (! result)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIRDFArcsOutCursorIID) ||
iid.Equals(kIRDFCursorIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFArcsOutCursor*, this);
/* AddRef(); // not necessary */
return NS_OK;
}
return NS_NOINTERFACE;
}
// nsIRDFCursor
NS_IMETHOD Advance(void) {
return NS_ERROR_RDF_CURSOR_EMPTY;
}
// nsIRDFArcsOutCursor
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetSubject(nsIRDFResource** aResource) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
return NS_ERROR_UNEXPECTED;
}
};
nsresult
NS_NewEmptyRDFArcsOutCursor(nsIRDFArcsOutCursor** result)
{
static EmptyArcsOutCursorImpl gEmptyArcsOutCursor;
*result = &gEmptyArcsOutCursor;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
class EmptyArcsInCursorImpl : public nsIRDFArcsInCursor
{
public:
EmptyArcsInCursorImpl(void) {};
virtual ~EmptyArcsInCursorImpl(void) {};
// nsISupports
NS_IMETHOD_(nsrefcnt) AddRef(void) {
return 2;
}
NS_IMETHOD_(nsrefcnt) Release(void) {
return 1;
}
NS_IMETHOD QueryInterface(REFNSIID iid, void** result) {
if (! result)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIRDFArcsInCursorIID) ||
iid.Equals(kIRDFCursorIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFArcsInCursor*, this);
/* AddRef(); // not necessary */
return NS_OK;
}
return NS_NOINTERFACE;
}
// nsIRDFCursor
NS_IMETHOD Advance(void) {
return NS_ERROR_RDF_CURSOR_EMPTY;
}
// nsIRDFArcsInCursor
NS_IMETHOD GetDataSource(nsIRDFDataSource** aDataSource) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetPredicate(nsIRDFResource** aPredicate) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetObject(nsIRDFNode** aNode) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetTruthValue(PRBool* aTruthValue) {
return NS_ERROR_UNEXPECTED;
}
NS_IMETHOD GetValue(nsIRDFNode** aValue) {
return NS_ERROR_UNEXPECTED;
}
};
nsresult
NS_NewEmptyRDFArcsInCursor(nsIRDFArcsInCursor** result)
{
static EmptyArcsInCursorImpl gEmptyArcsInCursor;
*result = &gEmptyArcsInCursor;
return NS_OK;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
/* -*- 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.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.
*/
/*
This header file just contains prototypes for the factory methods
for "builtin" data sources that are included in rdf.dll.
Each of these data sources is exposed to the external world via its
CID in ../include/nsRDFCID.h.
*/
#ifndef nsBaseDataSources_h__
#define nsBaseDataSources_h__
#include "nsError.h"
class nsIRDFDataSource;
// in nsInMemoryDataSource.cpp
nsresult NS_NewRDFInMemoryDataSource(nsIRDFDataSource** result);
#endif // nsBaseDataSources_h__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
/* -*- 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.0 (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.
*/
/*
*/
#ifndef nsRDFContentSink_h__
#define nsRDFContentSink_h__
#include "nsIRDFContentSink.h"
class nsIURL;
class nsVoidArray;
class nsIRDFResource;
class nsIRDFDataSource;
class nsIRDFService;
class nsINameSpaceManager;
typedef enum {
eRDFContentSinkState_InProlog,
eRDFContentSinkState_InDocumentElement,
eRDFContentSinkState_InDescriptionElement,
eRDFContentSinkState_InContainerElement,
eRDFContentSinkState_InPropertyElement,
eRDFContentSinkState_InMemberElement,
eRDFContentSinkState_InEpilog
} RDFContentSinkState;
class RDFContentSinkImpl : public nsIRDFContentSink
{
public:
RDFContentSinkImpl();
virtual ~RDFContentSinkImpl();
// nsISupports
NS_DECL_ISUPPORTS
// nsIContentSink
NS_IMETHOD WillBuildModel(void);
NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel);
NS_IMETHOD WillInterrupt(void);
NS_IMETHOD WillResume(void);
NS_IMETHOD SetParser(nsIParser* aParser);
NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
NS_IMETHOD CloseContainer(const nsIParserNode& aNode);
NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
NS_IMETHOD AddComment(const nsIParserNode& aNode);
NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
NS_IMETHOD NotifyError(nsresult aErrorResult);
// nsIXMLContentSink
NS_IMETHOD AddXMLDecl(const nsIParserNode& aNode);
NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode);
NS_IMETHOD AddCharacterData(const nsIParserNode& aNode);
NS_IMETHOD AddUnparsedEntity(const nsIParserNode& aNode);
NS_IMETHOD AddNotation(const nsIParserNode& aNode);
NS_IMETHOD AddEntityReference(const nsIParserNode& aNode);
// nsIRDFContentSink
NS_IMETHOD SetDataSource(nsIRDFDataSource* ds);
NS_IMETHOD GetDataSource(nsIRDFDataSource*& ds);
NS_IMETHOD Init(nsIURL* aURL, nsINameSpaceManager* aNameSpaceManager);
protected:
// Text management
nsresult FlushText(PRBool aCreateTextNode=PR_TRUE,
PRBool* aDidFlush=nsnull);
PRUnichar* mText;
PRInt32 mTextLength;
PRInt32 mTextSize;
PRBool mConstrainSize;
// namespace management
void PushNameSpacesFrom(const nsIParserNode& aNode);
nsIAtom* CutNameSpacePrefix(nsString& aString);
PRInt32 GetNameSpaceID(nsIAtom* aPrefix);
void GetNameSpaceURI(PRInt32 aID, nsString& aURI);
void PopNameSpaces();
nsINameSpaceManager* mNameSpaceManager;
nsVoidArray* mNameSpaceStack;
PRInt32 mRDFNameSpaceID;
void SplitQualifiedName(const nsString& aQualifiedName,
PRInt32& rNameSpaceID,
nsString& rProperty);
// RDF-specific parsing
nsresult GetIdAboutAttribute(const nsIParserNode& aNode, nsString& rResource);
nsresult GetResourceAttribute(const nsIParserNode& aNode, nsString& rResource);
nsresult AddProperties(const nsIParserNode& aNode, nsIRDFResource* aSubject);
virtual nsresult OpenRDF(const nsIParserNode& aNode);
virtual nsresult OpenObject(const nsIParserNode& aNode);
virtual nsresult OpenProperty(const nsIParserNode& aNode);
virtual nsresult OpenMember(const nsIParserNode& aNode);
virtual nsresult OpenValue(const nsIParserNode& aNode);
// Miscellaneous RDF junk
nsIRDFService* mRDFService;
nsIRDFDataSource* mDataSource;
RDFContentSinkState mState;
// content stack management
PRInt32 PushContext(nsIRDFResource *aContext, RDFContentSinkState aState);
nsresult PopContext(nsIRDFResource*& rContext, RDFContentSinkState& rState);
nsIRDFResource* GetContextElement(PRInt32 ancestor = 0);
nsVoidArray* mContextStack;
nsIURL* mDocumentURL;
PRUint32 mGenSym; // for generating anonymous resources
};
#endif // nsRDFContentSink_h__

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.0 (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.
*/
/*
Some useful parsing routines.
This isn't the best place for them: I wish that they'd go into some
shared area (like mozilla/base).
*/
#include <stdlib.h> // XXX for atoi(), maybe this should go into nsCRT?
#include "nsCRT.h"
#include "nsIURL.h"
#include "nsString.h"
#include "nsRDFParserUtils.h"
// XXX This totally sucks. I wish that mozilla/base had this code.
PRUnichar
nsRDFParserUtils::EntityToUnicode(const char* buf)
{
if ((buf[0] == 'g' || buf[0] == 'G') &&
(buf[1] == 't' || buf[1] == 'T'))
return PRUnichar('>');
if ((buf[0] == 'l' || buf[0] == 'L') &&
(buf[1] == 't' || buf[1] == 'T'))
return PRUnichar('<');
if ((buf[0] == 'a' || buf[0] == 'A') &&
(buf[1] == 'm' || buf[1] == 'M') &&
(buf[2] == 'p' || buf[2] == 'P'))
return PRUnichar('&');
NS_NOTYETIMPLEMENTED("this is a named entity that I can't handle...");
return PRUnichar('?');
}
// XXX Code copied from nsHTMLContentSink. It should be shared.
void
nsRDFParserUtils::StripAndConvert(nsString& aResult)
{
// Strip quotes if present
PRUnichar first = aResult.First();
if ((first == '"') || (first == '\'')) {
if (aResult.Last() == first) {
aResult.Cut(0, 1);
PRInt32 pos = aResult.Length() - 1;
if (pos >= 0) {
aResult.Cut(pos, 1);
}
} else {
// Mismatched quotes - leave them in
}
}
// Reduce any entities
// XXX Note: as coded today, this will only convert well formed
// entities. This may not be compatible enough.
// XXX there is a table in navigator that translates some numeric entities
// should we be doing that? If so then it needs to live in two places (bad)
// so we should add a translate numeric entity method from the parser...
char cbuf[100];
PRInt32 index = 0;
while (index < aResult.Length()) {
// If we have the start of an entity (and it's not at the end of
// our string) then translate the entity into it's unicode value.
if ((aResult.CharAt(index++) == '&') && (index < aResult.Length())) {
PRInt32 start = index - 1;
PRUnichar e = aResult.CharAt(index);
if (e == '#') {
// Convert a numeric character reference
index++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar e = aResult.CharAt(index);
if (e == ';') {
index++;
ok = PR_TRUE;
break;
}
if ((e >= '0') && (e <= '9')) {
*cp++ = char(e);
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
if (cp - cbuf > 5) {
continue;
}
PRInt32 ch = PRInt32( ::atoi(cbuf) );
if (ch > 65535) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
else if (((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
// Convert a named entity
index++;
char* cp = cbuf;
char* limit = cp + sizeof(cbuf) - 1;
*cp++ = char(e);
PRBool ok = PR_FALSE;
PRInt32 slen = aResult.Length();
while ((index < slen) && (cp < limit)) {
PRUnichar e = aResult.CharAt(index);
if (e == ';') {
index++;
ok = PR_TRUE;
break;
}
if (((e >= '0') && (e <= '9')) ||
((e >= 'A') && (e <= 'Z')) ||
((e >= 'a') && (e <= 'z'))) {
*cp++ = char(e);
index++;
continue;
}
break;
}
if (!ok || (cp == cbuf)) {
continue;
}
*cp = '\0';
PRInt32 ch;
// XXX Um, here's where we should be converting a
// named entity. I removed this to avoid a link-time
// dependency on core raptor.
ch = EntityToUnicode(cbuf);
if (ch < 0) {
continue;
}
// Remove entity from string and replace it with the integer
// value.
aResult.Cut(start, index - start);
aResult.Insert(PRUnichar(ch), start);
index = start + 1;
}
else if (e == '{') {
// Convert a script entity
// XXX write me!
NS_NOTYETIMPLEMENTED("convert a script entity");
}
}
}
}
nsresult
nsRDFParserUtils::GetQuotedAttributeValue(const nsString& aSource,
const nsString& aAttribute,
nsString& aValue)
{
static const char kQuote = '\"';
static const char kApostrophe = '\'';
PRInt32 offset;
PRInt32 endOffset = -1;
nsresult result = NS_OK;
offset = aSource.Find(aAttribute);
if (-1 != offset) {
offset = aSource.Find('=', offset);
PRUnichar next = aSource.CharAt(++offset);
if (kQuote == next) {
endOffset = aSource.Find(kQuote, ++offset);
}
else if (kApostrophe == next) {
endOffset = aSource.Find(kApostrophe, ++offset);
}
if (-1 != endOffset) {
aSource.Mid(aValue, offset, endOffset-offset);
}
else {
// Mismatched quotes - return an error
result = NS_ERROR_FAILURE;
}
}
else {
aValue.Truncate();
}
return result;
}
void
nsRDFParserUtils::FullyQualifyURI(const nsIURL* base, nsString& spec)
{
// This is a fairly heavy-handed way to do this, but...I don't
// like typing.
nsIURL* url;
if (NS_SUCCEEDED(NS_NewURL(&url, spec, base))) {
PRUnichar* str;
url->ToString(&str);
spec = str;
delete str;
url->Release();
}
}
PRBool
nsRDFParserUtils::IsJavaScriptLanguage(const nsString& aName)
{
if (aName.EqualsIgnoreCase("JavaScript") ||
aName.EqualsIgnoreCase("LiveScript") ||
aName.EqualsIgnoreCase("Mocha")) {
return PR_TRUE;
}
else if (aName.EqualsIgnoreCase("JavaScript1.1")) {
return PR_TRUE;
}
else if (aName.EqualsIgnoreCase("JavaScript1.2")) {
return PR_TRUE;
}
else if (aName.EqualsIgnoreCase("JavaScript1.3")) {
return PR_TRUE;
}
else if (aName.EqualsIgnoreCase("JavaScript1.4")) {
return PR_TRUE;
}
else {
return PR_FALSE;
}
}

View File

@@ -0,0 +1,58 @@
/* -*- 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.0 (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.
*/
/*
Some useful parsing routines.
*/
#ifndef nsRDFParserUtils_h__
#define nsRDFParserUtils_h__
#include "nscore.h"
class nsIURL;
class nsString;
class nsRDFParserUtils {
public:
static PRUnichar
EntityToUnicode(const char* buf);
static void
StripAndConvert(nsString& aResult);
static nsresult
GetQuotedAttributeValue(const nsString& aSource,
const nsString& aAttribute,
nsString& aValue);
static void
FullyQualifyURI(const nsIURL* base, nsString& spec);
static PRBool
IsJavaScriptLanguage(const nsString& aName);
};
#endif // nsRDFPasrserUtils_h__

View File

@@ -0,0 +1,117 @@
/* -*- 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 "nsRDFResource.h"
#include "nsCRT.h"
////////////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
////////////////////////////////////////////////////////////////////////////////
nsRDFResource::nsRDFResource(const char* uri)
: mURI(uri)
{
}
nsRDFResource::~nsRDFResource(void)
{
}
NS_IMPL_ADDREF(nsRDFResource)
NS_IMPL_RELEASE(nsRDFResource)
NS_IMETHODIMP
nsRDFResource::QueryInterface(REFNSIID iid, void** result)
{
if (! result)
return NS_ERROR_NULL_POINTER;
*result = nsnull;
if (iid.Equals(kIRDFResourceIID) ||
iid.Equals(kIRDFNodeIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFResource*, this);
}
if (*result != nsnull) {
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRDFNode methods:
NS_METHOD
nsRDFResource::EqualsNode(nsIRDFNode* node, PRBool* result) const
{
nsresult rv;
nsIRDFResource* resource;
if (NS_SUCCEEDED(node->QueryInterface(kIRDFResourceIID, (void**) &resource))) {
rv = EqualsResource(resource, result);
NS_RELEASE(resource);
}
else {
*result = PR_FALSE;
rv = NS_OK;
}
return rv;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRDFResource methods:
NS_METHOD
nsRDFResource::GetValue(const char* *uri) const
{
if (!uri)
return NS_ERROR_NULL_POINTER;
*uri = mURI;
return NS_OK;
}
NS_METHOD
nsRDFResource::EqualsResource(const nsIRDFResource* resource, PRBool* result) const
{
if (!resource || !result)
return NS_ERROR_NULL_POINTER;
const char *uri;
if (NS_SUCCEEDED(resource->GetValue(&uri))) {
return EqualsString(uri, result) ? NS_OK : NS_ERROR_FAILURE;
}
return NS_ERROR_FAILURE;
}
NS_METHOD
nsRDFResource::EqualsString(const char* uri, PRBool* result) const
{
if (!uri || !result)
return NS_ERROR_NULL_POINTER;
*result = nsCRT::strcmp(uri, mURI) == 0;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,759 @@
/* -*- 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.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.
*/
/*
This file provides the implementation for the RDF service manager.
TO DO
-----
1) Figure out a better way to do "pluggable resources." Currently,
we have two _major_ hacks:
RegisterBuiltInNamedDataSources()
RegisterBuiltInResourceFactories()
These introduce dependencies on the datasource directory. You'd
like to have this stuff discovered dynamically at startup or
something. Maybe from the registry.
2) Implement the CreateDataBase() methods.
*/
#include "nsIAtom.h"
#include "nsIRDFDataSource.h"
#include "nsIRDFNode.h"
#include "nsIRDFService.h"
#include "nsIRDFResourceFactory.h"
#include "nsString.h"
#include "plhash.h"
#include "plstr.h"
#include "prlog.h"
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID);
static NS_DEFINE_IID(kIRDFLiteralIID, NS_IRDFLITERAL_IID);
static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID);
static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
////////////////////////////////////////////////////////////////////////
// PrefixMap
//
// A simple map from a string prefix to a value. It maintains an
// ordered list of prefixes that map to a <tt>void*</tt>. The list
// is sorted in ASCII order such that if one prefix <b>p</b> is
// itself a prefix of another prefix <b>q</b>, the longest prefix
// (<b>q</b>) will appear first in the list. The idea is that you
// want to find the "best" match first. (Will this actually be
// useful? Probabably not...)
//
class PrefixMap
{
private:
struct PrefixMapEntry
{
const char* mPrefix;
PRInt32 mPrefixLen;
const void* mValue;
PrefixMapEntry* mNext;
};
PrefixMapEntry* mHead;
public:
PrefixMap();
~PrefixMap();
PRBool Add(const char* aPrefix, const void* aValue);
const void* Remove(const char* aPrefix);
/**
* Find the most specific value matching the specified string.
*/
const void* Find(const char* aString);
};
PrefixMap::PrefixMap()
: mHead(nsnull)
{
}
PrefixMap::~PrefixMap()
{
while (mHead) {
PrefixMapEntry* doomed = mHead;
mHead = mHead->mNext;
PL_strfree(NS_CONST_CAST(char*, doomed->mPrefix));
delete doomed;
}
}
PRBool
PrefixMap::Add(const char* aPrefix, const void* aValue)
{
PRInt32 newPrefixLen = PL_strlen(aPrefix);
PrefixMapEntry* entry = mHead;
PrefixMapEntry* last = nsnull;
while (entry != nsnull) {
// check to see if the new prefix is longer than the current
// entry. If so, we'll want to insert the new prefix *before*
// this one.
if (newPrefixLen > entry->mPrefixLen)
break;
// check for exact equality: if so, the prefix is already
// registered, so fail (?)
if (PL_strcmp(entry->mPrefix, aPrefix) == 0)
return PR_FALSE;
// otherwise, the new prefix is the same length or shorter
// than the current entry: continue on to the next one.
last = entry;
entry = entry->mNext;
}
PrefixMapEntry* newEntry = new PrefixMapEntry;
if (! newEntry)
return PR_FALSE;
newEntry->mPrefix = PL_strdup(aPrefix);
newEntry->mPrefixLen = newPrefixLen;
newEntry->mValue = aValue;
if (last) {
// we found an entry that we need to insert the current
// entry *before*
newEntry->mNext = last->mNext;
last->mNext = newEntry;
}
else {
// Otherwise, insert at the start
newEntry->mNext = mHead;
mHead = newEntry;
}
return PR_TRUE;
}
const void*
PrefixMap::Remove(const char* aPrefix)
{
PrefixMapEntry* entry = mHead;
PrefixMapEntry* last = nsnull;
PRInt32 doomedPrefixLen = PL_strlen(aPrefix);
while (entry != nsnull) {
if ((doomedPrefixLen == entry->mPrefixLen) &&
(PL_strcmp(entry->mPrefix, aPrefix) == 0)) {
if (last) {
last->mNext = entry->mNext;
}
else {
mHead = entry->mNext;
}
const void* value = entry->mValue;
PL_strfree(NS_CONST_CAST(char*, entry->mPrefix));
delete entry;
return value;
}
last = entry;
entry = entry->mNext;
}
return nsnull;
}
const void*
PrefixMap::Find(const char* aString)
{
for (PrefixMapEntry* entry = mHead; entry != nsnull; entry = entry->mNext) {
PRInt32 cmp = PL_strncmp(entry->mPrefix, aString, entry->mPrefixLen);
if (cmp == 0)
return entry->mValue;
}
return nsnull;
}
////////////////////////////////////////////////////////////////////////
// LiteralImpl
//
// Currently, all literals are implemented exactly the same way;
// i.e., there is are no resource factories to allow you to generate
// customer resources. I doubt that makes sense, anyway.
//
// What _may_ make sense is to atomize literals (well, at least
// short ones), to reduce in memory overhead at the expense of some
// processing time.
//
class LiteralImpl : public nsIRDFLiteral {
public:
LiteralImpl(const PRUnichar* s);
virtual ~LiteralImpl(void);
// nsISupports
NS_DECL_ISUPPORTS
// nsIRDFNode
NS_IMETHOD EqualsNode(nsIRDFNode* node, PRBool* result) const;
// nsIRDFLiteral
NS_IMETHOD GetValue(const PRUnichar* *value) const;
NS_IMETHOD EqualsLiteral(const nsIRDFLiteral* literal, PRBool* result) const;
private:
nsAutoString mValue;
};
LiteralImpl::LiteralImpl(const PRUnichar* s)
: mValue(s)
{
NS_INIT_REFCNT();
}
LiteralImpl::~LiteralImpl(void)
{
}
NS_IMPL_ADDREF(LiteralImpl);
NS_IMPL_RELEASE(LiteralImpl);
nsresult
LiteralImpl::QueryInterface(REFNSIID iid, void** result)
{
if (! result)
return NS_ERROR_NULL_POINTER;
*result = nsnull;
if (iid.Equals(kIRDFLiteralIID) ||
iid.Equals(kIRDFNodeIID) ||
iid.Equals(kISupportsIID)) {
*result = NS_STATIC_CAST(nsIRDFLiteral*, this);
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP
LiteralImpl::EqualsNode(nsIRDFNode* node, PRBool* result) const
{
nsresult rv;
nsIRDFLiteral* literal;
if (NS_SUCCEEDED(node->QueryInterface(kIRDFLiteralIID, (void**) &literal))) {
rv = EqualsLiteral(literal, result);
NS_RELEASE(literal);
}
else {
*result = PR_FALSE;
rv = NS_OK;
}
return rv;
}
NS_IMETHODIMP
LiteralImpl::GetValue(const PRUnichar* *value) const
{
NS_ASSERTION(value, "null ptr");
if (! value)
return NS_ERROR_NULL_POINTER;
*value = mValue.GetUnicode();
return NS_OK;
}
NS_IMETHODIMP
LiteralImpl::EqualsLiteral(const nsIRDFLiteral* literal, PRBool* result) const
{
NS_ASSERTION(literal && result, "null ptr");
if (!literal || !result)
return NS_ERROR_NULL_POINTER;
nsresult rv;
const PRUnichar* p;
if (NS_FAILED(rv = literal->GetValue(&p)))
return rv;
nsAutoString s(p);
*result = s.Equals(mValue);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// ServiceImpl
//
// This is the RDF service.
//
class ServiceImpl : public nsIRDFService
{
protected:
PrefixMap mResourceFactories;
PLHashTable* mNamedDataSources;
PLHashTable* mDataSourceConstructors;
PLHashTable* mResources;
ServiceImpl(void);
virtual ~ServiceImpl(void);
static nsIRDFService* gRDFService; // The one-and-only RDF service
static void RegisterBuiltInResourceFactories();
static void RegisterBuiltInNamedDataSources();
public:
static nsresult GetRDFService(nsIRDFService** result);
// nsISupports
NS_DECL_ISUPPORTS
// nsIRDFService
NS_IMETHOD GetResource(const char* uri, nsIRDFResource** resource);
NS_IMETHOD GetUnicodeResource(const PRUnichar* uri, nsIRDFResource** resource);
NS_IMETHOD GetLiteral(const PRUnichar* value, nsIRDFLiteral** literal);
NS_IMETHOD UnCacheResource(nsIRDFResource* resource);
NS_IMETHOD RegisterResourceFactory(const char* aURIPrefix, nsIRDFResourceFactory* aFactory);
NS_IMETHOD UnRegisterResourceFactory(const char* aURIPrefix);
NS_IMETHOD RegisterDataSource(nsIRDFDataSource* dataSource);
NS_IMETHOD UnregisterDataSource(nsIRDFDataSource* dataSource);
NS_IMETHOD RegisterDataSourceConstructor(const char* uri, NSDataSourceConstructorCallback fn);
NS_IMETHOD UnregisterDataSourceConstructor(const char* uri);
NS_IMETHOD GetDataSource(const char* uri, nsIRDFDataSource** dataSource);
NS_IMETHOD CreateDatabase(const char** uris, nsIRDFDataBase** dataBase);
NS_IMETHOD CreateBrowserDatabase(nsIRDFDataBase** dataBase);
};
nsIRDFService* ServiceImpl::gRDFService = nsnull;
////////////////////////////////////////////////////////////////////////
ServiceImpl::ServiceImpl(void)
: mResources(nsnull), mNamedDataSources(nsnull)
{
NS_INIT_REFCNT();
mResources = PL_NewHashTable(1023, // nbuckets
PL_HashString, // hash fn
PL_CompareStrings, // key compare fn
PL_CompareValues, // value compare fn
nsnull, nsnull); // alloc ops & priv
mNamedDataSources = PL_NewHashTable(23,
PL_HashString,
PL_CompareStrings,
PL_CompareValues,
nsnull, nsnull);
mDataSourceConstructors = PL_NewHashTable(23,
PL_HashString,
PL_CompareStrings,
PL_CompareValues,
nsnull, nsnull);
}
ServiceImpl::~ServiceImpl(void)
{
if (mDataSourceConstructors) {
PL_HashTableDestroy(mDataSourceConstructors);
mDataSourceConstructors = nsnull;
}
if (mNamedDataSources) {
PL_HashTableDestroy(mNamedDataSources);
mNamedDataSources = nsnull;
}
if (mResources) {
PL_HashTableDestroy(mResources);
mResources = nsnull;
}
gRDFService = nsnull;
}
nsresult
ServiceImpl::GetRDFService(nsIRDFService** mgr)
{
if (! gRDFService) {
gRDFService = new ServiceImpl();
if (! gRDFService)
return NS_ERROR_OUT_OF_MEMORY;
RegisterBuiltInResourceFactories();
RegisterBuiltInNamedDataSources();
}
NS_ADDREF(gRDFService);
*mgr = gRDFService;
return NS_OK;
}
NS_IMETHODIMP_(nsrefcnt)
ServiceImpl::AddRef(void)
{
return 2;
}
NS_IMETHODIMP_(nsrefcnt)
ServiceImpl::Release(void)
{
return 1;
}
NS_IMPL_QUERY_INTERFACE(ServiceImpl, kIRDFServiceIID);
NS_IMETHODIMP
ServiceImpl::GetResource(const char* uri, nsIRDFResource** resource)
{
nsIRDFResource* result =
NS_STATIC_CAST(nsIRDFResource*, PL_HashTableLookup(mResources, uri));
if (! result) {
nsIRDFResourceFactory* factory =
NS_STATIC_CAST(nsIRDFResourceFactory*,
NS_CONST_CAST(void*, mResourceFactories.Find(uri)));
PR_ASSERT(factory != nsnull);
if (! factory)
return NS_ERROR_FAILURE; // XXX
nsresult rv;
if (NS_FAILED(rv = factory->CreateResource(uri, &result)))
return rv;
const char* uri;
result->GetValue(&uri);
// This is a little trick to make storage more efficient. For
// the "key" in the table, we'll use the string value that's
// stored as a member variable of the nsIRDFResource object.
PL_HashTableAdd(mResources, uri, result);
// *We* don't AddRef() the resource: that way, the resource
// can be garbage collected when the last refcount goes
// away. The single addref that the CreateResource() call made
// will be owned by the callee.
}
else {
// Addref for the callee.
NS_ADDREF(result);
}
*resource = result;
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::GetUnicodeResource(const PRUnichar* uri, nsIRDFResource** resource)
{
nsString s(uri);
char* cstr = s.ToNewCString();
nsresult rv = GetResource(cstr, resource);
delete[] cstr;
return rv;
}
NS_IMETHODIMP
ServiceImpl::GetLiteral(const PRUnichar* uri, nsIRDFLiteral** literal)
{
LiteralImpl* result = new LiteralImpl(uri);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
*literal = result;
NS_ADDREF(result);
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::UnCacheResource(nsIRDFResource* resource)
{
nsresult rv;
const char* uri;
if (NS_FAILED(rv = resource->GetValue(&uri)))
return rv;
PL_HashTableRemove(mResources, uri);
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::RegisterResourceFactory(const char* aURIPrefix, nsIRDFResourceFactory* aFactory)
{
if (! mResourceFactories.Add(aURIPrefix, aFactory))
return NS_ERROR_ILLEGAL_VALUE;
NS_ADDREF(aFactory); // XXX should we addref?
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::UnRegisterResourceFactory(const char* aURIPrefix)
{
nsIRDFResourceFactory* factory =
NS_STATIC_CAST(nsIRDFResourceFactory*,
NS_CONST_CAST(void*, mResourceFactories.Remove(aURIPrefix)));
if (! factory)
return NS_ERROR_ILLEGAL_VALUE;
NS_RELEASE(factory); // XXX should we addref?
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::RegisterDataSource(nsIRDFDataSource* aDataSource)
{
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
if (! aDataSource)
return NS_ERROR_NULL_POINTER;
nsresult rv;
const char* uri;
if (NS_FAILED(rv = aDataSource->GetURI(&uri)))
return rv;
// XXX check for dups, etc.
PL_HashTableAdd(mNamedDataSources, uri, aDataSource);
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::UnregisterDataSource(nsIRDFDataSource* aDataSource)
{
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
if (! aDataSource)
return NS_ERROR_NULL_POINTER;
nsresult rv;
const char* uri;
if (NS_FAILED(rv = aDataSource->GetURI(&uri)))
return rv;
nsIRDFDataSource* ds =
NS_STATIC_CAST(nsIRDFDataSource*, PL_HashTableLookup(mNamedDataSources, uri));
if (! ds)
return NS_ERROR_ILLEGAL_VALUE;
PL_HashTableRemove(mNamedDataSources, uri);
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::RegisterDataSourceConstructor(const char* uri, NSDataSourceConstructorCallback fn)
{
// XXX check for dups, etc.
PL_HashTableAdd(mDataSourceConstructors, uri, fn);
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::UnregisterDataSourceConstructor(const char* uri)
{
PL_HashTableRemove(mDataSourceConstructors, uri);
return NS_OK;
}
NS_IMETHODIMP
ServiceImpl::GetDataSource(const char* uri, nsIRDFDataSource** aDataSource)
{
nsIRDFDataSource* ds =
NS_STATIC_CAST(nsIRDFDataSource*, PL_HashTableLookup(mNamedDataSources, uri));
if (ds) {
NS_ADDREF(ds);
*aDataSource = ds;
return NS_OK;
}
// Otherwise, see if we have a lazy constructor
NSDataSourceConstructorCallback constructor =
(NSDataSourceConstructorCallback)
PL_HashTableLookup(mDataSourceConstructors, uri);
if (constructor) {
// Yep, so try to construct it on the fly...
nsresult rv;
if (NS_FAILED(rv = constructor(&ds))) {
#ifdef DEBUG
printf("error constructing built-in datasource %s\n", uri);
#endif
return rv;
}
// If it wants to register itself, it should do so in the Init() method.
if (NS_FAILED(rv = ds->Init(uri))) {
#ifdef DEBUG
printf("error initializing named datasource %s\n", uri);
#endif
NS_RELEASE(ds);
return rv;
}
// constructor did an implicit addref
*aDataSource = ds;
return NS_OK;
}
// XXX at this point, we might want to try to construct a
// stream URI and load it that way...
return NS_ERROR_ILLEGAL_VALUE;
}
NS_IMETHODIMP
ServiceImpl::CreateDatabase(const char** uri, nsIRDFDataBase** dataBase)
{
PR_ASSERT(0);
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
ServiceImpl::CreateBrowserDatabase(nsIRDFDataBase** dataBase)
{
PR_ASSERT(0);
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////
//
// This is Big Hack #1. Depedencies on all builtin resource
// factories are *here*, in the ResourceFactoryTable.
//
struct ResourceFactoryTable {
const char* mPrefix;
nsresult (*mFactoryConstructor)(nsIRDFResourceFactory** result);
};
void
ServiceImpl::RegisterBuiltInResourceFactories(void)
{
extern nsresult NS_NewRDFDefaultResourceFactory(nsIRDFResourceFactory** result);
extern nsresult NS_NewRDFMailResourceFactory(nsIRDFResourceFactory** result);
extern nsresult NS_NewRDFMailAccountResourceFactory(nsIRDFResourceFactory** result);
extern nsresult NS_NewRDFFileResourceFactory(nsIRDFResourceFactory** result);
static ResourceFactoryTable gTable[] = {
"", NS_NewRDFDefaultResourceFactory,
"mailaccount:", NS_NewRDFMailAccountResourceFactory,
"mailbox:", NS_NewRDFMailResourceFactory,
#if 0
"file:", NS_NewRDFFileResourceFactory,
#endif
nsnull, nsnull
};
nsresult rv;
for (ResourceFactoryTable* entry = gTable; entry->mPrefix != nsnull; ++entry) {
nsIRDFResourceFactory* factory;
if (NS_FAILED(rv = (entry->mFactoryConstructor)(&factory)))
continue;
rv = gRDFService->RegisterResourceFactory(entry->mPrefix, factory);
PR_ASSERT(NS_SUCCEEDED(rv));
NS_RELEASE(factory);
}
}
////////////////////////////////////////////////////////////////////////
//
// This is Big Hack #2. Dependencies on all builtin datasources are
// *here*, in the DataSourceTable.
//
// FWIW, I don't particularly like this interface *anyway*, because
// it requires each built-in data source to be constructed "up
// front". Not only does it cause the service manager to be
// re-entered (which may be a problem), but it's wasteful: I think
// these data sources should be created on demand, and released when
// you're done with them.
//
struct DataSourceTable {
const char* mURI;
nsresult (*mDataSourceConstructor)(nsIRDFDataSource** result);
};
void
ServiceImpl::RegisterBuiltInNamedDataSources(void)
{
extern nsresult NS_NewRDFBookmarkDataSource(nsIRDFDataSource** result);
extern nsresult NS_NewRDFHistoryDataSource(nsIRDFDataSource** result);
extern nsresult NS_NewRDFLocalFileSystemDataSource(nsIRDFDataSource** result);
extern nsresult NS_NewRDFMailDataSource(nsIRDFDataSource** result);
static DataSourceTable gTable[] = {
"rdf:bookmarks", NS_NewRDFBookmarkDataSource,
"rdf:mail", NS_NewRDFMailDataSource,
#if 0
"rdf:history", NS_NewRDFHistoryDataSource,
"rdf:lfs", NS_NewRDFLocalFileSystemDataSource,
#endif
nsnull, nsnull
};
nsresult rv;
for (DataSourceTable* entry = gTable; entry->mURI != nsnull; ++entry) {
if (NS_FAILED(rv = gRDFService->RegisterDataSourceConstructor(entry->mURI, entry->mDataSourceConstructor))) {
#ifdef DEBUG
printf("error registering built-in datasource constructor for %s\n", entry->mURI);
#endif
continue;
}
}
}
////////////////////////////////////////////////////////////////////////
nsresult
NS_NewRDFService(nsIRDFService** mgr)
{
return ServiceImpl::GetRDFService(mgr);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,233 @@
/* -*- 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.0 (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.
*/
/*
A bunch of useful RDF utility routines. Many of these will
eventually be exported outside of RDF.DLL via the nsIRDFService
interface.
*/
#ifndef rdfutil_h__
#define rdfutil_h__
#include "prtypes.h"
class nsIRDFCursor;
class nsIRDFDataBase;
class nsIRDFDataSource;
class nsIRDFNode;
class nsString;
/**
* Returns PR_TRUE if the URI is an RDF ordinal property; e.g., rdf:_1,
* rdf:_2, etc.
*/
PR_EXTERN(PRBool)
rdf_IsOrdinalProperty(const nsIRDFResource* property);
/**
* Converts an ordinal property to an index
*/
PR_EXTERN(nsresult)
rdf_OrdinalResourceToIndex(nsIRDFResource* aOrdinal, PRInt32* aIndex);
/**
* Converts an index to an ordinal property
*/
PR_EXTERN(nsresult)
rdf_IndexToOrdinalResource(PRInt32 aIndex, nsIRDFResource** aOrdinal);
/**
* Returns PR_TRUE if the resource is a container resource; e.g., an
* rdf:Bag.
*/
PR_EXTERN(PRBool)
rdf_IsContainer(nsIRDFDataSource* db,
nsIRDFResource* resource);
PR_EXTERN(PRBool)
rdf_IsBag(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource);
PR_EXTERN(PRBool)
rdf_IsSeq(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource);
PR_EXTERN(PRBool)
rdf_IsAlt(nsIRDFDataSource* aDataSource,
nsIRDFResource* aResource);
/**
* Various utilities routines for making assertions in a data source
*/
// 0. node, node, node
PR_EXTERN(nsresult)
rdf_Assert(nsIRDFDataSource* ds,
nsIRDFResource* subject,
nsIRDFResource* predicate,
nsIRDFNode* object);
// 1. string, string, string
PR_EXTERN(nsresult)
rdf_Assert(nsIRDFDataSource* ds,
const nsString& subjectURI,
const nsString& predicateURI,
const nsString& objectURI);
// 2. node, node, string
PR_EXTERN(nsresult)
rdf_Assert(nsIRDFDataSource* ds,
nsIRDFResource* subject,
nsIRDFResource* predicate,
const nsString& objectURI);
// 3. node, string, string
PR_EXTERN(nsresult)
rdf_Assert(nsIRDFDataSource* ds,
nsIRDFResource* subject,
const nsString& predicateURI,
const nsString& objectURI);
// 4. node, string, node
PR_EXTERN(nsresult)
rdf_Assert(nsIRDFDataSource* ds,
nsIRDFResource* subject,
const nsString& predicateURI,
nsIRDFNode* object);
// 5. string, string, node
PR_EXTERN(nsresult)
rdf_Assert(nsIRDFDataSource* ds,
const nsString& subjectURI,
const nsString& predicateURI,
nsIRDFNode* object);
/**
* Construct a new, "anonymous" node; that is, a node with an internal
* resource URI.
*/
PR_EXTERN(nsresult)
rdf_CreateAnonymousResource(const nsString& aContextURI, nsIRDFResource** result);
/**
* Determine if a resource is an "anonymous" resource that we've constructed
* ourselves.
*/
PR_EXTERN(PRBool)
rdf_IsAnonymousResource(const nsString& aContextURI, nsIRDFResource* aResource);
/**
* Try to convert the absolute URL into a relative URL.
*/
PR_EXTERN(nsresult)
rdf_PossiblyMakeRelative(const nsString& aContextURI, nsString& aURI);
/**
* Create a bag resource.
*/
PR_EXTERN(nsresult)
rdf_MakeBag(nsIRDFDataSource* ds,
nsIRDFResource* resource);
/**
* Create a sequence resource.
*/
PR_EXTERN(nsresult)
rdf_MakeSeq(nsIRDFDataSource* ds,
nsIRDFResource* resource);
/**
* Create an alternation resource.
*/
PR_EXTERN(nsresult)
rdf_MakeAlt(nsIRDFDataSource* ds,
nsIRDFResource* resource);
/**
* Add an element to the end of container.
*/
PR_EXTERN(nsresult)
rdf_ContainerAppendElement(nsIRDFDataSource* ds,
nsIRDFResource* container,
nsIRDFNode* element);
/**
* Remove an element from a container
*/
PR_EXTERN(nsresult)
rdf_ContainerRemoveElement(nsIRDFDataSource* aDataSource,
nsIRDFResource* aContainer,
nsIRDFNode* aElement);
/**
* Insert an element into a container at the specified index.
*/
PR_EXTERN(nsresult)
rdf_ContainerInsertElementAt(nsIRDFDataSource* aDataSource,
nsIRDFResource* aContainer,
nsIRDFNode* aElement,
PRInt32 aIndex);
/**
* Determine the index of an element in a container.
*/
PR_EXTERN(nsresult)
rdf_ContainerIndexOf(nsIRDFDataSource* aDataSource,
nsIRDFResource* aContainer,
nsIRDFNode* aElement,
PRInt32* aIndex);
/**
* Create a cursor on a container that enumerates its contents in
* order
*/
PR_EXTERN(nsresult)
NS_NewContainerCursor(nsIRDFDataSource* ds,
nsIRDFResource* container,
nsIRDFAssertionCursor** cursor);
/**
* Create an empty nsIRDFCursor. This will *never* fail, and will *always*
* return the same object.
*/
PR_EXTERN(nsresult)
NS_NewEmptyRDFAssertionCursor(nsIRDFAssertionCursor** result);
PR_EXTERN(nsresult)
NS_NewEmptyRDFArcsInCursor(nsIRDFArcsInCursor** result);
PR_EXTERN(nsresult)
NS_NewEmptyRDFArcsOutCursor(nsIRDFArcsOutCursor** result);
// XXX need to move nsEmptyCursor stuff here.
#endif // rdfutil_h__

View File

@@ -0,0 +1 @@
nsRDFCID.h

View File

@@ -0,0 +1,69 @@
#!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=../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
include $(topsrcdir)/config/config.mk
LIBRARY_NAME = rdf
CPPSRCS = \
nsRDFFactory.cpp \
$(NULL)
EXPORTS = \
nsRDFCID.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
MODULE = rdf
REQUIRES = dom js netlib rdf raptor xpcom
# XXX Note dependencies on implementation headers for factory functions
INCLUDES += -I$(srcdir)/../base/src \
-I$(srcdir)/../content/src \
-I$(srcdir)/../datasource/src \
$(NULL)
EXTRA_DSO_LDOPTS = \
-L$(DIST)/bin \
-L$(DIST)/lib \
-lrdfbase_s \
-lrdfcontent_s \
-lrdfdatasource_s \
$(NULL)
include $(topsrcdir)/config/rules.mk
install:: $(TARGETS)
$(INSTALL) $(srcdir)/../resources/Mail/joe@meer.net/inbox $(DIST)/bin/res/rdf/Mail/joe@meer.net
$(INSTALL) $(srcdir)/../resources/sidebar.xul $(DIST)/bin/res/rdf
$(INSTALL) $(srcdir)/../resources/sidebar.css $(DIST)/bin/res/rdf
$(INSTALL) $(srcdir)/../resources/bookmarks.html $(DIST)/bin/res/rdf
$(INSTALL) $(srcdir)/../resources/Mail/joe@meer.net/work $(DIST)/bin/res/rdf/Mail/joe@meer.net
$(INSTALL) $(srcdir)/../resources/Mail/joe@meer.net/other $(DIST)/bin/res/rdf/Mail/joe@meer.net
$(INSTALL) $(srcdir)/../resources/Mail/jane@aol.com/inbox $(DIST)/bin/res/rdf/Mail/jane@aol.com
$(INSTALL) $(srcdir)/../resources/Mail/jane@aol.com/hiking $(DIST)/bin/res/rdf/Mail/jane@aol.com
$(INSTALL) $(srcdir)/../resources/Mail/jane@aol.com/trash $(DIST)/bin/res/rdf/Mail/jane@aol.com

View File

@@ -0,0 +1,83 @@
#!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=..\..
MODULE=rdf
MAKE_OBJ_TYPE=DLL
DLLNAME=rdf
DLL=.\$(OBJDIR)\$(DLLNAME).dll
EXPORTS=\
nsRDFCID.h \
$(NULL)
CPP_OBJS=\
.\$(OBJDIR)\nsRDFFactory.obj \
$(NULL)
# XXX linking in raptor is a heinous crime that will go away once we
# have a more DOM-based mechanism for constructing elements and
# hooking in to their changes.
LLIBS=\
$(DIST)\lib\rdfbase_s.lib \
$(DIST)\lib\rdfcontent_s.lib \
$(DIST)\lib\rdfdatasource_s.lib \
$(DIST)\lib\xpcom32.lib \
$(DIST)\lib\raptorbase.lib \
$(DIST)\lib\raptorgfxwin.lib \
$(DIST)\lib\netlib.lib \
$(DIST)\lib\libplc21.lib \
$(DIST)\lib\raptorhtml.lib \
$(DIST)\lib\jsdom.lib \
$(DIST)\lib\js3250.lib \
$(LIBNSPR)
MISCDEP=$(LLIBS)
# XXX Note dependencies on implementation dirs for factory methods.
LINCS= -I$(PUBLIC)\rdf \
-I$(PUBLIC)\xpcom \
-I$(PUBLIC)\netlib \
-I$(PUBLIC)\raptor \
-I$(PUBLIC)\js \
-I$(PUBLIC)\dom \
-I$(DEPTH)\rdf\base\src \
-I$(DEPTH)\rdf\content\src \
-I$(DEPTH)\rdf\datasource\src \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib
$(MAKE_INSTALL) ..\resources\Mail\joe@meer.net\inbox $(DIST)\bin\res\rdf\Mail\joe@meer.net
$(MAKE_INSTALL) ..\resources\sidebar.xul $(DIST)\bin\res\rdf
$(MAKE_INSTALL) ..\resources\sidebar.css $(DIST)\bin\res\rdf
$(MAKE_INSTALL) ..\resources\bookmarks.html $(DIST)\bin\res\rdf
$(MAKE_INSTALL) ..\resources\Mail\joe@meer.net\work $(DIST)\bin\res\rdf\Mail\joe@meer.net
$(MAKE_INSTALL) ..\resources\Mail\joe@meer.net\other $(DIST)\bin\res\rdf\Mail\joe@meer.net
$(MAKE_INSTALL) ..\resources\Mail\jane@aol.com\inbox $(DIST)\bin\res\rdf\Mail\jane@aol.com
$(MAKE_INSTALL) ..\resources\Mail\jane@aol.com\hiking $(DIST)\bin\res\rdf\Mail\jane@aol.com
$(MAKE_INSTALL) ..\resources\Mail\jane@aol.com\trash $(DIST)\bin\res\rdf\Mail\jane@aol.com

View File

@@ -0,0 +1,81 @@
/* -*- 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.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.
*/
/*
XPCOM Class IDs for RDF objects that can be constructed via the RDF
factory.
*/
#ifndef nsRDFCID_h__
#define nsRDFCID_h__
// {0F78DA56-8321-11d2-8EAC-00805F29F370}
#define NS_RDFNODE_CID \
{ 0xf78da56, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
// {BFD05264-834C-11d2-8EAC-00805F29F370}
#define NS_RDFSERVICE_CID \
{ 0xbfd05264, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
// {BFD0526D-834C-11d2-8EAC-00805F29F370}
#define NS_RDFINMEMORYDATASOURCE_CID \
{ 0xbfd0526d, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
// {E638D760-8687-11d2-B530-000000000000}
#define NS_RDFBOOKMARKDATASOURCE_CID \
{ 0xe638d760, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
// {E638D761-8687-11d2-B530-000000000000}
#define NS_RDFCOMPOSITEDATASOURCE_CID \
{ 0xe638d761, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
// {954F0813-81DC-11d2-B52A-000000000000}
#define NS_RDFHTMLBUILDER_CID \
{ 0x954f0813, 0x81dc, 0x11d2, { 0xb5, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
// {3D262D00-8B5A-11d2-8EB0-00805F29F370}
#define NS_RDFTREEBUILDER_CID \
{ 0x3d262d00, 0x8b5a, 0x11d2, { 0x8e, 0xb0, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
// {7BAF62E0-8E61-11d2-8EB1-00805F29F370}
#define NS_RDFXMLDATASOURCE_CID \
{ 0x7baf62e0, 0x8e61, 0x11d2, { 0x8e, 0xb1, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
// {6791B601-B9FE-11d2-BF86-00105A1B0627}
#define NS_XULDATASOURCE_CID \
{ 0x6791b601, 0xb9fe, 0x11d2, { 0xbf, 0x86, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }
// {0958B101-9ADA-11d2-8EBC-00805F29F370}
#define NS_RDFCONTENTSINK_CID \
{ 0x958b101, 0x9ada, 0x11d2, { 0x8e, 0xbc, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
// {E45313F0-B59C-11d2-A68C-00104BDE6048}
#define NS_RDFXULBUILDER_CID \
{ 0xe45313f0, 0xb59c, 0x11d2, { 0xa6, 0x8c, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } }
// {CE058B21-BA9C-11d2-BF86-00105A1B0627}
#define NS_XULCONTENTSINK_CID \
{ 0xce058b21, 0xba9c, 0x11d2, { 0xbf, 0x86, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }
// {541AFCB2-A9A3-11d2-8EC5-00805F29F370}
#define NS_XULDOCUMENT_CID \
{ 0x541afcb2, 0xa9a3, 0x11d2, { 0x8e, 0xc5, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } }
#endif // nsRDFCID_h__

View File

@@ -0,0 +1,263 @@
/* -*- 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.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.
*/
/*
The RDF factory implementation.
*/
#include "nsIFactory.h"
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFContentModelBuilder.h"
#include "nsIRDFContentSink.h"
#include "nsIRDFDocument.h"
#include "nsIRDFService.h"
#include "nsIRDFXMLDataSource.h"
#include "nsIXULContentSink.h"
#include "nsISupports.h"
#include "nsRDFBaseDataSources.h"
#include "nsRDFBuiltInDataSources.h"
#include "nsRDFCID.h"
#include "nsRepository.h"
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
static NS_DEFINE_CID(kRDFBookmarkDataSourceCID, NS_RDFBOOKMARKDATASOURCE_CID);
static NS_DEFINE_CID(kRDFCompositeDataSourceCID, NS_RDFCOMPOSITEDATASOURCE_CID);
static NS_DEFINE_CID(kRDFContentSinkCID, NS_RDFCONTENTSINK_CID);
static NS_DEFINE_CID(kRDFHTMLBuilderCID, NS_RDFHTMLBUILDER_CID);
static NS_DEFINE_CID(kRDFInMemoryDataSourceCID, NS_RDFINMEMORYDATASOURCE_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kRDFTreeBuilderCID, NS_RDFTREEBUILDER_CID);
static NS_DEFINE_CID(kRDFXMLDataSourceCID, NS_RDFXMLDATASOURCE_CID);
static NS_DEFINE_CID(kRDFXULBuilderCID, NS_RDFXULBUILDER_CID);
static NS_DEFINE_CID(kXULContentSinkCID, NS_XULCONTENTSINK_CID);
static NS_DEFINE_CID(kXULDataSourceCID, NS_XULDATASOURCE_CID);
static NS_DEFINE_CID(kXULDocumentCID, NS_XULDOCUMENT_CID);
class RDFFactoryImpl : public nsIFactory
{
public:
RDFFactoryImpl(const nsCID &aClass);
// nsISupports methods
NS_DECL_ISUPPORTS
// nsIFactory methods
NS_IMETHOD CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult);
NS_IMETHOD LockFactory(PRBool aLock);
protected:
virtual ~RDFFactoryImpl();
private:
nsCID mClassID;
};
////////////////////////////////////////////////////////////////////////
RDFFactoryImpl::RDFFactoryImpl(const nsCID &aClass)
{
NS_INIT_REFCNT();
mClassID = aClass;
}
RDFFactoryImpl::~RDFFactoryImpl()
{
NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction");
}
NS_IMETHODIMP
RDFFactoryImpl::QueryInterface(const nsIID &aIID,
void **aResult)
{
if (! aResult)
return NS_ERROR_NULL_POINTER;
// Always NULL result, in case of failure
*aResult = nsnull;
if (aIID.Equals(kISupportsIID)) {
*aResult = NS_STATIC_CAST(nsISupports*, this);
AddRef();
return NS_OK;
} else if (aIID.Equals(kIFactoryIID)) {
*aResult = NS_STATIC_CAST(nsIFactory*, this);
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMPL_ADDREF(RDFFactoryImpl);
NS_IMPL_RELEASE(RDFFactoryImpl);
NS_IMETHODIMP
RDFFactoryImpl::CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (! aResult)
return NS_ERROR_NULL_POINTER;
if (aOuter)
return NS_ERROR_NO_AGGREGATION;
*aResult = nsnull;
nsresult rv;
PRBool wasRefCounted = PR_TRUE;
nsISupports *inst = nsnull;
if (mClassID.Equals(kRDFServiceCID)) {
if (NS_FAILED(rv = NS_NewRDFService((nsIRDFService**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFInMemoryDataSourceCID)) {
if (NS_FAILED(rv = NS_NewRDFInMemoryDataSource((nsIRDFDataSource**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFXMLDataSourceCID)) {
if (NS_FAILED(rv = NS_NewRDFXMLDataSource((nsIRDFXMLDataSource**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFBookmarkDataSourceCID)) {
if (NS_FAILED(rv = NS_NewRDFBookmarkDataSource((nsIRDFDataSource**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFCompositeDataSourceCID)) {
if (NS_FAILED(rv = NS_NewRDFCompositeDataSource((nsIRDFCompositeDataSource**) &inst)))
return rv;
}
else if (mClassID.Equals(kXULDocumentCID)) {
if (NS_FAILED(rv = NS_NewXULDocument((nsIRDFDocument**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFHTMLBuilderCID)) {
if (NS_FAILED(rv = NS_NewRDFHTMLBuilder((nsIRDFContentModelBuilder**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFTreeBuilderCID)) {
if (NS_FAILED(rv = NS_NewRDFTreeBuilder((nsIRDFContentModelBuilder**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFXULBuilderCID)) {
if (NS_FAILED(rv = NS_NewRDFXULBuilder((nsIRDFContentModelBuilder**) &inst)))
return rv;
}
else if (mClassID.Equals(kRDFContentSinkCID)) {
if (NS_FAILED(rv = NS_NewRDFContentSink((nsIRDFContentSink**) &inst)))
return rv;
}
else if (mClassID.Equals(kXULDataSourceCID)) {
if (NS_FAILED(rv = NS_NewXULDataSource((nsIRDFXMLDataSource**) &inst)))
return rv;
}
else if (mClassID.Equals(kXULContentSinkCID)) {
if (NS_FAILED(rv = NS_NewXULContentSink((nsIXULContentSink**) &inst)))
return rv;
}
else {
return NS_ERROR_NO_INTERFACE;
}
if (! inst)
return NS_ERROR_OUT_OF_MEMORY;
if (NS_FAILED(rv = inst->QueryInterface(aIID, aResult)))
// We didn't get the right interface, so clean up
delete inst;
if (wasRefCounted)
NS_IF_RELEASE(inst);
return rv;
}
nsresult RDFFactoryImpl::LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
// return the proper factory to the caller
extern "C" PR_IMPLEMENT(nsresult)
NSGetFactory(const nsCID &aClass, nsISupports* aServiceManager, nsIFactory **aFactory)
{
if (! aFactory)
return NS_ERROR_NULL_POINTER;
RDFFactoryImpl* factory = new RDFFactoryImpl(aClass);
if (factory == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(factory);
*aFactory = factory;
return NS_OK;
}
extern "C" PR_IMPLEMENT(nsresult)
NSRegisterSelf(const char* aPath)
{
nsRepository::RegisterFactory(kRDFBookmarkDataSourceCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFCompositeDataSourceCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFContentSinkCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFHTMLBuilderCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFInMemoryDataSourceCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFServiceCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFTreeBuilderCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFXMLDataSourceCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kRDFXULBuilderCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kXULContentSinkCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kXULDataSourceCID, aPath, PR_TRUE, PR_TRUE);
nsRepository::RegisterFactory(kXULDocumentCID, aPath, PR_TRUE, PR_TRUE);
return NS_OK;
}
extern "C" PR_IMPLEMENT(nsresult)
NSUnregisterSelf(const char* aPath)
{
nsRepository::UnregisterFactory(kRDFBookmarkDataSourceCID, aPath);
nsRepository::UnregisterFactory(kRDFCompositeDataSourceCID, aPath);
nsRepository::UnregisterFactory(kRDFContentSinkCID, aPath);
nsRepository::UnregisterFactory(kRDFHTMLBuilderCID, aPath);
nsRepository::UnregisterFactory(kRDFInMemoryDataSourceCID, aPath);
nsRepository::UnregisterFactory(kRDFServiceCID, aPath);
nsRepository::UnregisterFactory(kRDFTreeBuilderCID, aPath);
nsRepository::UnregisterFactory(kRDFXMLDataSourceCID, aPath);
nsRepository::UnregisterFactory(kRDFXULBuilderCID, aPath);
nsRepository::UnregisterFactory(kXULContentSinkCID, aPath);
nsRepository::UnregisterFactory(kXULDataSourceCID, aPath);
nsRepository::UnregisterFactory(kXULDocumentCID, aPath);
return NS_OK;
}

View File

@@ -0,0 +1,29 @@
#!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 = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,27 @@
#!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=..\..
MODULE = rdf
DIRS=\
public \
src \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,5 @@
nsIDOMNodeObserver.h
nsIDOMXULNode.h
nsIRDFContent.h
nsIRDFContentModelBuilder.h
nsIRDFDocument.h

View File

@@ -0,0 +1,39 @@
#!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=../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = rdf
EXPORTS = \
nsIDOMNodeObserver.h \
nsIDOMXULNode.h \
nsIRDFContent.h \
nsIRDFContentModelBuilder.h \
nsIRDFDocument.h \
$(NULL)
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,10 @@
interface NodeObserver {
/* IID: { 0x3e969070, 0xc301, 0x11d2, \
{ 0xa6, 0xae, 0x0, 0x10, 0x4b, 0xde, 0x60, 0x48 } } */
void onSetNodeValue(in Node node, in DOMString value);
void onInsertBefore(in Node parent, in Node newChild, in Node refChild);
void onReplaceChild(in Node parent, in Node newChild, in Node oldChild);
void onRemoveChild(in Node parent, in Node oldChild);
void onAppendChild(in Node parent, in Node newChild);
};

View File

@@ -0,0 +1,9 @@
interface XULNode {
/* IID: { 0x574ed81, 0xc088, 0x11d2, \
{ 0x96, 0xed, 0x0, 0x10, 0x4b, 0x7b, 0x7d, 0xeb } } */
void addBroadcastListener(in DOMString attr, in Node node);
void removeBroadcastListener(in DOMString attr, in Node node);
void doCommand();
};

Some files were not shown because too many files have changed in this diff Show More