[jboss-svn-commits] JBL Code SVN: r35292 - in labs/jbossrules/trunk/drools-core/src: main/java/org/drools/reteoo and 2 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Sep 24 18:53:25 EDT 2010
Author: mark.proctor at jboss.com
Date: 2010-09-24 18:53:24 -0400 (Fri, 24 Sep 2010)
New Revision: 35292
Added:
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/LazyTMSEnablingTest.java
Modified:
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java
labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeConf.java
labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java
Log:
JBRULES-2709 Initial implementation of lazily enabled TMS.
-Applying patch from Leonardo Gomes
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java 2010-09-24 21:48:00 UTC (rev 35291)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java 2010-09-24 22:53:24 UTC (rev 35292)
@@ -52,9 +52,11 @@
import org.drools.RuleBaseConfiguration.AssertBehaviour;
import org.drools.RuleBaseConfiguration.LogicalOverride;
import org.drools.base.CalendarsImpl;
+import org.drools.base.ClassObjectType;
import org.drools.base.MapGlobalResolver;
import org.drools.concurrent.ExecutorService;
import org.drools.concurrent.ExternalExecutorService;
+import org.drools.core.util.ObjectHashSet;
import org.drools.event.AgendaEventListener;
import org.drools.event.AgendaEventSupport;
import org.drools.event.RuleBaseEventListener;
@@ -68,9 +70,10 @@
import org.drools.reteoo.LIANodePropagation;
import org.drools.reteoo.LeftTuple;
import org.drools.reteoo.ObjectTypeConf;
+import org.drools.reteoo.ObjectTypeNode;
import org.drools.reteoo.PartitionManager;
import org.drools.reteoo.PartitionTaskManager;
-import org.drools.reteoo.ReteooWorkingMemory;
+import org.drools.reteoo.Rete;
import org.drools.rule.Declaration;
import org.drools.rule.EntryPoint;
import org.drools.rule.Rule;
@@ -93,6 +96,7 @@
import org.drools.spi.AsyncExceptionHandler;
import org.drools.spi.FactHandleFactory;
import org.drools.spi.GlobalResolver;
+import org.drools.spi.ObjectType;
import org.drools.spi.PropagationContext;
import org.drools.time.SessionClock;
import org.drools.time.TimerService;
@@ -169,7 +173,6 @@
*/
protected AtomicLong propagationIdCounter;
- private boolean maintainTms;
private boolean sequential;
private List liaPropagations;
@@ -319,9 +322,9 @@
final RuleBaseConfiguration conf = this.ruleBase.getConfiguration();
- this.maintainTms = conf.isMaintainTms();
this.sequential = conf.isSequential();
+
if ( initialFactHandle == null ) {
this.initialFactHandle = handleFactory.newFactHandle( InitialFactImpl.getInstance(),
null,
@@ -345,13 +348,9 @@
timerService = TimerServiceFactory.getTimerService( this.config );
this.nodeMemories = new ConcurrentNodeMemories( this.ruleBase );
+
+ this.tms = new TruthMaintenanceSystem(this);
- if ( this.maintainTms ) {
- this.tms = new TruthMaintenanceSystem( this );
- } else {
- this.tms = null;
- }
-
this.propagationIdCounter = new AtomicLong( propagationContext );
this.objectStore = new SingleThreadedObjectStore( conf,
@@ -953,6 +952,9 @@
ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
object );
+ if ( logical && !typeConf.isTMSEnabled()) {
+ enableTMS(object, typeConf);
+ }
InternalFactHandle handle = null;
@@ -972,8 +974,8 @@
// check if the object already exists in the WM
handle = (InternalFactHandle) this.objectStore.getHandleForObject( object );
- if ( this.maintainTms ) {
-
+ if ( typeConf.isTMSEnabled() ) {
+
EqualityKey key = null;
if ( handle == null ) {
@@ -1006,12 +1008,14 @@
// At this point we know the handle is null
if ( key == null ) {
+
handle = createHandle( object,
typeConf );
- key = new EqualityKey( handle );
- handle.setEqualityKey( key );
+ key = createEqualityKey(handle);
+
this.tms.put( key );
+
if ( !logical ) {
key.setStatus( EqualityKey.STATED );
} else {
@@ -1110,6 +1114,53 @@
}
+ /** Side-effects, will add the created key to the handle. */
+ private EqualityKey createEqualityKey(InternalFactHandle handle) {
+ EqualityKey key = new EqualityKey( handle );
+ handle.setEqualityKey( key );
+ return key;
+ }
+
+ /**
+ * TMS will be automatically enabled when the first logical insert happens.
+ *
+ * We will take all the already asserted objects of the same type and initialize
+ * the equality map.
+ *
+ * @param object the logically inserted object.
+ * @param conf the type's configuration.
+ */
+ private void enableTMS(Object object, ObjectTypeConf conf) {
+
+
+ final Rete source = this.ruleBase.getRete();
+ final ClassObjectType cot = new ClassObjectType( object.getClass() );
+ final Map<ObjectType, ObjectTypeNode> map = source.getObjectTypeNodes( EntryPoint.DEFAULT );
+ final ObjectTypeNode node = map.get( cot );
+ final ObjectHashSet memory = (ObjectHashSet) this.getNodeMemory( node );
+
+ // All objects of this type that are already there were certainly stated,
+ // since this method call happens at the first logical insert, for any given type.
+ org.drools.core.util.Iterator it = memory.iterator();
+
+ for ( Object obj = it.next(); obj != null; obj = it.next() ) {
+
+ org.drools.core.util.ObjectHashSet.ObjectEntry holder = (org.drools.core.util.ObjectHashSet.ObjectEntry) obj;
+
+ InternalFactHandle handle = (InternalFactHandle) holder.getValue();
+
+ if ( handle != null) {
+ EqualityKey key = createEqualityKey(handle);
+ key.setStatus(EqualityKey.STATED);
+ this.tms.put(key);
+ }
+ }
+
+ // Enable TMS for this type.
+ conf.enableTMS();
+
+ }
+
private InternalFactHandle createHandle(final Object object,
ObjectTypeConf typeConf) {
InternalFactHandle handle;
@@ -1257,14 +1308,17 @@
this.entryPoint );
final Object object = handle.getObject();
+
+ final ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
+ object );
this.entryPointNode.retractObject( handle,
propagationContext,
- this.typeConfReg.getObjectTypeConf( this.entryPoint,
- object ),
+ typeConf,
this );
- if ( this.maintainTms ) {
+ if ( typeConf.isTMSEnabled() ) {
+
// Update the equality key, which maintains a list of stated
// FactHandles
final EqualityKey key = handle.getEqualityKey();
@@ -1284,6 +1338,7 @@
this.tms.remove( key );
}
}
+
this.workingMemoryEventSupport.fireObjectRetracted( propagationContext,
handle,
@@ -1345,10 +1400,13 @@
if ( ((InternalFactHandle)factHandle).isDisconnected() ) {
factHandle = this.objectStore.reconnect( factHandle );
}
+
+ final ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
+ object );
// only needed if we maintain tms, but either way we must get it before we do the retract
int status = -1;
- if ( this.maintainTms ) {
+ if ( typeConf.isTMSEnabled() ) {
status = ((InternalFactHandle) factHandle).getEqualityKey().getStatus();
}
final InternalFactHandle handle = (InternalFactHandle) factHandle;
@@ -1373,18 +1431,19 @@
object );
}
- if ( this.maintainTms ) {
-
+ if ( typeConf.isTMSEnabled() ) {
+
// the hashCode and equality has changed, so we must update the
// EqualityKey
EqualityKey key = handle.getEqualityKey();
key.removeFactHandle( handle );
+
// If the equality key is now empty, then remove it
if ( key.isEmpty() ) {
this.tms.remove( key );
}
-
+
// now use an existing EqualityKey, if it exists, else create a new one
key = this.tms.get( object );
if ( key == null ) {
@@ -1394,8 +1453,9 @@
} else {
key.addFactHandle( handle );
}
+
+ handle.setEqualityKey( key );
- handle.setEqualityKey( key );
}
this.handleFactory.increaseFactHandleRecency( handle );
@@ -1409,9 +1469,6 @@
this.agenda.getDormantActivations(),
entryPoint );
- ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
- object );
-
this.entryPointNode.modifyObject( handle,
propagationContext,
typeConf,
@@ -1474,11 +1531,11 @@
public void removeLogicalDependencies(final Activation activation,
final PropagationContext context,
final Rule rule) throws FactException {
- if ( this.maintainTms ) {
- this.tms.removeLogicalDependencies( activation,
- context,
- rule );
- }
+
+ this.tms.removeLogicalDependencies( activation,
+ context,
+ rule );
+
}
/**
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java 2010-09-24 21:48:00 UTC (rev 35291)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ClassObjectTypeConf.java 2010-09-24 22:53:24 UTC (rev 35292)
@@ -52,7 +52,10 @@
private EntryPoint entryPoint;
private TypeDeclaration typeDecl;
+
+ private boolean tmsEnabled;
+
public ClassObjectTypeConf() {
}
@@ -104,6 +107,7 @@
shadowEnabled = stream.readBoolean();
concreteObjectTypeNode = (ObjectTypeNode) stream.readObject();
entryPoint = (EntryPoint) stream.readObject();
+ tmsEnabled = stream.readBoolean();
defineShadowProxyData( cls );
}
@@ -114,6 +118,7 @@
stream.writeBoolean( shadowEnabled );
stream.writeObject( concreteObjectTypeNode );
stream.writeObject( entryPoint );
+ stream.writeObject(tmsEnabled);
}
public boolean isAssignableFrom(Object object) {
@@ -191,4 +196,13 @@
public boolean isDynamic() {
return (typeDecl != null) ? typeDecl.isDynamic() : false;
}
+
+ public boolean isTMSEnabled() {
+ return this.tmsEnabled;
+ }
+
+ public void enableTMS() {
+ this.tmsEnabled = true;
+ }
+
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java 2010-09-24 21:48:00 UTC (rev 35291)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/FactTemplateTypeConf.java 2010-09-24 22:53:24 UTC (rev 35292)
@@ -20,6 +20,7 @@
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
+import java.util.concurrent.atomic.AtomicInteger;
import org.drools.RuntimeDroolsException;
import org.drools.common.InternalRuleBase;
@@ -41,7 +42,10 @@
private FactTemplate factTemplate;
private ObjectTypeNode concreteObjectTypeNode;
private ObjectTypeNode[] cache;
+
+ private boolean tmsEnabled;
+
public FactTemplateTypeConf() {
}
@@ -127,5 +131,13 @@
public boolean isDynamic() {
return false;
}
+
+ public boolean isTMSEnabled() {
+ return this.tmsEnabled;
+ }
+ public void enableTMS() {
+ this.tmsEnabled = true;
+ }
+
}
Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeConf.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeConf.java 2010-09-24 21:48:00 UTC (rev 35291)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ObjectTypeConf.java 2010-09-24 22:53:24 UTC (rev 35292)
@@ -34,6 +34,15 @@
public boolean isEvent();
public boolean isDynamic();
+
+ public TypeDeclaration getTypeDeclaration();
- public TypeDeclaration getTypeDeclaration();
+ /** Whether or not, TMS is active for this object type. */
+ public boolean isTMSEnabled();
+
+ /**
+ * Enable TMS for this object type.
+ * */
+ public void enableTMS();
+
}
\ No newline at end of file
Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/LazyTMSEnablingTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/LazyTMSEnablingTest.java (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/common/LazyTMSEnablingTest.java 2010-09-24 22:53:24 UTC (rev 35292)
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2010 JBoss Inc
+ *
+ * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.drools.common;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.drools.RuleBaseFactory;
+import org.drools.reteoo.ObjectTypeConf;
+import org.drools.reteoo.ReteooWorkingMemory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * <p>
+ * Verify that TMS will be lazily enabled after the first logical insert is
+ * processed.
+ * </p>
+ *
+ * <p>
+ * This is based on the ideas <a
+ * href="http://blog.athico.com/2010/09/lazily-enabled-truth-maintenace.html">
+ * published here.</a>
+ * </p>
+ *
+ * @author <a href="mailto:leonardo.f.gomes at gmail.com">Leonardo Gomes</a>
+ */
+public class LazyTMSEnablingTest {
+
+ private ReteooWorkingMemory wm;
+ private TruthMaintenanceSystem tms;
+
+ @Before
+ public void setUp() {
+
+ wm = (ReteooWorkingMemory) RuleBaseFactory.newRuleBase()
+ .newStatefulSession();
+
+ tms = wm.getTruthMaintenanceSystem();
+
+ }
+
+ @Test
+ public void shouldLazilyAdd() throws Exception {
+
+ final String fact1 = "logical";
+
+ wm.insert(fact1);
+
+ assertEquals(
+ "Shouldn't have anything, since no logical insert was performed.",
+ 0, tms.getAssertMap().size());
+
+ final String fact2 = "logical";
+
+ wm.insertLogical(fact2);
+
+ assertEquals(
+ "Now that a logical insert was done, it should have an element.",
+ 1, tms.getAssertMap().size());
+
+ // Make sure the internals are fine.
+ ObjectTypeConf typeConf = wm.getObjectTypeConfigurationRegistry()
+ .getObjectTypeConf(wm.getEntryPoint(), fact1);
+
+ assertTrue("Should have enabled TMS", typeConf.isTMSEnabled());
+
+ }
+
+ @Test
+ public void shouldEnableTMSForSpecificType() throws Exception {
+
+ final String stringFact1 = "toto";
+ final String stringFact2 = "toto";
+ final String anotherString = "tata";
+
+ final Integer intFact1 = 99;
+ final Integer intFact2 = 99;
+
+ final Double doubleFact = 77.8;
+
+ ObjectTypeConf stringTypeConf = wm.getObjectTypeConfigurationRegistry()
+ .getObjectTypeConf(wm.getEntryPoint(), stringFact1);
+
+ ObjectTypeConf intTypeConf = wm.getObjectTypeConfigurationRegistry()
+ .getObjectTypeConf(wm.getEntryPoint(), intFact1);
+
+ wm.insert(stringFact1);
+ wm.insert(anotherString);
+ wm.insert(intFact1);
+ wm.insert(doubleFact);
+
+ for (ObjectTypeConf conf : wm.getObjectTypeConfigurationRegistry()
+ .values()) {
+
+ assertFalse(
+ "TMS shouldn't be enabled for any type, since no logical insert was done.",
+ conf.isTMSEnabled());
+
+ }
+
+ wm.insertLogical(stringFact2);
+
+ assertTrue("Should have enabled TMS for Strings.", stringTypeConf
+ .isTMSEnabled());
+
+ assertFalse("Shouldn't have enabled TMS for Integers.", intTypeConf
+ .isTMSEnabled());
+
+ wm.insertLogical(intFact2);
+
+ assertTrue("Now it should have enabled TMS for Integers!.", intTypeConf
+ .isTMSEnabled());
+
+ }
+
+}
Modified: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java 2010-09-24 21:48:00 UTC (rev 35291)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/reteoo/ReteooWorkingMemoryTest.java 2010-09-24 22:53:24 UTC (rev 35292)
@@ -50,10 +50,14 @@
final ReteooWorkingMemory workingMemory = (ReteooWorkingMemory) RuleBaseFactory.newRuleBase().newStatefulSession();
final TruthMaintenanceSystem tms = workingMemory.getTruthMaintenanceSystem();
final String string = "test";
- FactHandle fd = workingMemory.insert( string );
+
+ workingMemory.insert( string );
+
+ FactHandle fd = workingMemory.insertLogical( string );
assertEquals( 1,
tms.getAssertMap().size() );
+
EqualityKey key = tms.get( string );
assertSame( fd,
key.getFactHandle() );
More information about the jboss-svn-commits
mailing list