[jboss-svn-commits] JBL Code SVN: r34382 - in labs/jbossrules/trunk/drools-core/src/main/java/org/drools: common and 3 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Jul 29 22:00:34 EDT 2010


Author: tirelli
Date: 2010-07-29 22:00:34 -0400 (Thu, 29 Jul 2010)
New Revision: 34382

Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooStatelessSession.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java
Log:
JBRULES-2263: applying patches

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java	2010-07-30 01:59:52 UTC (rev 34381)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/agent/impl/KnowledgeAgentImpl.java	2010-07-30 02:00:34 UTC (rev 34382)
@@ -590,12 +590,16 @@
              * If the ruleBase is sequential, after rebuilding or incremental
              * update, do an ordering of the ReteooBuilder
              */
+            // FIXME: this same code exists in ReteooRuleBase#newStatelessSession()
             InternalRuleBase ruleBase = (InternalRuleBase) ((KnowledgeBaseImpl) this.kbase).ruleBase;
-            synchronized (ruleBase.getPackagesMap()) {
-                if (ruleBase.getConfiguration().isSequential()) {
+            ruleBase.lock(); // XXX: readlock might be enough, no idea what order() does.
+            try {
+                if ( ruleBase.getConfiguration().isSequential() ) {
                     ruleBase.getReteooBuilder().order();
                 }
-            }
+            } finally {
+                ruleBase.unlock();
+            }            
         }
         this.eventSupport.fireKnowledgeBaseUpdated(this.kbase);
         this.listener.debug("KnowledgeAgent finished rebuilding KnowledgeBase using ChangeSet");

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java	2010-07-30 01:59:52 UTC (rev 34381)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/common/AbstractRuleBase.java	2010-07-30 02:00:34 UTC (rev 34382)
@@ -22,7 +22,6 @@
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -30,8 +29,11 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
-import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -73,49 +75,49 @@
     // ------------------------------------------------------------
     // Instance members
     // ------------------------------------------------------------
-    private String                                     id;
+    private String                                        id;
 
-    private int                                        workingMemoryCounter;
+    private AtomicInteger                                 workingMemoryCounter = new AtomicInteger(0);
 
-    private RuleBaseConfiguration                      config;
+    private RuleBaseConfiguration                         config;
 
-    protected Map<String, Package>                     pkgs;
+    protected Map<String, Package>                        pkgs;
 
-    private Map                                        processes;
+    private Map                                           processes;
 
-    private Map                                        agendaGroupRuleTotals;
+    private Map                                           agendaGroupRuleTotals;
 
-    private transient DroolsCompositeClassLoader       rootClassLoader;
+    private transient DroolsCompositeClassLoader          rootClassLoader;
 
     /**
      * The fact handle factory.
      */
-    private FactHandleFactory                          factHandleFactory;
+    private FactHandleFactory                             factHandleFactory;
 
-    private transient Map<String, Class< ? >>          globals;
+    private transient Map<String, Class< ? >>             globals;
 
-    private ReloadPackageCompilationData               reloadPackageCompilationData = null;
+    private final transient Queue<DialectRuntimeRegistry> reloadPackageCompilationData = new ConcurrentLinkedQueue<DialectRuntimeRegistry>();
 
-    private RuleBaseEventSupport                       eventSupport                 = new RuleBaseEventSupport( this );
+    private RuleBaseEventSupport                          eventSupport                 = new RuleBaseEventSupport( this );
 
-    private transient ObjectHashSet                    statefulSessions;
+    private transient ObjectHashSet                       statefulSessions;
 
     // lock for entire rulebase, used for dynamic updates
-    private final ReentrantReadWriteLock               lock                         = new ReentrantReadWriteLock();
+    private final ReentrantReadWriteLock                  lock                         = new ReentrantReadWriteLock();
 
     /**
      * This lock is used when adding to, or reading the <field>statefulSessions</field>
      */
-    private final ReentrantLock                        statefulSessionLock          = new ReentrantLock();
+    private final ReentrantLock                           statefulSessionLock          = new ReentrantLock();
 
-    private int                                        additionsSinceLock;
-    private int                                        removalsSinceLock;
+    private int                                           additionsSinceLock;
+    private int                                           removalsSinceLock;
 
-    private transient Map<Class< ? >, TypeDeclaration> classTypeDeclaration;
+    private transient Map<Class< ? >, TypeDeclaration>    classTypeDeclaration;
 
-    private List<RuleBasePartitionId>                  partitionIDs;
+    private List<RuleBasePartitionId>                     partitionIDs;
 
-    private ClassFieldAccessorCache                    classFieldAccessorCache;
+    private ClassFieldAccessorCache                       classFieldAccessorCache;
 
     /**
      * Default constructor - for Externalizable. This should never be used by a user, as it
@@ -125,12 +127,12 @@
 
     }
 
-    public synchronized int nextWorkingMemoryCounter() {
-        return this.workingMemoryCounter++;
+    public int nextWorkingMemoryCounter() {
+        return this.workingMemoryCounter.getAndIncrement();
     }
 
-    public synchronized long getWorkingMemoryCounter() {
-        return this.workingMemoryCounter;
+    public int getWorkingMemoryCounter() {
+        return this.workingMemoryCounter.get();
     }
 
     /**
@@ -159,7 +161,7 @@
         this.statefulSessions = new ObjectHashSet();
 
         this.classTypeDeclaration = new HashMap<Class< ? >, TypeDeclaration>();
-        this.partitionIDs = new ArrayList<RuleBasePartitionId>();
+        this.partitionIDs = new CopyOnWriteArrayList<RuleBasePartitionId>();
 
         this.classFieldAccessorCache = new ClassFieldAccessorCache( this.rootClassLoader );
     }
@@ -207,7 +209,7 @@
         // Rules must be restored by an ObjectInputStream that can resolve using a given ClassLoader to handle seaprately by storing as
         // a byte[]
         droolsStream.writeObject( this.id );
-        droolsStream.writeInt( this.workingMemoryCounter );
+        droolsStream.writeInt( this.workingMemoryCounter.get() );
         droolsStream.writeObject( this.processes );
         droolsStream.writeObject( this.agendaGroupRuleTotals );
         droolsStream.writeUTF( this.factHandleFactory.getClass().getName() );
@@ -271,7 +273,7 @@
 
         // PackageCompilationData must be restored before Rules as it has the ClassLoader needed to resolve the generated code references in Rules
         this.id = (String) droolsStream.readObject();
-        this.workingMemoryCounter = droolsStream.readInt();
+        this.workingMemoryCounter.set( droolsStream.readInt() );
 
         this.processes = (Map) droolsStream.readObject();
         this.agendaGroupRuleTotals = (Map) droolsStream.readObject();
@@ -330,6 +332,7 @@
      * @throws ClassNotFoundException
      */
     private void populateTypeDeclarationMaps() throws ClassNotFoundException {
+        // FIXME: readLock
         this.classTypeDeclaration = new HashMap<Class< ? >, TypeDeclaration>();
         for ( Package pkg : this.pkgs.values() ) {
             for ( TypeDeclaration type : pkg.getTypeDeclarations().values() ) {
@@ -390,13 +393,21 @@
     }
 
     public Process[] getProcesses() {
-        return (Process[]) this.processes.values().toArray( new Process[this.processes.size()] );
+        synchronized ( this.pkgs ) {
+            return (Process[]) this.processes.values().toArray( new Process[this.processes.size()] );
+        }
     }
 
     public Package[] getPackages() {
-        return this.pkgs.values().toArray( new Package[this.pkgs.size()] );
+        readLock();
+        try {
+            return this.pkgs.values().toArray( new Package[this.pkgs.size()] );
+        } finally {
+            readUnlock();
+        }
     }
 
+    // FIXME: this returns the live map!
     public Map<String, Package> getPackagesMap() {
         return this.pkgs;
     }
@@ -418,17 +429,30 @@
     }
 
     public void lock() {
-        this.additionsSinceLock = 0;
-        this.removalsSinceLock = 0;
-        this.eventSupport.fireBeforeRuleBaseLocked();
+        // The lock is reentrant, so we need additional magic here to skip
+        // notifications for locked if this thread already has locked it.
+        boolean firstLock = !this.lock.isWriteLockedByCurrentThread();
+        if ( firstLock ) {
+            this.eventSupport.fireBeforeRuleBaseLocked();
+        }
+        // Always lock to increase the counter
         this.lock.writeLock().lock();
-        this.eventSupport.fireAfterRuleBaseLocked();
+        if ( firstLock ) {
+            this.additionsSinceLock = 0;
+            this.removalsSinceLock = 0;
+            this.eventSupport.fireAfterRuleBaseLocked();
+        }        
     }
 
     public void unlock() {
-        this.eventSupport.fireBeforeRuleBaseUnlocked();
+        boolean lastUnlock = this.lock.getWriteHoldCount() == 1;
+        if ( lastUnlock ) {
+            this.eventSupport.fireBeforeRuleBaseUnlocked();
+        }
         this.lock.writeLock().unlock();
-        this.eventSupport.fireAfterRuleBaseUnlocked();
+        if ( lastUnlock ) {
+            this.eventSupport.fireAfterRuleBaseUnlocked();
+        }
     }
 
     public void readLock() {
@@ -448,8 +472,8 @@
      * @param newPkg The package to add.
      */
     public void addPackages(final Collection<Package> newPkgs) {
+        lock();
         try {
-            lock();
             // we need to merge all byte[] first, so that the root classloader can resolve classes
             for ( Package newPkg : newPkgs ) {
                 newPkg.checkValidity();
@@ -524,11 +548,11 @@
 
                 // add the flows to the RuleBase
                 if ( newPkg.getRuleFlows() != null ) {
-                    final Map flows = newPkg.getRuleFlows();
-                    for ( final Object object : flows.entrySet() ) {
-                        final Entry flow = (Entry) object;
-                        this.processes.put( flow.getKey(),
-                                            flow.getValue() );
+                    final Map<String, org.drools.definition.process.Process> flows = newPkg.getRuleFlows();
+                    for ( org.drools.definition.process.Process process : flows.values() ) {
+                        // XXX: is this cast safe?
+                        // XXX: we could take the lock inside addProcess() out, but OTOH: this is what the VM is supposed to do ...
+                        addProcess( (Process) process );
                     }
                 }
 
@@ -611,13 +635,6 @@
                 pkg.addProcess( flow );
             }
         }
-
-        //        // this handles re-wiring any dirty Packages, it's done lazily to allow incremental 
-        //        // additions without incurring the repeated cost.
-        //        if ( this.reloadPackageCompilationData == null ) {
-        //            this.reloadPackageCompilationData = new ReloadPackageCompilationData();
-        //        }
-        //        this.reloadPackageCompilationData.addDialectDatas( pkg.getDialectRuntimeRegistry() );
     }
 
     private static class TypeDeclarationCandidate {
@@ -634,7 +651,7 @@
             candidate = checkInterfaces( clazz,
                                          candidate,
                                          1 );
-            if( candidate != null ) {
+            if ( candidate != null ) {
                 typeDeclaration = candidate.candidate;
             }
         }
@@ -694,7 +711,8 @@
 
     public void addRule(final Package pkg,
                         final Rule rule) throws InvalidPatternException {
-        synchronized ( this.pkgs ) {
+        lock();
+        try {
             this.eventSupport.fireBeforeRuleAdded( pkg,
                                                    rule );
             //        if ( !rule.isValid() ) {
@@ -703,14 +721,22 @@
             addRule( rule );
             this.eventSupport.fireAfterRuleAdded( pkg,
                                                   rule );
+        } finally {
+            unlock();
         }
     }
 
+    /**
+     * This method is called with the rulebase lock held.
+     *
+     * @param rule
+     * @throws InvalidPatternException
+     */    
     protected abstract void addRule(final Rule rule) throws InvalidPatternException;
 
     public void removePackage(final String packageName) {
+        lock();
         try {
-            lock();
             final Package pkg = this.pkgs.get( packageName );
             if ( pkg == null ) {
                 throw new IllegalArgumentException( "Package name '" + packageName + "' does not exist for this Rule Base." );
@@ -727,16 +753,14 @@
             }
 
             // getting the list of referenced globals
-            final Set referencedGlobals = new HashSet();
-            for ( final Iterator it = this.pkgs.values().iterator(); it.hasNext(); ) {
-                final org.drools.rule.Package pkgref = (org.drools.rule.Package) it.next();
+            final Set<String> referencedGlobals = new HashSet<String>();
+            for ( Package pkgref : this.pkgs.values() ) {
                 if ( pkgref != pkg ) {
                     referencedGlobals.addAll( pkgref.getGlobals().keySet() );
                 }
             }
             // removing globals declared inside the package that are not shared
-            for ( final Iterator it = pkg.getGlobals().keySet().iterator(); it.hasNext(); ) {
-                final String globalName = (String) it.next();
+            for ( String globalName : pkg.getGlobals().keySet() ) {
                 if ( !referencedGlobals.contains( globalName ) ) {
                     this.globals.remove( globalName );
                 }
@@ -759,16 +783,17 @@
             unlock();
         }
     }
-    
+
     public void removeQuery(final String packageName,
-                           final String ruleName) {
-        removeRule(packageName, ruleName);
+                            final String ruleName) {
+        removeRule( packageName,
+                    ruleName );
     }
 
     public void removeRule(final String packageName,
                            final String ruleName) {
+        lock();
         try {
-            lock();
             final Package pkg = this.pkgs.get( packageName );
             if ( pkg == null ) {
                 throw new IllegalArgumentException( "Package name '" + packageName + "' does not exist for this Rule Base." );
@@ -784,19 +809,23 @@
             removeRule( pkg,
                         rule );
             pkg.removeRule( rule );
-            if ( this.reloadPackageCompilationData == null ) {
-                this.reloadPackageCompilationData = new ReloadPackageCompilationData();
-            }
-            this.reloadPackageCompilationData.addDialectDatas( pkg.getDialectRuntimeRegistry() );
+            addReloadDialectDatas( pkg.getDialectRuntimeRegistry() );
         } finally {
             unlock();
         }
     }
 
+    /**
+     * Notify listeners and sub-classes about imminent removal of a rule from a package.
+     *
+     * @param pkg
+     * @param rule
+     */
+    // FIXME: removeRule(String, String) and removeRule(Package, Rule) do totally different things!
     public void removeRule(final Package pkg,
                            final Rule rule) {
+        lock();
         try {
-            lock();
             this.eventSupport.fireBeforeRuleRemoved( pkg,
                                                      rule );
             removeRule( rule );
@@ -807,60 +836,103 @@
         }
     }
 
+    /**
+     * Handle rule removal.
+     *
+     * This method is intended for sub-classes, and called after the 
+     * {@link RuleBaseEventListener#beforeRuleRemoved(org.drools.event.BeforeRuleRemovedEvent) before-rule-removed} 
+     * event is fired, and before the rule is physically removed from the package.
+     *
+     * This method is called with the rulebase lock held.
+     * @param rule
+     */
     protected abstract void removeRule(Rule rule);
 
     public void removeFunction(final String packageName,
                                final String functionName) {
-        synchronized ( this.pkgs ) {
+        lock();
+        try {
             final Package pkg = this.pkgs.get( packageName );
             if ( pkg == null ) {
                 throw new IllegalArgumentException( "Package name '" + packageName + "' does not exist for this Rule Base." );
             }
 
-            this.eventSupport.fireBeforeFunctionRemoved( pkg,
-                                                         functionName );
-
             if ( !pkg.getFunctions().containsKey( functionName ) ) {
                 throw new IllegalArgumentException( "function name '" + packageName + "' does not exist in the Package '" + packageName + "'." );
             }
 
+            removeFunction( pkg,
+                            functionName );
             pkg.removeFunction( functionName );
 
-            if ( this.reloadPackageCompilationData == null ) {
-                this.reloadPackageCompilationData = new ReloadPackageCompilationData();
-            }
-            this.reloadPackageCompilationData.addDialectDatas( pkg.getDialectRuntimeRegistry() );
-
-            this.eventSupport.fireAfterFunctionRemoved( pkg,
-                                                        functionName );
+            addReloadDialectDatas( pkg.getDialectRuntimeRegistry() );
+        } finally {
+            unlock();
         }
     }
 
+    /**
+     * Handle function removal.
+     *
+     * This method is intended for sub-classes, and called after the 
+     * {@link RuleBaseEventListener#beforeFunctionRemoved(org.drools.event.BeforeFunctionRemovedEvent) before-function-removed} 
+     * event is fired, and before the function is physically removed from the package.
+     *
+     * This method is called with the rulebase lock held.
+     * @param rule
+     */
+    protected /* abstract */ void removeFunction( String functionName ) {
+        // Nothing in default.
+    }
+
+    /**
+     * Notify listeners and sub-classes about imminent removal of a function from a package.
+     *
+     * This method is called with the rulebase lock held.
+     * @param pkg
+     * @param rule
+     */
+    private void removeFunction (final Package pkg,
+                                 final String functionName) {
+        this.eventSupport.fireBeforeFunctionRemoved( pkg,
+                                                     functionName );
+        removeFunction(functionName);
+        this.eventSupport.fireAfterFunctionRemoved( pkg,
+                                                    functionName );
+    }
+    
     public void addProcess(final Process process) {
-        synchronized ( this.pkgs ) {
+        // XXX: could use a synchronized(processes) here.
+        lock();
+        try {
             this.processes.put( process.getId(),
                                 process );
+        } finally {
+            unlock();
         }
 
     }
 
     public void removeProcess(final String id) {
-        synchronized ( this.pkgs ) {
+        lock();
+        try {
             this.processes.remove( id );
+        } finally {
+            unlock();
         }
     }
 
     public Process getProcess(final String id) {
-        Process process;
-        synchronized ( this.pkgs ) {
-            process = (Process) this.processes.get( id );
+        readLock();
+        try {
+            return (Process) this.processes.get( id );
+        } finally {
+            readUnlock();
         }
-        return process;
     }
 
     public void addStatefulSession(final StatefulSession statefulSession) {
         statefulSessionLock.lock();
-
         try {
             this.statefulSessions.add( statefulSession );
         } finally {
@@ -870,7 +942,12 @@
     }
 
     public Package getPackage(final String name) {
-        return this.pkgs.get( name );
+        readLock();
+        try {
+            return this.pkgs.get( name );
+        } finally {
+            readUnlock();
+        }
     }
 
     public StatefulSession[] getStatefulSessions() {
@@ -904,11 +981,9 @@
     }
 
     public void executeQueuedActions() {
-        synchronized ( this.pkgs ) {
-            if ( this.reloadPackageCompilationData != null ) {
-                this.reloadPackageCompilationData.execute( this );
-                this.reloadPackageCompilationData = null;
-            }
+        DialectRuntimeRegistry registry;
+        while ( (registry = reloadPackageCompilationData.poll()) != null ) {
+            registry.onBeforeExecute();
         }
     }
 
@@ -922,7 +997,8 @@
     }
 
     public List<RuleBasePartitionId> getPartitionIds() {
-        return this.partitionIDs;
+        // this returns an unmodifiable CopyOnWriteArrayList, so should be safe for concurrency
+        return Collections.unmodifiableList( this.partitionIDs );
     }
 
     public void addEventListener(final RuleBaseEventListener listener) {
@@ -940,52 +1016,37 @@
         return this.eventSupport.getEventListeners();
     }
 
-    public boolean isEvent(Class clazz) {
-        for ( Package pkg : this.pkgs.values() ) {
-            if ( pkg.isEvent( clazz ) ) {
-                return true;
+    public boolean isEvent(Class<?> clazz) {
+        readLock();
+        try {
+            for ( Package pkg : this.pkgs.values() ) {
+                if ( pkg.isEvent( clazz ) ) {
+                    return true;
+                }
             }
+            return false;
+        } finally {
+            readUnlock();
         }
-        return false;
     }
 
     public FactType getFactType(final String name) {
-        for ( Package pkg : this.pkgs.values() ) {
-            FactType type = pkg.getFactType( name );
-            if ( type != null ) {
-                return type;
+        readLock();
+        try {
+            for ( Package pkg : this.pkgs.values() ) {
+                FactType type = pkg.getFactType( name );
+                if ( type != null ) {
+                    return type;
+                }
             }
+            return null;
+        } finally {
+            readUnlock();
         }
-        return null;
     }
 
-    public static class ReloadPackageCompilationData
-        implements
-        RuleBaseAction {
-        private static final long           serialVersionUID = 510l;
-        private Set<DialectRuntimeRegistry> set;
-
-        public void readExternal(ObjectInput in) throws IOException,
-                                                ClassNotFoundException {
-            set = (Set<DialectRuntimeRegistry>) in.readObject();
-        }
-
-        public void writeExternal(ObjectOutput out) throws IOException {
-            out.writeObject( set );
-        }
-
-        public void addDialectDatas(final DialectRuntimeRegistry registry) {
-            if ( this.set == null ) {
-                this.set = new HashSet<DialectRuntimeRegistry>();
-            }
-            if ( !this.set.contains( registry ) ) this.set.add( registry );
-        }
-
-        public void execute(final InternalRuleBase ruleBase) {
-            for ( final DialectRuntimeRegistry registry : this.set ) {
-                registry.onBeforeExecute();
-            }
-        }
+    private void addReloadDialectDatas(DialectRuntimeRegistry registry) {
+        this.reloadPackageCompilationData.offer( registry );
     }
 
     public static interface RuleBaseAction

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java	2010-07-30 01:59:52 UTC (rev 34381)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/impl/StatelessKnowledgeSessionImpl.java	2010-07-30 02:00:34 UTC (rev 34382)
@@ -88,10 +88,14 @@
         this.environment = EnvironmentFactory.newEnvironment();
 
         if ( this.ruleBase != null ) {
-            synchronized ( this.ruleBase.getPackagesMap() ) {
+            // FIXME: this same code exists in ReteooRuleBase#newStatelessSession()
+            this.ruleBase.lock();
+            try {
                 if ( ruleBase.getConfiguration().isSequential() ) {
                     this.ruleBase.getReteooBuilder().order();
                 }
+            } finally {
+                this.ruleBase.unlock();
             }
         }
     }
@@ -113,7 +117,8 @@
             // if we have an agent always get the rulebase from there
             this.ruleBase = (InternalRuleBase) ((KnowledgeBaseImpl) this.kagent.getKnowledgeBase()).ruleBase;
         }
-        synchronized ( this.ruleBase.getPackagesMap() ) {
+        this.ruleBase.readLock();
+        try {
             ReteooWorkingMemory wm = new ReteooWorkingMemory( this.ruleBase.nextWorkingMemoryCounter(),
                                                               this.ruleBase,
                                                               (SessionConfiguration) this.conf,
@@ -142,6 +147,8 @@
                                                                             null,
                                                                             null ) );
             return ksession;
+        } finally {
+            this.ruleBase.readUnlock();
         }
     }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java	2010-07-30 01:59:52 UTC (rev 34381)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooBuilder.java	2010-07-30 02:00:34 UTC (rev 34382)
@@ -113,7 +113,7 @@
      *             the <code>Rule</code>.
      * @throws InvalidPatternException
      */
-    void addRule(final Rule rule) throws InvalidPatternException {
+    synchronized void addRule(final Rule rule) throws InvalidPatternException {
         final List<TerminalNode> terminals = this.ruleBuilder.addRule( rule,
                                                                        this.ruleBase,
                                                                        this.idGenerator );
@@ -130,7 +130,7 @@
         this.ordered = ordered;
     }
 
-    public void order() {
+    public synchronized void order() {
         if ( ordered ) {
             // we should only do this on first call, its expected the RuleBase should not change afterwards.
             return;
@@ -220,11 +220,11 @@
 
     }
 
-    public BaseNode[] getTerminalNodes(final Rule rule) {
+    public synchronized BaseNode[] getTerminalNodes(final Rule rule) {
         return this.rules.get( rule );
     }
 
-    public void removeRule(final Rule rule) {
+    public synchronized void removeRule(final Rule rule) {
         // reset working memories for potential propagation
         InternalWorkingMemory[] workingMemories = this.ruleBase.getWorkingMemories();
 
@@ -270,12 +270,12 @@
             out.writeInt( nextId );
         }
 
-        public int getNextId() {
+        public synchronized int getNextId() {
             Integer id = this.recycledIds.poll();
             return ( id == null ) ? this.nextId++ : id.intValue();
         }
 
-        public void releaseId(int id) {
+        public synchronized void releaseId(int id) {
             this.recycledIds.add( id );
         }
 

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java	2010-07-30 01:59:52 UTC (rev 34381)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooRuleBase.java	2010-07-30 02:00:34 UTC (rev 34382)
@@ -38,10 +38,9 @@
 import java.io.ObjectInput;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutput;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.List;
+import java.util.Collections;
 
 import org.drools.FactException;
 import org.drools.FactHandle;
@@ -319,7 +318,8 @@
                                               boolean keepReference) {
         StatefulSession session = null;
         try {
-            synchronized ( this.pkgs ) {
+            readLock();
+            try {
                 // first unwrap the byte[]
                 ObjectInputStream ois = new ObjectInputStream( stream );
     
@@ -343,6 +343,8 @@
                 }
     
                 bais.close();
+            } finally {
+                readUnlock();
             }
 
         } catch ( Exception e ) {
@@ -377,15 +379,15 @@
         if ( this.getConfig().isSequential() ) {
             throw new RuntimeException( "Cannot have a stateful rule session, with sequential configuration set to true" );
         }
-        ReteooStatefulSession session  ;
 
-        synchronized ( this.pkgs ) {
-            ExecutorService executor = ExecutorServiceFactory.createExecutorService( this.getConfig().getExecutorService() );
-            session = new ReteooStatefulSession( id,
-                                                 this,
-                                                 executor,
-                                                 sessionConfig,
-                                                 environment );
+        ExecutorService executor = ExecutorServiceFactory.createExecutorService( this.getConfig().getExecutorService() );
+        readLock();
+        try {
+            ReteooStatefulSession session = new ReteooStatefulSession( id,
+                                                                       this,
+                                                                       executor,
+                                                                       sessionConfig,
+                                                                       environment );
 
             executor.setCommandExecutor( new CommandExecutor( session ) );
 
@@ -403,9 +405,10 @@
                                                                                  true,
                                                                                  null,
                                                                                  null ) );
+            return session;
+        } finally {
+            readUnlock();
         }
-
-        return session;
     }
 
     public StatelessSession newStatelessSession() {
@@ -420,12 +423,12 @@
         }
     }
 
-    protected synchronized void addRule(final Rule rule) throws InvalidPatternException {
+    protected void addRule(final Rule rule) throws InvalidPatternException {
         // This adds the rule. ReteBuilder has a reference to the WorkingMemories and will propagate any existing facts.
         this.reteooBuilder.addRule( rule );
     }
 
-    protected synchronized void removeRule(final Rule rule) {
+    protected void removeRule(final Rule rule) {
         this.reteooBuilder.removeRule( rule );
     }
 
@@ -446,11 +449,6 @@
     }
 
     public void addPackage(final Package newPkg) {
-        List<Package> list = new ArrayList<Package>();
-        list.add( newPkg );
-        super.addPackages( list );
-        if ( this.getConfig().isSequential() ) {
-            this.reteooBuilder.setOrdered( false );
-        }
+        addPackages( Collections.singleton( newPkg ) );
     }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooStatelessSession.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooStatelessSession.java	2010-07-30 01:59:52 UTC (rev 34381)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/ReteooStatelessSession.java	2010-07-30 02:00:34 UTC (rev 34382)
@@ -105,7 +105,8 @@
     }
 
     public InternalWorkingMemory newWorkingMemory() {
-        synchronized ( this.ruleBase.getPackagesMap() ) {
+        this.ruleBase.readLock();
+        try {
             InternalWorkingMemory wm = new ReteooWorkingMemory( this.ruleBase.nextWorkingMemoryCounter(),
                                                                 this.ruleBase,
                                                                 this.sessionConf,
@@ -128,6 +129,8 @@
                                                                             null,
                                                                             null ) );
             return wm;
+        } finally {
+            this.ruleBase.readUnlock();
         }
     }
     

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java	2010-07-30 01:59:52 UTC (rev 34381)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/reteoo/builder/PatternBuilder.java	2010-07-30 02:00:34 UTC (rev 34382)
@@ -25,6 +25,7 @@
 import org.drools.base.ClassObjectType;
 import org.drools.base.DroolsQuery;
 import org.drools.common.InstanceNotEqualsConstraint;
+import org.drools.common.InternalRuleBase;
 import org.drools.common.InternalWorkingMemory;
 import org.drools.conf.EventProcessingOption;
 import org.drools.reteoo.AlphaNode;
@@ -226,13 +227,15 @@
 
     public static ObjectTypeNode attachObjectTypeNode(BuildContext context,
                                                       ObjectType objectType) {
-        synchronized ( context.getRuleBase().getPackagesMap() ) {
+        final InternalRuleBase ruleBase = context.getRuleBase();
+        ruleBase.readLock();
+        try {
             InternalWorkingMemory[] wms = context.getWorkingMemories();
 
-            EntryPointNode epn = context.getRuleBase().getRete().getEntryPointNode( context.getCurrentEntryPoint() );
+            EntryPointNode epn = ruleBase.getRete().getEntryPointNode( context.getCurrentEntryPoint() );
             if ( epn == null ) {
                 epn = new EntryPointNode( context.getNextId(),
-                                          context.getRuleBase().getRete(),
+                                          ruleBase.getRete(),
                                           context );
                 if ( wms.length > 0 ) {
                     epn.attach( wms );
@@ -257,6 +260,8 @@
             }
 
             return otn;
+        } finally {
+            ruleBase.readUnlock();
         }
     }
 



More information about the jboss-svn-commits mailing list