[jboss-jira] [JBoss JIRA] Commented: (JBRULES-2465) Corruption of Rete when removing complex NotNodes
Edson Tirelli (JIRA)
jira-events at lists.jboss.org
Thu Apr 15 17:18:25 EDT 2010
[ https://jira.jboss.org/jira/browse/JBRULES-2465?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12525996#action_12525996 ]
Edson Tirelli commented on JBRULES-2465:
----------------------------------------
Andreas,
I am looking into this, but not able to reproduce it yet. I started with this testcase:
========= DRL ==================
package org.drools;
rule "subnetworks with not"
when
not(
not( Person( name == "bob") ) and
not( Person( name == "mark" ) )
)
then
// do something
end
========= JUNIT ================
public void testDynamicRuleRemovalsSubNetworkAndNot() throws Exception {
final KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add( ResourceFactory.newInputStreamResource( getClass().getResourceAsStream( "test_DynamicRulesWithNotSubnetwork.drl" ) ),
ResourceType.DRL );
assertFalse( kbuilder.getErrors().toString(),
kbuilder.hasErrors() );
final KnowledgeBase kbase = KnowledgeBaseFactory.newKnowledgeBase();
kbase.addKnowledgePackages( kbuilder.getKnowledgePackages() );
final StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
final AgendaEventListener alistener = mock( AgendaEventListener.class );
ksession.addEventListener( alistener );
// pattern does not match, so do not activate
ksession.insert( new Person( "toni" ) );
verify( alistener,
never() ).activationCreated( any( org.drools.event.rule.ActivationCreatedEvent.class ) );
// pattern matches, so create activation
ksession.insert( new Person( "bob" ) );
verify( alistener,
times( 1 ) ).activationCreated( any( org.drools.event.rule.ActivationCreatedEvent.class ) );
// already active, so no new activation should be created
ksession.insert( new Person( "mark" ) );
verify( alistener,
times( 1 ) ).activationCreated( any( org.drools.event.rule.ActivationCreatedEvent.class ) );
kbase.removeKnowledgePackage( "org.drools" );
assertEquals( 0,
kbase.getKnowledgePackages().size() );
}
================================
It is working fine. Can you provide more info on how to replicate? If you can show me some of your rules that cause the problem, I might be able to figure what is happening. If you can disclose your rules, but would prefer to do it privately, you can contact me by e-mail "etirelli AT redhat DOT com" or "ed.tirelli AT gmail DOT com".
> Corruption of Rete when removing complex NotNodes
> -------------------------------------------------
>
> Key: JBRULES-2465
> URL: https://jira.jboss.org/jira/browse/JBRULES-2465
> Project: Drools
> Issue Type: Bug
> Security Level: Public(Everyone can see)
> Components: drools-core
> Affects Versions: 5.0.1.FINAL
> Reporter: Andreas Kohn
> Assignee: Edson Tirelli
> Fix For: 5.1.0.M2
>
> Attachments: drools-core-betanode-remove.diff, drools-core-betanode-remove.diff
>
>
> while working further on our drools integration we came across an odd
> exception when removing a particular rule:
> java.lang.IllegalArgumentException: Cannot remove a sink, when the list of sinks is null
> at org.drools.reteoo.ObjectSource.removeObjectSink(ObjectSource.java:159)
> at org.drools.reteoo.RightInputAdapterNode.doRemove(RightInputAdapterNode.java:217)
> at org.drools.common.BaseNode.remove(BaseNode.java:95)
> at org.drools.reteoo.BetaNode.doRemove(BetaNode.java:275)
> at org.drools.common.BaseNode.remove(BaseNode.java:95)
> at org.drools.reteoo.BetaNode.doRemove(BetaNode.java:280)
> at org.drools.common.BaseNode.remove(BaseNode.java:95)
> at org.drools.reteoo.RuleTerminalNode.doRemove(RuleTerminalNode.java:387)
> at org.drools.common.BaseNode.remove(BaseNode.java:95)
> at org.drools.reteoo.ReteooBuilder.removeRule(ReteooBuilder.java:237)
> at org.drools.reteoo.ReteooRuleBase.removeRule(ReteooRuleBase.java:371)
> at org.drools.common.AbstractRuleBase.removeRule(AbstractRuleBase.java:746)
> While stepping through the code it looked like the network was corrupt (there was indeed no
> sinks on the ObjectSource, but the node calling removeObjectSink was still linked to it
> and claiming it as source).
> The rule itself contains multiple NotNodes, checking a condition that looks like this:
> not(not(Foo.v = X) and not(Foo.v = Y))
> I could track this down to some sort of "loop" in the rete that triggers this when the outer
> not node is removed.
> When removing BetaNode#doRemove() first walks along 'rightInput':
> this.rightInput.remove( context,
> builder,
> this,
> workingMemories );
> and eventually _in that call_ it also hits a node that is the direct 'leftInput' of the original beta node.
> The removal marks that node as visited in the removal context, and when the 'rightInput.remove' returns to the
> beta node it does not visit the leftInput due to this condition in BetaNode#doRemove():
> if ( !context.alreadyVisited( this.leftInput ) ) {
> this.leftInput.remove( context,
> builder,
> this,
> workingMemories );
> }
> In other words: before the remove the BetaNode had another node that was both referenced directly as 'leftInput',
> as well as an input to the 'rightInput'.
> The first removal of the rule "worked", and no exceptions happened. But: any further attempt to re-add the same rule and remove
> it again lead to the exception above.
> I was able to fix it with the attached patch, reproduced here:
> + boolean needRemoveFromLeft = !context.alreadyVisited( this.leftInput );
> this.rightInput.remove( context,
> builder,
> this,
> workingMemories );
> - if ( !context.alreadyVisited( this.leftInput ) ) {
> + if ( needRemoveFromLeft ) {
> this.leftInput.remove( context,
> builder,
> this,
> workingMemories );
> }
> With this patch applied I could add/delete/add the particular rule repeatedly without problems.
> The attached patch also adds an assert in ObjectSource#removeObjectSink(): when removing a sink from an object source with
> only one sink the sink was unconditionally replaced with an empty sink, although the argument ObjectSink could be a different
> sink than the one in the ObjectSource. For CompositeObjectSinkAdapters this case is checked, but not for single sinks.
> I originally suspected that place to be responsible for the problem I observed but the assertion never fired in my tests.
> (taken from rules-dev mail "Bug in BetaNode#doRemove()?"
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the jboss-jira
mailing list