[jboss-svn-commits] JBL Code SVN: r27318 - in labs/jbossrules/trunk: drools-compiler/src/test/java/org/drools/integrationtests and 3 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Jun 29 21:10:21 EDT 2009


Author: tirelli
Date: 2009-06-29 21:10:21 -0400 (Mon, 29 Jun 2009)
New Revision: 27318

Modified:
   labs/jbossrules/trunk/drools-clips/src/main/java/org/drools/clips/ClipsShell.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/RulebasePartitioningTest.java
   labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NamedEntryPoint.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java
Log:
Adding support to idle time. I don't remember the ticket number and obviously enough, JIRA is down

Modified: labs/jbossrules/trunk/drools-clips/src/main/java/org/drools/clips/ClipsShell.java
===================================================================
--- labs/jbossrules/trunk/drools-clips/src/main/java/org/drools/clips/ClipsShell.java	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-clips/src/main/java/org/drools/clips/ClipsShell.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -365,7 +365,7 @@
         }
         builder.append( "}" );
 
-        functionDescr.setContent( builder.toString() );
+        functionDescr.setText( builder.toString() );
         functionDescr.setDialect( "clips" );
 
         PackageDescr pkgDescr = createPackageDescr( functionDescr.getNamespace() );

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/RulebasePartitioningTest.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/RulebasePartitioningTest.java	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/integrationtests/RulebasePartitioningTest.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -46,14 +46,7 @@
                                             config );
     }
     
-    public void testDummy() {
-        // I've added this until edson stops sucking.
-    }
-    
-    /**
-     * Edson Sucks so I'm making this a @FIXME
-     */
-    public void FIXME_testRulebasePartitions1() throws Exception {
+    public void testRulebasePartitions1() throws Exception {
         final PackageBuilder builder = new PackageBuilder();
         builder.addPackageFromDrl( new InputStreamReader( getClass().getResourceAsStream( "test_rulebasePartitions1.drl" ) ) );
         final org.drools.rule.Package pkg = builder.getPackage();

Modified: labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockWorkingMemory.java	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-compiler/src/test/java/org/drools/testframework/MockWorkingMemory.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -562,4 +562,19 @@
         return null;
     }
 
+    public void endOperation() {
+        // TODO Auto-generated method stub
+        
+    }
+
+    public long getIdleTime() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    public void startOperation() {
+        // TODO Auto-generated method stub
+        
+    }
+
 }

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	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractWorkingMemory.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -214,6 +214,13 @@
     private Environment                                                       environment;
 
     private ExecutionResults                                                  batchExecutionResult;
+    
+    // this is a counter of concurrent operations happening. When this counter is zero, 
+    // the engine is idle.
+    private AtomicLong                                                        opCounter;
+    // this is the timestamp of the end of the last operation, based on the session clock,
+    // or -1 if there are operation being executed at this moment
+    private AtomicLong                                                        lastIdleTimestamp;
 
     // ------------------------------------------------------------
     // Constructors
@@ -325,6 +332,9 @@
         initProcessEventListeners();
         initPartitionManagers();
         initTransient();
+        
+        this.opCounter = new AtomicLong(0);
+        this.lastIdleTimestamp = new AtomicLong( -1 );
     }
 
     public static class GlobalsAdapter
@@ -398,27 +408,37 @@
      * running in multi-thread mode
      */
     public void startPartitionManagers() {
-        if ( this.ruleBase.getConfiguration().isMultithreadEvaluation() ) {
-            int maxThreads = (this.ruleBase.getConfiguration().getMaxThreads() > 0) ? this.ruleBase.getConfiguration().getMaxThreads() : this.ruleBase.getPartitionIds().size();
-            if ( this.threadPool.compareAndSet( null,
-                                                Executors.newFixedThreadPool( maxThreads ) ) ) {
-                for ( PartitionTaskManager task : this.partitionManagers.values() ) {
-                    task.setPool( this.threadPool.get() );
+        startOperation();
+        try {
+            if ( this.ruleBase.getConfiguration().isMultithreadEvaluation() ) {
+                int maxThreads = (this.ruleBase.getConfiguration().getMaxThreads() > 0) ? this.ruleBase.getConfiguration().getMaxThreads() : this.ruleBase.getPartitionIds().size();
+                if ( this.threadPool.compareAndSet( null,
+                                                    Executors.newFixedThreadPool( maxThreads ) ) ) {
+                    for ( PartitionTaskManager task : this.partitionManagers.values() ) {
+                        task.setPool( this.threadPool.get() );
+                    }
                 }
             }
+        } finally {
+            endOperation();
         }
     }
 
     public void stopPartitionManagers() {
-        if ( this.ruleBase.getConfiguration().isMultithreadEvaluation() ) {
-            java.util.concurrent.ExecutorService service = this.threadPool.get();
-            if ( this.threadPool.compareAndSet( service,
-                                                null ) ) {
-                service.shutdown();
-                for ( PartitionTaskManager task : this.partitionManagers.values() ) {
-                    task.setPool( null );
+        startOperation();
+        try {
+            if ( this.ruleBase.getConfiguration().isMultithreadEvaluation() ) {
+                java.util.concurrent.ExecutorService service = this.threadPool.get();
+                if ( this.threadPool.compareAndSet( service,
+                                                    null ) ) {
+                    service.shutdown();
+                    for ( PartitionTaskManager task : this.partitionManagers.values() ) {
+                        task.setPool( null );
+                    }
                 }
             }
+        } finally {
+            endOperation();
         }
     }
 
@@ -448,6 +468,8 @@
         this.actionQueue.clear();
 
         this.propagationIdCounter = new AtomicLong( propagationCounter );
+        this.opCounter.set( 0 );
+        this.lastIdleTimestamp.set( -1 );
 
         // TODO should these be cleared?
         // we probably neeed to do CEP and Flow timers too
@@ -542,6 +564,7 @@
         try {
             this.ruleBase.readLock();
             this.lock.lock();
+            startOperation();
             // Make sure the global has been declared in the RuleBase
             final Map globalDefintions = this.ruleBase.getGlobals();
             final Class type = (Class) globalDefintions.get( identifier );
@@ -555,6 +578,7 @@
                                                value );
             }
         } finally {
+            endOperation();
             this.lock.unlock();
             this.ruleBase.readUnlock();
         }
@@ -850,169 +874,175 @@
             return null;
         }
 
-        ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
-                                                                      object );
-
-        InternalFactHandle handle = null;
-
-        if ( isSequential() ) {
-            handle = createHandle( object,
-                                   typeConf );
-            insert( handle,
-                    object,
-                    rule,
-                    activation,
-                    typeConf );
-            return handle;
-        }
-
         try {
-            this.ruleBase.readLock();
-            this.lock.lock();
-            // check if the object already exists in the WM
-            handle = (InternalFactHandle) this.objectStore.getHandleForObject( object );
+            startOperation();
+            
+            ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
+                                                                          object );
 
-            if ( this.maintainTms ) {
+            InternalFactHandle handle = null;
 
-                EqualityKey key = null;
+            if ( isSequential() ) {
+                handle = createHandle( object,
+                                       typeConf );
+                insert( handle,
+                        object,
+                        rule,
+                        activation,
+                        typeConf );
+                return handle;
+            }
+            try {
+                this.ruleBase.readLock();
+                this.lock.lock();
+                // check if the object already exists in the WM
+                handle = (InternalFactHandle) this.objectStore.getHandleForObject( object );
 
-                if ( handle == null ) {
-                    // lets see if the object is already logical asserted
-                    key = this.tms.get( object );
-                } else {
-                    // Object is already asserted, so check and possibly correct
-                    // its
-                    // status and then return the handle
-                    key = handle.getEqualityKey();
+                if ( this.maintainTms ) {
 
-                    if ( key.getStatus() == EqualityKey.STATED ) {
-                        // return null as you cannot justify a stated object.
-                        return handle;
-                    }
+                    EqualityKey key = null;
 
-                    if ( !logical ) {
-                        // this object was previously justified, so we have to
-                        // override it to stated
-                        key.setStatus( EqualityKey.STATED );
-                        this.tms.removeLogicalDependencies( handle );
+                    if ( handle == null ) {
+                        // lets see if the object is already logical asserted
+                        key = this.tms.get( object );
                     } else {
-                        // this was object is already justified, so just add new
-                        // logical dependency
-                        this.tms.addLogicalDependency( handle,
-                                                       activation,
-                                                       activation.getPropagationContext(),
-                                                       rule );
-                    }
+                        // Object is already asserted, so check and possibly correct
+                        // its
+                        // status and then return the handle
+                        key = handle.getEqualityKey();
 
-                    return handle;
-                }
+                        if ( key.getStatus() == EqualityKey.STATED ) {
+                            // return null as you cannot justify a stated object.
+                            return handle;
+                        }
 
-                // At this point we know the handle is null
-                if ( key == null ) {
-                    handle = createHandle( object,
-                                           typeConf );
+                        if ( !logical ) {
+                            // this object was previously justified, so we have to
+                            // override it to stated
+                            key.setStatus( EqualityKey.STATED );
+                            this.tms.removeLogicalDependencies( handle );
+                        } else {
+                            // this was object is already justified, so just add new
+                            // logical dependency
+                            this.tms.addLogicalDependency( handle,
+                                                           activation,
+                                                           activation.getPropagationContext(),
+                                                           rule );
+                        }
 
-                    key = new EqualityKey( handle );
-                    handle.setEqualityKey( key );
-                    this.tms.put( key );
-                    if ( !logical ) {
-                        key.setStatus( EqualityKey.STATED );
-                    } else {
-                        key.setStatus( EqualityKey.JUSTIFIED );
-                        this.tms.addLogicalDependency( handle,
-                                                       activation,
-                                                       activation.getPropagationContext(),
-                                                       rule );
+                        return handle;
                     }
-                } else if ( !logical ) {
-                    if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
-                        // Its previous justified, so switch to stated and
-                        // remove
-                        // logical dependencies
-                        final InternalFactHandle justifiedHandle = key.getFactHandle();
-                        this.tms.removeLogicalDependencies( justifiedHandle );
 
-                        if ( this.discardOnLogicalOverride ) {
-                            // override, setting to new instance, and return
-                            // existing handle
+                    // At this point we know the handle is null
+                    if ( key == null ) {
+                        handle = createHandle( object,
+                                               typeConf );
+
+                        key = new EqualityKey( handle );
+                        handle.setEqualityKey( key );
+                        this.tms.put( key );
+                        if ( !logical ) {
                             key.setStatus( EqualityKey.STATED );
-                            handle = key.getFactHandle();
+                        } else {
+                            key.setStatus( EqualityKey.JUSTIFIED );
+                            this.tms.addLogicalDependency( handle,
+                                                           activation,
+                                                           activation.getPropagationContext(),
+                                                           rule );
+                        }
+                    } else if ( !logical ) {
+                        if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
+                            // Its previous justified, so switch to stated and
+                            // remove
+                            // logical dependencies
+                            final InternalFactHandle justifiedHandle = key.getFactHandle();
+                            this.tms.removeLogicalDependencies( justifiedHandle );
 
-                            if ( AssertBehaviour.IDENTITY.equals( this.ruleBase.getConfiguration().getAssertBehaviour() ) ) {
-                                // as assertMap may be using an "identity"
-                                // equality comparator,
-                                // we need to remove the handle from the map,
-                                // before replacing the object
-                                // and then re-add the handle. Otherwise we may
-                                // end up with a leak.
-                                this.objectStore.updateHandle( handle,
-                                                               object );
+                            if ( this.discardOnLogicalOverride ) {
+                                // override, setting to new instance, and return
+                                // existing handle
+                                key.setStatus( EqualityKey.STATED );
+                                handle = key.getFactHandle();
+
+                                if ( AssertBehaviour.IDENTITY.equals( this.ruleBase.getConfiguration().getAssertBehaviour() ) ) {
+                                    // as assertMap may be using an "identity"
+                                    // equality comparator,
+                                    // we need to remove the handle from the map,
+                                    // before replacing the object
+                                    // and then re-add the handle. Otherwise we may
+                                    // end up with a leak.
+                                    this.objectStore.updateHandle( handle,
+                                                                   object );
+                                } else {
+                                    Object oldObject = handle.getObject();
+                                }
+                                return handle;
                             } else {
-                                Object oldObject = handle.getObject();
+                                // override, then instantiate new handle for
+                                // assertion
+                                key.setStatus( EqualityKey.STATED );
+                                handle = createHandle( object,
+                                                       typeConf );
+                                handle.setEqualityKey( key );
+                                key.addFactHandle( handle );
                             }
-                            return handle;
+
                         } else {
-                            // override, then instantiate new handle for
-                            // assertion
-                            key.setStatus( EqualityKey.STATED );
                             handle = createHandle( object,
                                                    typeConf );
+                            key.addFactHandle( handle );
                             handle.setEqualityKey( key );
-                            key.addFactHandle( handle );
+
                         }
 
                     } else {
-                        handle = createHandle( object,
-                                               typeConf );
-                        key.addFactHandle( handle );
-                        handle.setEqualityKey( key );
-
+                        if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
+                            // only add as logical dependency if this wasn't
+                            // previously
+                            // stated
+                            this.tms.addLogicalDependency( key.getFactHandle(),
+                                                           activation,
+                                                           activation.getPropagationContext(),
+                                                           rule );
+                            return key.getFactHandle();
+                        } else {
+                            // You cannot justify a previously stated equality equal
+                            // object, so return null
+                            return null;
+                        }
                     }
 
                 } else {
-                    if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
-                        // only add as logical dependency if this wasn't
-                        // previously
-                        // stated
-                        this.tms.addLogicalDependency( key.getFactHandle(),
-                                                       activation,
-                                                       activation.getPropagationContext(),
-                                                       rule );
-                        return key.getFactHandle();
-                    } else {
-                        // You cannot justify a previously stated equality equal
-                        // object, so return null
-                        return null;
+                    if ( handle != null ) {
+                        return handle;
                     }
+                    handle = createHandle( object,
+                                           typeConf );
+
                 }
 
-            } else {
-                if ( handle != null ) {
-                    return handle;
+                // if the dynamic parameter is true or if the
+                // user declared the fact type with the meta tag:
+                // @propertyChangeSupport
+                if ( dynamic || typeConf.isDynamic() ) {
+                    addPropertyChangeListener( object );
                 }
-                handle = createHandle( object,
-                                       typeConf );
 
-            }
+                insert( handle,
+                        object,
+                        rule,
+                        activation,
+                        typeConf );
 
-            // if the dynamic parameter is true or if the
-            // user declared the fact type with the meta tag:
-            // @propertyChangeSupport
-            if ( dynamic || typeConf.isDynamic() ) {
-                addPropertyChangeListener( object );
+            } finally {
+                this.lock.unlock();
+                this.ruleBase.readUnlock();
             }
-
-            insert( handle,
-                    object,
-                    rule,
-                    activation,
-                    typeConf );
-
+            return handle;
         } finally {
-            this.lock.unlock();
-            this.ruleBase.readUnlock();
+            endOperation();
         }
-        return handle;
+
     }
 
     private InternalFactHandle createHandle(final Object object,
@@ -1130,6 +1160,7 @@
         try {
             this.ruleBase.readLock();
             this.lock.lock();
+            startOperation();
             this.ruleBase.executeQueuedActions();
 
             InternalFactHandle handle = (InternalFactHandle) factHandle;
@@ -1198,6 +1229,7 @@
 
             executeQueuedActions();
         } finally {
+            endOperation();
             this.lock.unlock();
             this.ruleBase.readUnlock();
         }
@@ -1215,6 +1247,7 @@
         try {
             this.ruleBase.readLock();
             this.lock.lock();
+            startOperation();
             this.ruleBase.executeQueuedActions();
 
             InternalFactHandle handle = (InternalFactHandle) factHandle;
@@ -1268,6 +1301,7 @@
                 }
             }
         } finally {
+            endOperation();
             this.lock.unlock();
             this.ruleBase.readUnlock();
         }
@@ -1288,6 +1322,7 @@
         try {
             this.ruleBase.readLock();
             this.lock.lock();
+            startOperation();
             this.ruleBase.executeQueuedActions();
 
             InternalFactHandle handle = (InternalFactHandle) factHandle;
@@ -1344,6 +1379,7 @@
             executeQueuedActions();
 
         } finally {
+            endOperation();
             this.lock.unlock();
             this.ruleBase.readUnlock();
         }
@@ -1381,6 +1417,7 @@
         try {
             this.ruleBase.readLock();
             this.lock.lock();
+            startOperation();
             this.ruleBase.executeQueuedActions();
 
             // the handle might have been disconnected, so reconnect if it has
@@ -1478,33 +1515,39 @@
 
             executeQueuedActions();
         } finally {
+            endOperation();
             this.lock.unlock();
             this.ruleBase.readUnlock();
         }
     }
 
     public void executeQueuedActions() {
-        synchronized ( this.actionQueue ) {
-            if ( !this.actionQueue.isEmpty() && !evaluatingActionQueue ) {
-                evaluatingActionQueue = true;
-                WorkingMemoryAction action = null;
+        try {
+            startOperation();
+            synchronized ( this.actionQueue ) {
+                if ( !this.actionQueue.isEmpty() && !evaluatingActionQueue ) {
+                    evaluatingActionQueue = true;
+                    WorkingMemoryAction action = null;
 
-                while ( (action = actionQueue.poll()) != null ) {
-                    try {
-                        action.execute( this );
-                    } catch ( Exception e ) {
-                        if ( e instanceof RuntimeDroolsException ) {
-                            // rethrow the exception
-                            throw ((RuntimeDroolsException) e);
-                        } else {
-                            System.err.println( "************************************************" );
-                            System.err.println( "Exception caught while executing action: " + action.toString() );
-                            e.printStackTrace();
+                    while ( (action = actionQueue.poll()) != null ) {
+                        try {
+                            action.execute( this );
+                        } catch ( Exception e ) {
+                            if ( e instanceof RuntimeDroolsException ) {
+                                // rethrow the exception
+                                throw ((RuntimeDroolsException) e);
+                            } else {
+                                System.err.println( "************************************************" );
+                                System.err.println( "Exception caught while executing action: " + action.toString() );
+                                e.printStackTrace();
+                            }
                         }
                     }
+                    evaluatingActionQueue = false;
                 }
-                evaluatingActionQueue = false;
             }
+        } finally {
+            endOperation();
         }
     }
 
@@ -1615,22 +1658,27 @@
 
     public ProcessInstance startProcess(String processId,
                                         Map<String, Object> parameters) {
-        if ( !this.actionQueue.isEmpty() ) {
-            executeQueuedActions();
+        try {
+            startOperation();
+            if ( !this.actionQueue.isEmpty() ) {
+                executeQueuedActions();
+            }
+            final Process process = ((InternalRuleBase) getRuleBase()).getProcess( processId );
+            if ( process == null ) {
+                throw new IllegalArgumentException( "Unknown process ID: " + processId );
+            }
+            ProcessInstance processInstance = startProcess( process, parameters );
+            
+            if (processInstance != null) { 
+                // start process instance
+                getRuleFlowEventSupport().fireBeforeRuleFlowProcessStarted( processInstance, this );
+                processInstance.start();
+                getRuleFlowEventSupport().fireAfterRuleFlowProcessStarted( processInstance, this );
+            }
+            return processInstance;
+        } finally {
+            endOperation();
         }
-        final Process process = ((InternalRuleBase) getRuleBase()).getProcess( processId );
-        if ( process == null ) {
-            throw new IllegalArgumentException( "Unknown process ID: " + processId );
-        }
-        ProcessInstance processInstance = startProcess( process, parameters );
-        
-        if (processInstance != null) { 
-	        // start process instance
-	        getRuleFlowEventSupport().fireBeforeRuleFlowProcessStarted( processInstance, this );
-	        processInstance.start();
-	        getRuleFlowEventSupport().fireAfterRuleFlowProcessStarted( processInstance, this );
-        }
-        return processInstance;
     }
 
     private ProcessInstance startProcess(final Process process, Map<String, Object> parameters) {
@@ -1948,5 +1996,48 @@
     public Map<String, WorkingMemoryEntryPoint> getEntryPoints() {
         return this.entryPoints;
     }
+    
+    /**
+     * This method must be called before starting any new work in the engine,
+     * like inserting a new fact or firing a new rule. It will reset the engine
+     * idle time counter.
+     * 
+     * This method must be extremely light to avoid contentions when called by 
+     * multiple threads/entry-points
+     */
+    public void startOperation() {
+        if( this.opCounter.getAndIncrement() == 0) {
+            // means the engine was idle, reset the timestamp
+            this.lastIdleTimestamp.set( -1 );
+        }
+    }
 
+    /**
+     * This method must be called after finishing any work in the engine,
+     * like inserting a new fact or firing a new rule. It will reset the engine
+     * idle time counter.
+     * 
+     * This method must be extremely light to avoid contentions when called by 
+     * multiple threads/entry-points
+     */
+    public void endOperation() {
+        if( this.opCounter.decrementAndGet() == 0) {
+            // means the engine is idle, so, set the timestamp
+            this.lastIdleTimestamp.set( this.timerManager.getTimerService().getCurrentTime() );
+        }
+    }
+    
+    /**
+     * Returns the number of time units (usually ms) that the engine is idle
+     * according to the session clock or -1 if it is not idle.
+     * 
+     * This method is not synchronised and might return an approximate value.
+     *  
+     * @return
+     */
+    public long getIdleTime() {
+        long lastIdle = this.lastIdleTimestamp.get();
+        return lastIdle > -1 ? timerManager.getTimerService().getCurrentTime() - lastIdle : -1;
+    }
+
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/DefaultAgenda.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -912,69 +912,74 @@
         // We do this first as if a node modifies a fact that causes a recursion
         // on an empty pattern
         // we need to make sure it re-activates
-        increaseDormantActivations();
+        this.workingMemory.startOperation();
+        try {
+            increaseDormantActivations();
 
-        final EventSupport eventsupport = (EventSupport) this.workingMemory;
+            final EventSupport eventsupport = (EventSupport) this.workingMemory;
 
-        eventsupport.getAgendaEventSupport().fireBeforeActivationFired( activation,
-                                                                        this.workingMemory );
+            eventsupport.getAgendaEventSupport().fireBeforeActivationFired( activation,
+                                                                            this.workingMemory );
 
-        if ( activation.getActivationGroupNode() != null ) {
-            // We know that this rule will cancel all other activatiosn in the
-            // group
-            // so lets remove the information now, before the consequence fires
-            final ActivationGroup activationGroup = activation.getActivationGroupNode().getActivationGroup();
-            activationGroup.removeActivation( activation );
-            clearAndCancelActivationGroup( activationGroup );
-        }
-        activation.setActivated( false );
+            if ( activation.getActivationGroupNode() != null ) {
+                // We know that this rule will cancel all other activatiosn in the
+                // group
+                // so lets remove the information now, before the consequence fires
+                final ActivationGroup activationGroup = activation.getActivationGroupNode().getActivationGroup();
+                activationGroup.removeActivation( activation );
+                clearAndCancelActivationGroup( activationGroup );
+            }
+            activation.setActivated( false );
 
-        try {
-            this.knowledgeHelper.setActivation( activation );
-            activation.getRule().getConsequence().evaluate( this.knowledgeHelper,
-                                                            this.workingMemory );
-            this.knowledgeHelper.reset();
-        } catch ( final Exception e ) {
-            if ( this.legacyConsequenceExceptionHandler != null ) {
-                this.legacyConsequenceExceptionHandler.handleException( activation,
-                                                                        this.workingMemory,
-                                                                        e );
-            } else if ( this.consequenceExceptionHandler != null ) {
-                this.consequenceExceptionHandler.handleException( activation,
-                                                                  new StatefulKnowledgeSessionImpl( (ReteooWorkingMemory) this.workingMemory ),
-                                                                  e );
-            } else {
-                throw new RuntimeException( e );
+            try {
+                this.knowledgeHelper.setActivation( activation );
+                activation.getRule().getConsequence().evaluate( this.knowledgeHelper,
+                                                                this.workingMemory );
+                this.knowledgeHelper.reset();
+            } catch ( final Exception e ) {
+                if ( this.legacyConsequenceExceptionHandler != null ) {
+                    this.legacyConsequenceExceptionHandler.handleException( activation,
+                                                                            this.workingMemory,
+                                                                            e );
+                } else if ( this.consequenceExceptionHandler != null ) {
+                    this.consequenceExceptionHandler.handleException( activation,
+                                                                      new StatefulKnowledgeSessionImpl( (ReteooWorkingMemory) this.workingMemory ),
+                                                                      e );
+                } else {
+                    throw new RuntimeException( e );
+                }
             }
-        }
 
-        if ( activation.getRuleFlowGroupNode() != null ) {
-            final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
-            // it is possible that the ruleflow group is no longer active if it was
-            // cleared during execution of this activation
-            if (ruleFlowGroup.isActive()) {
-            	ruleFlowGroup.removeActivation( activation );
+            if ( activation.getRuleFlowGroupNode() != null ) {
+                final InternalRuleFlowGroup ruleFlowGroup = activation.getRuleFlowGroupNode().getRuleFlowGroup();
+                // it is possible that the ruleflow group is no longer active if it was
+                // cleared during execution of this activation
+                if (ruleFlowGroup.isActive()) {
+                    ruleFlowGroup.removeActivation( activation );
+                }
             }
-        }
 
-        // if the tuple contains expired events 
-        for ( LeftTuple tuple = (LeftTuple) activation.getTuple(); tuple != null; tuple = tuple.getParent() ) {
-            if ( tuple.getLastHandle().isEvent() ) {
-                EventFactHandle handle = (EventFactHandle) tuple.getLastHandle();
-                // handles "expire" only in stream mode.
-                if ( handle.isExpired() ) {
-                    // decrease the activation count for the event
-                    handle.decreaseActivationsCount();
-                    if ( handle.getActivationsCount() == 0 ) {
-                        // and if no more activations, retract the handle
-                        handle.getEntryPoint().retract( handle );
+            // if the tuple contains expired events 
+            for ( LeftTuple tuple = (LeftTuple) activation.getTuple(); tuple != null; tuple = tuple.getParent() ) {
+                if ( tuple.getLastHandle().isEvent() ) {
+                    EventFactHandle handle = (EventFactHandle) tuple.getLastHandle();
+                    // handles "expire" only in stream mode.
+                    if ( handle.isExpired() ) {
+                        // decrease the activation count for the event
+                        handle.decreaseActivationsCount();
+                        if ( handle.getActivationsCount() == 0 ) {
+                            // and if no more activations, retract the handle
+                            handle.getEntryPoint().retract( handle );
+                        }
                     }
                 }
             }
+
+            eventsupport.getAgendaEventSupport().fireAfterActivationFired( activation,
+                                                                           this.workingMemory );
+        } finally {
+            this.workingMemory.endOperation();
         }
-
-        eventsupport.getAgendaEventSupport().fireAfterActivationFired( activation,
-                                                                       this.workingMemory );
     }
 
     public void increaseActiveActivations() {

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/InternalWorkingMemory.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -139,4 +139,35 @@
     public BatchExecutionResultImpl getExecutionResult();
     
     public void endBatchExecution();
+    
+    /**
+     * This method must be called before starting any new work in the engine,
+     * like inserting a new fact or firing a new rule. It will reset the engine
+     * idle time counter.
+     * 
+     * This method must be extremely light to avoid contentions when called by 
+     * multiple threads/entry-points
+     */
+    public void startOperation();
+
+    /**
+     * This method must be called after finishing any work in the engine,
+     * like inserting a new fact or firing a new rule. It will reset the engine
+     * idle time counter.
+     * 
+     * This method must be extremely light to avoid contentions when called by 
+     * multiple threads/entry-points
+     */
+    public void endOperation();
+    
+    /**
+     * Returns the number of time units (usually ms) that the engine is idle
+     * according to the session clock or -1 if it is not idle.
+     * 
+     * This method is not synchronised and might return an approximate value.
+     *  
+     * @return
+     */
+    public long getIdleTime();
+    
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NamedEntryPoint.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NamedEntryPoint.java	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/NamedEntryPoint.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -102,32 +102,34 @@
             // you cannot assert a null object
             return null;
         }
-
-        ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
-                                                                      object );
-
-        InternalFactHandle handle = this.handleFactory.newFactHandle( object,
-                                                                      typeConf,
-                                                                      wm );
-        handle.setEntryPoint( this );
-        this.objectStore.addHandle( handle,
-                                    object );
-
-        if ( dynamic ) {
-            addPropertyChangeListener( object );
-        }
-
+        
         try {
-            this.lock.lock();
-            insert( handle,
-                    object,
-                    rule,
-                    activation );
+            this.wm.startOperation();
+            ObjectTypeConf typeConf = this.typeConfReg.getObjectTypeConf( this.entryPoint,
+                                                                          object );
+            InternalFactHandle handle = this.handleFactory.newFactHandle( object,
+                                                                          typeConf,
+                                                                          wm );
+            handle.setEntryPoint( this );
+            this.objectStore.addHandle( handle,
+                                        object );
+            if ( dynamic ) {
+                addPropertyChangeListener( object );
+            }
+            try {
+                this.lock.lock();
+                insert( handle,
+                        object,
+                        rule,
+                        activation );
 
+            } finally {
+                this.lock.unlock();
+            }
+            return handle;
         } finally {
-            this.lock.unlock();
+            this.wm.endOperation();
         }
-        return handle;
     }
 
     protected void insert(final InternalFactHandle handle,
@@ -178,6 +180,7 @@
         try {
             this.lock.lock();
             this.ruleBase.executeQueuedActions();
+            this.wm.startOperation();
 
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
             final Object originalObject = handle.getObject();
@@ -237,6 +240,7 @@
 
             this.wm.executeQueuedActions();
         } finally {
+            this.wm.endOperation();
             this.lock.unlock();
         }
     }
@@ -257,6 +261,7 @@
         try {
             this.lock.lock();
             this.ruleBase.executeQueuedActions();
+            this.wm.startOperation();
 
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
             if ( handle.getId() == -1 ) {
@@ -299,6 +304,7 @@
 
             this.wm.executeQueuedActions();
         } finally {
+            this.wm.endOperation();
             this.lock.unlock();
         }
     }
@@ -315,6 +321,7 @@
         try {
             this.lock.lock();
             this.ruleBase.executeQueuedActions();
+            this.wm.startOperation();
 
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
             // final Object originalObject = (handle.isShadowFact()) ?
@@ -350,6 +357,7 @@
                                                this.wm );
 
         } finally {
+            this.wm.endOperation();
             this.lock.unlock();
         }
     }
@@ -381,6 +389,7 @@
         try {
             this.lock.lock();
             this.ruleBase.executeQueuedActions();
+            this.wm.startOperation();
 
             final InternalFactHandle handle = (InternalFactHandle) factHandle;
             final Object originalObject = handle.getObject();
@@ -419,6 +428,7 @@
 
             this.wm.executeQueuedActions();
         } finally {
+            this.wm.endOperation();
             this.lock.unlock();
         }
     }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java	2009-06-30 00:33:17 UTC (rev 27317)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooWorkingMemory.java	2009-06-30 01:10:21 UTC (rev 27318)
@@ -45,7 +45,6 @@
 import org.drools.rule.Rule;
 import org.drools.runtime.Environment;
 import org.drools.runtime.ObjectFilter;
-import org.drools.runtime.rule.FactHandle;
 import org.drools.spi.FactHandleFactory;
 import org.drools.spi.PropagationContext;
 
@@ -134,57 +133,62 @@
     public QueryResults getQueryResults(final String query,
                                         final Object[] arguments) {
 
-        Object object = new DroolsQuery( query,
-                                         arguments );
-        InternalFactHandle handle = this.handleFactory.newFactHandle( object,
-                                                                      this.getObjectTypeConfigurationRegistry().getObjectTypeConf( EntryPoint.DEFAULT,
-                                                                                                                                   object ),
-                                                                      this );
+        try {
+            startOperation();
+            Object object = new DroolsQuery( query,
+                                             arguments );
+            InternalFactHandle handle = this.handleFactory.newFactHandle( object,
+                                                                          this.getObjectTypeConfigurationRegistry().getObjectTypeConf( EntryPoint.DEFAULT,
+                                                                                                                                       object ),
+                                                                          this );
 
-        insert( handle,
-                object,
-                null,
-                null,
-                this.typeConfReg.getObjectTypeConf( this.entryPoint,
-                                                    object ) );
+            insert( handle,
+                    object,
+                    null,
+                    null,
+                    this.typeConfReg.getObjectTypeConf( this.entryPoint,
+                                                        object ) );
 
-        final QueryTerminalNode node = (QueryTerminalNode) this.queryResults.remove( query );
-        Query queryObj = null;
-        List list = null;
+            final QueryTerminalNode node = (QueryTerminalNode) this.queryResults.remove( query );
+            Query queryObj = null;
+            List list = null;
 
-        if ( node == null ) {
-            // There are no results, first check the query object actually exists
-            final org.drools.rule.Package[] pkgs = this.ruleBase.getPackages();
-            for ( int i = 0; i < pkgs.length; i++ ) {
-                final Rule rule = pkgs[i].getRule( query );
-                if ( (rule != null) && (rule instanceof Query) ) {
-                    queryObj = (Query) rule;
-                    break;
+            if ( node == null ) {
+                // There are no results, first check the query object actually exists
+                final org.drools.rule.Package[] pkgs = this.ruleBase.getPackages();
+                for ( int i = 0; i < pkgs.length; i++ ) {
+                    final Rule rule = pkgs[i].getRule( query );
+                    if ( (rule != null) && (rule instanceof Query) ) {
+                        queryObj = (Query) rule;
+                        break;
+                    }
                 }
-            }
 
-            this.handleFactory.destroyFactHandle( handle );
+                this.handleFactory.destroyFactHandle( handle );
 
-            if ( queryObj == null ) {
-                throw new IllegalArgumentException( "Query '" + query + "' does not exist" );
-            }
-            list = Collections.EMPTY_LIST;
-        } else {
-            list = (List) this.getNodeMemory( node );
-
-            if ( list == null ) {
+                if ( queryObj == null ) {
+                    throw new IllegalArgumentException( "Query '" + query + "' does not exist" );
+                }
                 list = Collections.EMPTY_LIST;
             } else {
-                this.clearNodeMemory( node );
+                list = (List) this.getNodeMemory( node );
+
+                if ( list == null ) {
+                    list = Collections.EMPTY_LIST;
+                } else {
+                    this.clearNodeMemory( node );
+                }
+                queryObj = (Query) node.getRule();
+
+                this.handleFactory.destroyFactHandle( handle );
             }
-            queryObj = (Query) node.getRule();
 
-            this.handleFactory.destroyFactHandle( handle );
+            return new QueryResults( list,
+                                     queryObj,
+                                     this );
+        } finally {
+            endOperation();
         }
-
-        return new QueryResults( list,
-                                 queryObj,
-                                 this );
     }
 
     void setQueryResults(final String query,




More information about the jboss-svn-commits mailing list