Fix bug # 15222: The composite datasource has a few operations which are somewhat "expensive". Have these behaviors on by default, but expose a method on the composite datasources so that they can be selectively turned off [for Mail/News, for example] if the capability is not needed/used (such as negative assertions). Review: waterson@netscape.com. Additional Mail/News Testing: putterman@netscape.com

git-svn-id: svn://10.0.0.236/trunk@49541 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rjc%netscape.com 1999-10-01 04:07:55 +00:00
parent 6ac3886652
commit aa8041f54e
5 changed files with 245 additions and 71 deletions

View File

@ -2061,6 +2061,9 @@ XULDocumentImpl::EndLoad()
NS_ASSERTION(NS_SUCCEEDED(rv), "couldn't create composite datasource");
if (NS_FAILED(rv)) return rv;
db->SetAllowNegativeAssertions(PR_FALSE);
db->SetCoalesceDuplicateArcs(PR_FALSE);
// Create a XUL content model builder
rv = nsComponentManager::CreateInstance(kRDFXULBuilderCID,
nsnull,

View File

@ -22,6 +22,10 @@
// the illusion of a single, coherent RDF graph.
[scriptable, uuid(96343820-307C-11D2-BC15-00805F912FE7)]
interface nsIRDFCompositeDataSource : nsIRDFDataSource {
attribute boolean allowNegativeAssertions; // true by default
attribute boolean coalesceDuplicateArcs; // true by default
// Add a datasource the the database.
void AddDataSource(in nsIRDFDataSource aDataSource);

View File

@ -90,9 +90,12 @@ public:
nsIRDFNode* target,
PRBool tv);
protected:
nsCOMPtr<nsISupportsArray> mObservers;
virtual ~CompositeDataSourceImpl(void);
nsCOMPtr<nsISupportsArray> mObservers;
PRBool mAllowNegativeAssertions;
PRBool mCoalesceDuplicateArcs;
virtual ~CompositeDataSourceImpl(void);
};
@ -105,7 +108,9 @@ protected:
class CompositeEnumeratorImpl : public nsISimpleEnumerator
{
public:
CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource);
CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs);
virtual ~CompositeEnumeratorImpl();
// nsISupports interface
@ -126,11 +131,18 @@ protected:
nsISimpleEnumerator* mCurrent;
nsIRDFNode* mResult;
PRInt32 mNext;
nsVoidArray mAlreadyReturned;
PRBool mAllowNegativeAssertions;
PRBool mCoalesceDuplicateArcs;
};
CompositeEnumeratorImpl::CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource)
: mCompositeDataSource(aCompositeDataSource),
CompositeEnumeratorImpl::CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs)
: mCompositeDataSource(aCompositeDataSource),
mAllowNegativeAssertions(aAllowNegativeAssertions),
mCoalesceDuplicateArcs(aCoalesceDuplicateArcs),
mCurrent(nsnull),
mResult(nsnull),
mNext(0)
@ -142,10 +154,18 @@ CompositeEnumeratorImpl::CompositeEnumeratorImpl(CompositeDataSourceImpl* aCompo
CompositeEnumeratorImpl::~CompositeEnumeratorImpl(void)
{
if (mCoalesceDuplicateArcs == PR_TRUE)
{
for (PRInt32 i = mAlreadyReturned.Count() - 1; i >= 0; --i)
{
nsIRDFNode *node = (nsIRDFNode *) mAlreadyReturned[i];
NS_RELEASE(node);
}
}
NS_IF_RELEASE(mCurrent);
NS_IF_RELEASE(mResult);
NS_RELEASE(mCompositeDataSource);
NS_IF_RELEASE(mCurrent);
NS_IF_RELEASE(mResult);
NS_RELEASE(mCompositeDataSource);
}
@ -221,33 +241,66 @@ CompositeEnumeratorImpl::HasMoreElements(PRBool* aResult)
rv = result->QueryInterface(nsIRDFNode::GetIID(), (void**) &mResult);
if (NS_FAILED(rv)) return rv;
// See if any previous data source negates this
PRBool hasNegation = PR_FALSE;
for (i = mNext - 1; i >= 0; --i) {
nsIRDFDataSource* datasource =
(nsIRDFDataSource*) mCompositeDataSource->mDataSources[i];
if (mAllowNegativeAssertions == PR_TRUE)
{
// See if any previous data source negates this
PRBool hasNegation = PR_FALSE;
for (i = mNext - 1; i >= 0; --i)
{
nsIRDFDataSource* datasource =
(nsIRDFDataSource*) mCompositeDataSource->mDataSources[i];
rv = HasNegation(datasource, mResult, &hasNegation);
if (NS_FAILED(rv)) return rv;
if (hasNegation)
break;
}
// if so, we've gotta keep looking
if (hasNegation) {
NS_RELEASE(mResult);
continue;
}
rv = HasNegation(datasource, mResult, &hasNegation);
if (NS_FAILED(rv)) return rv;
if (hasNegation)
break;
}
// if so, we've gotta keep looking
if (hasNegation)
{
NS_RELEASE(mResult);
continue;
}
}
if (mCoalesceDuplicateArcs == PR_TRUE)
{
// Now see if we've returned it once already.
// XXX N.B. performance here...may want to hash if things get large?
PRBool alreadyReturned = PR_FALSE;
for (i = mAlreadyReturned.Count() - 1; i >= 0; --i)
{
if (mAlreadyReturned[i] == mResult)
{
alreadyReturned = PR_TRUE;
break;
}
}
if (alreadyReturned == PR_TRUE)
{
NS_RELEASE(mResult);
continue;
}
}
// If we get here, then we've really found one. It'll
// remain cached in mResult until GetNext() sucks it out.
*aResult = PR_TRUE;
// Remember that we returned it, so we don't return duplicates.
// XXX I wonder if we should make unique-checking be
// optional. This could get to be pretty expensive (this
// implementation turns iteration into O(n^2)).
if (mCoalesceDuplicateArcs == PR_TRUE)
{
mAlreadyReturned.AppendElement(mResult);
NS_ADDREF(mResult);
}
return NS_OK;
} while (1);
@ -292,7 +345,9 @@ public:
CompositeArcsInOutEnumeratorImpl(CompositeDataSourceImpl* aCompositeDataSource,
nsIRDFNode* aNode,
Type aType);
Type aType,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs);
virtual ~CompositeArcsInOutEnumeratorImpl();
@ -305,15 +360,21 @@ public:
private:
nsIRDFNode* mNode;
Type mType;
PRBool mAllowNegativeAssertions;
PRBool mCoalesceDuplicateArcs;
};
CompositeArcsInOutEnumeratorImpl::CompositeArcsInOutEnumeratorImpl(
CompositeDataSourceImpl* aCompositeDataSource,
nsIRDFNode* aNode,
Type aType)
: CompositeEnumeratorImpl(aCompositeDataSource),
Type aType,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs)
: CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs),
mNode(aNode),
mType(aType)
mType(aType),
mAllowNegativeAssertions(aAllowNegativeAssertions),
mCoalesceDuplicateArcs(aCoalesceDuplicateArcs)
{
NS_ADDREF(mNode);
}
@ -361,7 +422,9 @@ public:
nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue);
PRBool aTruthValue,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs);
virtual ~CompositeAssertionEnumeratorImpl();
@ -376,6 +439,8 @@ private:
nsIRDFResource* mProperty;
nsIRDFNode* mTarget;
PRBool mTruthValue;
PRBool mAllowNegativeAssertions;
PRBool mCoalesceDuplicateArcs;
};
@ -384,12 +449,16 @@ CompositeAssertionEnumeratorImpl::CompositeAssertionEnumeratorImpl(
nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget,
PRBool aTruthValue)
: CompositeEnumeratorImpl(aCompositeDataSource),
PRBool aTruthValue,
PRBool aAllowNegativeAssertions,
PRBool aCoalesceDuplicateArcs)
: CompositeEnumeratorImpl(aCompositeDataSource, aAllowNegativeAssertions, aCoalesceDuplicateArcs),
mSource(aSource),
mProperty(aProperty),
mTarget(aTarget),
mTruthValue(aTruthValue)
mTruthValue(aTruthValue),
mAllowNegativeAssertions(aAllowNegativeAssertions),
mCoalesceDuplicateArcs(aCoalesceDuplicateArcs)
{
NS_IF_ADDREF(mSource);
NS_ADDREF(mProperty); // always must be specified
@ -449,6 +518,8 @@ NS_NewRDFCompositeDataSource(nsIRDFCompositeDataSource** result)
CompositeDataSourceImpl::CompositeDataSourceImpl(void)
: mAllowNegativeAssertions(PR_TRUE),
mCoalesceDuplicateArcs(PR_TRUE)
{
NS_INIT_REFCNT();
@ -540,6 +611,9 @@ CompositeDataSourceImpl::GetSource(nsIRDFResource* property,
PRBool tv,
nsIRDFResource** source)
{
if ((mAllowNegativeAssertions == PR_FALSE) && (tv == PR_FALSE))
return(NS_RDF_NO_VALUE);
PRInt32 count = mDataSources.Count();
for (PRInt32 i = 0; i < count; ++i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
@ -551,6 +625,8 @@ CompositeDataSourceImpl::GetSource(nsIRDFResource* property,
if (rv == NS_RDF_NO_VALUE)
continue;
if (mAllowNegativeAssertions == PR_FALSE) return(NS_OK);
// 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))
@ -580,7 +656,11 @@ CompositeDataSourceImpl::GetSources(nsIRDFResource* aProperty,
if (! aResult)
return NS_ERROR_NULL_POINTER;
*aResult = new CompositeAssertionEnumeratorImpl(this, nsnull, aProperty, aTarget, aTruthValue);
if ((mAllowNegativeAssertions == PR_FALSE) && (aTruthValue == PR_FALSE))
return(NS_RDF_NO_VALUE);
*aResult = new CompositeAssertionEnumeratorImpl(this, nsnull, aProperty,
aTarget, aTruthValue, mAllowNegativeAssertions, mCoalesceDuplicateArcs);
if (! *aResult)
return NS_ERROR_OUT_OF_MEMORY;
@ -606,6 +686,9 @@ CompositeDataSourceImpl::GetTarget(nsIRDFResource* aSource,
if (! aResult)
return NS_ERROR_NULL_POINTER;
if ((mAllowNegativeAssertions == PR_FALSE) && (aTruthValue == PR_FALSE))
return(NS_RDF_NO_VALUE);
PRInt32 count = mDataSources.Count();
for (PRInt32 i = 0; i < count; ++i) {
nsIRDFDataSource* ds = NS_STATIC_CAST(nsIRDFDataSource*, mDataSources[i]);
@ -619,14 +702,14 @@ CompositeDataSourceImpl::GetTarget(nsIRDFResource* aSource,
// okay, found it. make sure we don't have the opposite
// asserted in an earlier data source
if (HasAssertionN(count-1, aSource, aProperty, *aResult, !aTruthValue)) {
// whoops, it's been negated.
NS_RELEASE(*aResult);
return NS_RDF_NO_VALUE;
}
else {
return NS_OK;
if (mAllowNegativeAssertions == PR_TRUE) {
if (HasAssertionN(count-1, aSource, aProperty, *aResult, !aTruthValue)) {
// whoops, it's been negated.
NS_RELEASE(*aResult);
return NS_RDF_NO_VALUE;
}
}
return NS_OK;
}
}
@ -677,7 +760,11 @@ CompositeDataSourceImpl::GetTargets(nsIRDFResource* aSource,
if (! aResult)
return NS_ERROR_NULL_POINTER;
*aResult = new CompositeAssertionEnumeratorImpl(this, aSource, aProperty, nsnull, aTruthValue);
if ((mAllowNegativeAssertions == PR_FALSE) && (aTruthValue == PR_FALSE))
return(NS_RDF_NO_VALUE);
*aResult = new CompositeAssertionEnumeratorImpl(this, aSource, aProperty,
nsnull, aTruthValue, mAllowNegativeAssertions, mCoalesceDuplicateArcs);
if (! *aResult)
return NS_ERROR_OUT_OF_MEMORY;
@ -703,6 +790,9 @@ CompositeDataSourceImpl::Assert(nsIRDFResource* aSource,
if (! aTarget)
return NS_ERROR_NULL_POINTER;
if ((mAllowNegativeAssertions == PR_FALSE) && (aTruthValue == PR_FALSE))
return(NS_RDF_ASSERTION_REJECTED);
nsresult rv;
// XXX Need to add back the stuff for unblocking ...
@ -900,6 +990,12 @@ CompositeDataSourceImpl::HasAssertion(nsIRDFResource* aSource,
if (! aResult)
return NS_ERROR_NULL_POINTER;
if ((mAllowNegativeAssertions == PR_FALSE) && (aTruthValue == PR_FALSE))
{
*aResult = PR_FALSE;
return(NS_OK);
}
nsresult rv;
// Otherwise, look through all the data sources to see if anyone
@ -913,14 +1009,18 @@ CompositeDataSourceImpl::HasAssertion(nsIRDFResource* aSource,
if (*aResult)
return NS_OK;
PRBool hasNegation;
rv = datasource->HasAssertion(aSource, aProperty, aTarget, !aTruthValue, &hasNegation);
if (NS_FAILED(rv)) return rv;
if (mAllowNegativeAssertions == PR_TRUE)
{
PRBool hasNegation;
rv = datasource->HasAssertion(aSource, aProperty, aTarget, !aTruthValue, &hasNegation);
if (NS_FAILED(rv)) return rv;
if (hasNegation) {
*aResult = PR_FALSE;
return NS_OK;
}
if (hasNegation)
{
*aResult = PR_FALSE;
return NS_OK;
}
}
}
// If we get here, nobody had the assertion at all
@ -973,7 +1073,9 @@ CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode* aTarget, nsISimpleEnumerator**
return NS_ERROR_NULL_POINTER;
nsISimpleEnumerator* result =
new CompositeArcsInOutEnumeratorImpl(this, aTarget, CompositeArcsInOutEnumeratorImpl::eArcsIn);
new CompositeArcsInOutEnumeratorImpl(this, aTarget,
CompositeArcsInOutEnumeratorImpl::eArcsIn,
mAllowNegativeAssertions, mCoalesceDuplicateArcs);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
@ -996,7 +1098,9 @@ CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource* aSource,
return NS_ERROR_NULL_POINTER;
nsISimpleEnumerator* result =
new CompositeArcsInOutEnumeratorImpl(this, aSource, CompositeArcsInOutEnumeratorImpl::eArcsOut);
new CompositeArcsInOutEnumeratorImpl(this, aSource,
CompositeArcsInOutEnumeratorImpl::eArcsOut,
mAllowNegativeAssertions, mCoalesceDuplicateArcs);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
@ -1181,6 +1285,34 @@ CompositeDataSourceImpl::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSource
// 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::GetAllowNegativeAssertions(PRBool *aAllowNegativeAssertions)
{
*aAllowNegativeAssertions = mAllowNegativeAssertions;
return(NS_OK);
}
NS_IMETHODIMP
CompositeDataSourceImpl::SetAllowNegativeAssertions(PRBool aAllowNegativeAssertions)
{
mAllowNegativeAssertions = aAllowNegativeAssertions;
return(NS_OK);
}
NS_IMETHODIMP
CompositeDataSourceImpl::GetCoalesceDuplicateArcs(PRBool *aCoalesceDuplicateArcs)
{
*aCoalesceDuplicateArcs = mCoalesceDuplicateArcs;
return(NS_OK);
}
NS_IMETHODIMP
CompositeDataSourceImpl::SetCoalesceDuplicateArcs(PRBool aCoalesceDuplicateArcs)
{
mCoalesceDuplicateArcs = aCoalesceDuplicateArcs;
return(NS_OK);
}
NS_IMETHODIMP
CompositeDataSourceImpl::AddDataSource(nsIRDFDataSource* aDataSource)
{
@ -1224,13 +1356,17 @@ CompositeDataSourceImpl::OnAssert(nsIRDFResource* aSource,
// datasource actually served up the OnAssert(): we could use
// HasAssertionN() to only search datasources _before_ the
// datasource that coughed up the assertion.
nsresult rv;
PRBool hasAssertion;
rv = HasAssertion(aSource, aProperty, aTarget, PR_TRUE, &hasAssertion);
if (NS_FAILED(rv)) return rv;
nsresult rv = NS_OK;
if (! hasAssertion)
return NS_OK;
if (mAllowNegativeAssertions == PR_TRUE)
{
PRBool hasAssertion;
rv = HasAssertion(aSource, aProperty, aTarget, PR_TRUE, &hasAssertion);
if (NS_FAILED(rv)) return rv;
if (! hasAssertion)
return(NS_OK);
}
if (mObservers) {
PRUint32 count;
@ -1260,12 +1396,16 @@ CompositeDataSourceImpl::OnUnassert(nsIRDFResource* aSource,
// HasAssertionN() to only search datasources _before_ the
// datasource that coughed up the assertion.
nsresult rv;
PRBool hasAssertion;
rv = HasAssertion(aSource, aProperty, aTarget, PR_TRUE, &hasAssertion);
if (NS_FAILED(rv)) return rv;
if (hasAssertion)
return NS_OK;
if (mAllowNegativeAssertions == PR_TRUE)
{
PRBool hasAssertion;
rv = HasAssertion(aSource, aProperty, aTarget, PR_TRUE, &hasAssertion);
if (NS_FAILED(rv)) return rv;
if (hasAssertion)
return NS_OK;
}
if (mObservers) {
PRUint32 count;
@ -1337,9 +1477,3 @@ CompositeDataSourceImpl::OnMove(nsIRDFResource* aOldSource,
}
return NS_OK;
}

View File

@ -152,6 +152,9 @@ private:
static nsIAtom* kRefAtom;
static nsIAtom* kTemplateAtom;
static nsIAtom* kXMLNSAtom;
static nsIAtom* kAllowNegativeAssertionsAtom;
static nsIAtom* kCoalesceDuplicateArcsAtom;
static nsIRDFResource* kRDF_instanceOf;
static nsIRDFResource* kRDF_nextVal;
@ -248,6 +251,9 @@ nsIAtom* RDFXULBuilderImpl::kRefAtom;
nsIAtom* RDFXULBuilderImpl::kTemplateAtom;
nsIAtom* RDFXULBuilderImpl::kXMLNSAtom;
nsIAtom* RDFXULBuilderImpl::kAllowNegativeAssertionsAtom;
nsIAtom* RDFXULBuilderImpl::kCoalesceDuplicateArcsAtom;
nsIRDFResource* RDFXULBuilderImpl::kRDF_instanceOf;
nsIRDFResource* RDFXULBuilderImpl::kRDF_nextVal;
nsIRDFResource* RDFXULBuilderImpl::kRDF_child;
@ -313,7 +319,10 @@ RDFXULBuilderImpl::Init()
kRefAtom = NS_NewAtom("ref");
kTemplateAtom = NS_NewAtom("template");
kXMLNSAtom = NS_NewAtom("xmlns");
kAllowNegativeAssertionsAtom = NS_NewAtom("allownegativeassertions");
kCoalesceDuplicateArcsAtom = NS_NewAtom("coalesceduplicatearcs");
rv = nsServiceManager::GetService(kRDFServiceCID,
kIRDFServiceIID,
(nsISupports**) &gRDFService);
@ -388,6 +397,9 @@ RDFXULBuilderImpl::~RDFXULBuilderImpl(void)
NS_IF_RELEASE(kRefAtom);
NS_IF_RELEASE(kTemplateAtom);
NS_IF_RELEASE(kXMLNSAtom);
NS_IF_RELEASE(kAllowNegativeAssertionsAtom);
NS_IF_RELEASE(kCoalesceDuplicateArcsAtom);
}
}
@ -1319,6 +1331,24 @@ RDFXULBuilderImpl::CreateTemplateBuilder(nsIContent* aElement,
return rv;
}
nsAutoString allowNegativeAssertionsStr;
rv = aElement->GetAttribute(kNameSpaceID_None,
kAllowNegativeAssertionsAtom,
allowNegativeAssertionsStr);
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (allowNegativeAssertionsStr.Equals("false")))
{
db->SetAllowNegativeAssertions(PR_FALSE);
}
nsAutoString coalesceDuplicateArcsStr;
rv = aElement->GetAttribute(kNameSpaceID_None,
kCoalesceDuplicateArcsAtom,
coalesceDuplicateArcsStr);
if ((rv == NS_CONTENT_ATTR_HAS_VALUE) && (coalesceDuplicateArcsStr.Equals("false")))
{
db->SetCoalesceDuplicateArcs(PR_FALSE);
}
// Add the local store as the first data source in the db. Note
// that we _might_ not be able to get a local store if we haven't
// got a profile to read from yet.

View File

@ -2061,6 +2061,9 @@ XULDocumentImpl::EndLoad()
NS_ASSERTION(NS_SUCCEEDED(rv), "couldn't create composite datasource");
if (NS_FAILED(rv)) return rv;
db->SetAllowNegativeAssertions(PR_FALSE);
db->SetCoalesceDuplicateArcs(PR_FALSE);
// Create a XUL content model builder
rv = nsComponentManager::CreateInstance(kRDFXULBuilderCID,
nsnull,