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

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Aug 19 01:05:13 EDT 2008


Author: mark.proctor at jboss.com
Date: 2008-08-19 01:05:09 -0400 (Tue, 19 Aug 2008)
New Revision: 21619

Added:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/StatefulSessionSnapshotter.java
   labs/jbossrules/trunk/drools-core/src/test/java/org/drools/persistence/memory/MemoryPersistenceSessionTest.java
Modified:
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/DefaultMarshaller.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/Marshaller.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/DroolsXid.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryPersistenceManager.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryXaResource.java
   labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/ObjectHashMap.java
Log:
JBRULES-1738 Support XAResource transactions and generic save points
JBRULES-1739 in-memory XAResource
-MemoryPersistenceManager now works with sessions

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/DefaultMarshaller.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/DefaultMarshaller.java	2008-08-19 03:50:43 UTC (rev 21618)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/DefaultMarshaller.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -16,7 +16,7 @@
     implements
     Marshaller {
     GlobalResolver                     globalResolver;
-    private RuleBaseConfiguration      config;
+    RuleBaseConfiguration              config;
     PlaceholderResolverStrategyFactory factory;
 
     public DefaultMarshaller() {
@@ -63,16 +63,16 @@
 
     }
 
-    public ReteooStatefulSession read(final InputStream stream,
-                                      final InternalRuleBase ruleBase,
-                                      ReteooStatefulSession session) throws IOException,
-                                                                    ClassNotFoundException {
+    public StatefulSession read(final InputStream stream,
+                                final InternalRuleBase ruleBase,
+                                StatefulSession session) throws IOException,
+                                                        ClassNotFoundException {
         MarshallerReaderContext context = new MarshallerReaderContext( stream,
                                                                        ruleBase,
                                                                        RuleBaseNodes.getNodeMap( ruleBase ),
                                                                        factory );
 
-        session = InputMarshaller.readSession( session,
+        session = InputMarshaller.readSession( (ReteooStatefulSession) session,
                                                context );
         context.close();
         return session;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/Marshaller.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/Marshaller.java	2008-08-19 03:50:43 UTC (rev 21618)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/marshalling/Marshaller.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -11,12 +11,17 @@
 
 public interface Marshaller {
 
-    public abstract ReteooStatefulSession read(final InputStream stream,
-                                               final InternalRuleBase ruleBase,
-                                               final int id,
-                                               final ExecutorService executor) throws IOException,
-                                                                              ClassNotFoundException;
+    public StatefulSession read(final InputStream stream,
+                                final InternalRuleBase ruleBase,
+                                final int id,
+                                final ExecutorService executor) throws IOException,
+                                                               ClassNotFoundException;
 
+    public StatefulSession read(final InputStream stream,
+                                final InternalRuleBase ruleBase,
+                                final StatefulSession session) throws IOException,
+                                                              ClassNotFoundException;
+
     public abstract void write(final OutputStream stream,
                                final InternalRuleBase ruleBase,
                                final StatefulSession session) throws IOException;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/DroolsXid.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/DroolsXid.java	2008-08-19 03:50:43 UTC (rev 21618)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/DroolsXid.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -35,5 +35,4 @@
         {
             return gtrid;
         }
-
     }

Added: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/StatefulSessionSnapshotter.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/StatefulSessionSnapshotter.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/StatefulSessionSnapshotter.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -0,0 +1,40 @@
+package org.drools.persistence;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import org.drools.StatefulSession;
+import org.drools.common.InternalRuleBase;
+import org.drools.marshalling.DefaultMarshaller;
+import org.drools.marshalling.Marshaller;
+
+public class StatefulSessionSnapshotter implements ByteArraySnapshotter{
+	StatefulSession session;
+    Marshaller marshaller = new DefaultMarshaller();
+	
+	public StatefulSessionSnapshotter(StatefulSession session) {
+		this.session = session;
+	}
+
+	public byte[] getSnapshot() {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try {
+            marshaller.write( baos, (InternalRuleBase) session.getRuleBase(), session );
+        } catch (IOException e) {
+        	throw new RuntimeException( "Unable to get session snapshot", e );
+        }
+        
+        return baos.toByteArray();
+	}
+
+	public void loadSnapshot(byte[] bytes) {
+        ByteArrayInputStream bais = new ByteArrayInputStream( bytes );
+        try {
+            marshaller.read( bais, (InternalRuleBase) session.getRuleBase(), session );
+        } catch (Exception e) {
+        	throw new RuntimeException( "Unable to load session snapshot", e );
+        }
+		
+	}
+}

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryPersistenceManager.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryPersistenceManager.java	2008-08-19 03:50:43 UTC (rev 21618)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryPersistenceManager.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -1,60 +1,123 @@
 package org.drools.persistence.memory;
 
+import java.net.Inet4Address;
+import java.util.Random;
+
+import javax.transaction.xa.Xid;
+
 import org.drools.persistence.ByteArraySnapshotter;
+import org.drools.persistence.DroolsXid;
 import org.drools.persistence.PersistenceManager;
 import org.drools.persistence.Transaction;
 
-public class MemoryPersistenceManager implements ByteArraySnapshotter, PersistenceManager {  
-    ByteArraySnapshotter snapshotter;
-    byte[] lastSave;  
-    MemoryXaResource xaResource;
-	
-	public MemoryPersistenceManager(ByteArraySnapshotter snapshotter) {
-		this.snapshotter = snapshotter;
-	}
-	
-	public MemoryXaResource getXAResource() {
-		if ( xaResource == null ) {
-			xaResource = new MemoryXaResource( this );
-		}
-		return xaResource;
-	}
-	
-	public Transaction getTransaction() {
-		return new Transaction( null, getXAResource() );
-	}
-	
-	public void save() {
-		if ( xaResource != null && xaResource.isInTransaction() ) {
-			throw new RuntimeException("You cannot call a persistence save point while a transaction is open" );
-		}
-		lastSave = getSnapshot();
-	}
+public class MemoryPersistenceManager
+    implements
+    ByteArraySnapshotter,
+    PersistenceManager {
+    ByteArraySnapshotter  snapshotter;
+    byte[]                lastSave;
+    MemoryXaResource      xaResource;
 
-	public void load() {
-		if ( xaResource != null && xaResource.isInTransaction() ) {
-			throw new RuntimeException("You cannot call a persistence save point while a transaction is open" );
-		}		
-		loadSnapshot( lastSave );
-	}
-	
-	public boolean isInTransaction() {
-		return false;
-	}
-	
-	public void setLastSave(byte[] lastSave) {
-		this.lastSave = lastSave;
-	}
-	
-	public byte[] getLastSave() {
-		return lastSave;
-	}
-	
+    public MemoryPersistenceManager(ByteArraySnapshotter snapshotter) {
+        this.snapshotter = snapshotter;
+    }
+
+    public MemoryXaResource getXAResource() {
+        if ( xaResource == null ) {
+            xaResource = new MemoryXaResource( this );
+        }
+        return xaResource;
+    }
+
+    public Transaction getTransaction() {
+        return new Transaction( getUniqueXID(),
+                                getXAResource() );
+    }
+
+    public void save() {
+        if ( xaResource != null && xaResource.isInTransaction() ) {
+            throw new RuntimeException( "You cannot call a persistence save point while a transaction is open" );
+        }
+        lastSave = getSnapshot();
+    }
+
+    public void load() {
+        if ( xaResource != null && xaResource.isInTransaction() ) {
+            throw new RuntimeException( "You cannot call a persistence save point while a transaction is open" );
+        }
+        loadSnapshot( lastSave );
+    }
+
+    public boolean isInTransaction() {
+        return false;
+    }
+
+    public void setLastSave(byte[] lastSave) {
+        this.lastSave = lastSave;
+    }
+
+    public byte[] getLastSave() {
+        return lastSave;
+    }
+
     public byte[] getSnapshot() {
-    	return snapshotter.getSnapshot();
+        return snapshotter.getSnapshot();
     }
-    
+
     public void loadSnapshot(byte[] bytes) {
-    	this.snapshotter.loadSnapshot( bytes );
+        this.snapshotter.loadSnapshot( bytes );
     }
+
+    byte[]      localIP     = null;
+    private int txnUniqueID = 0;
+    private int tid         = 1;
+
+    private Xid getUniqueXID() {
+        Random rnd = new Random( System.currentTimeMillis() );
+        txnUniqueID++;
+        int txnUID = txnUniqueID;
+        int tidID = tid;
+        int randID = rnd.nextInt();
+        byte[] gtrid = new byte[64];
+        byte[] bqual = new byte[64];
+
+        if ( null == localIP ) {
+            try {
+                localIP = Inet4Address.getLocalHost().getAddress();
+            } catch ( Exception ex ) {
+                localIP = new byte[]{0x01, 0x02, 0x03, 0x04};
+            }
+        }
+
+        System.arraycopy( localIP,
+                          0,
+                          gtrid,
+                          0,
+                          4 );
+        System.arraycopy( localIP,
+                          0,
+                          bqual,
+                          0,
+                          4 );
+
+        // Bytes 4 -> 7 - unique transaction id (unique to our class instance).          
+        // Bytes 8 ->11 - thread id (unique to our thread).
+        // Bytes 12->15 - random number generated using seed from current time in milliseconds.
+        for ( int i = 0; i <= 3; i++ ) {
+            gtrid[i + 4] = (byte) (txnUID % 0x100);
+            bqual[i + 4] = (byte) (txnUID % 0x100);
+            txnUID >>= 8;
+            gtrid[i + 8] = (byte) (tidID % 0x100);
+            bqual[i + 8] = (byte) (tidID % 0x100);
+            tidID >>= 8;
+            gtrid[i + 12] = (byte) (randID % 0x100);
+            bqual[i + 12] = (byte) (randID % 0x100);
+            randID >>= 8;
+        }
+
+        return new DroolsXid( 0x1234,
+                              gtrid,
+                              bqual );
+
+    }
 }

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryXaResource.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryXaResource.java	2008-08-19 03:50:43 UTC (rev 21618)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/persistence/memory/MemoryXaResource.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -14,7 +14,7 @@
     private MemoryPersistenceManager pm;
     
     Map<Xid, byte[]> data = new HashMap<Xid, byte[]>();
-    LinkedList<Xid> list = new LinkedList<Xid>();      
+    LinkedList<Xid> list = new LinkedList<Xid>();       
 
     public MemoryXaResource(MemoryPersistenceManager pm) {
         this.pm = pm;

Modified: labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/ObjectHashMap.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/ObjectHashMap.java	2008-08-19 03:50:43 UTC (rev 21618)
+++ labs/jbossrules/trunk/drools-core/src/main/java/org/drools/util/ObjectHashMap.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -45,6 +45,7 @@
         this.table = new Entry[Math.min( this.table.length,
                                          16 )];
         this.threshold = (int) (this.table.length * this.loadFactor);
+        size = 0;
     }
 
     public Object put(final Object key,

Added: labs/jbossrules/trunk/drools-core/src/test/java/org/drools/persistence/memory/MemoryPersistenceSessionTest.java
===================================================================
--- labs/jbossrules/trunk/drools-core/src/test/java/org/drools/persistence/memory/MemoryPersistenceSessionTest.java	                        (rev 0)
+++ labs/jbossrules/trunk/drools-core/src/test/java/org/drools/persistence/memory/MemoryPersistenceSessionTest.java	2008-08-19 05:05:09 UTC (rev 21619)
@@ -0,0 +1,237 @@
+package org.drools.persistence.memory;
+
+import java.beans.IntrospectionException;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.drools.Person;
+import org.drools.RuleBase;
+import org.drools.RuleBaseFactory;
+import org.drools.StatefulSession;
+import org.drools.WorkingMemory;
+import org.drools.base.ClassFieldAccessorCache;
+import org.drools.base.ClassFieldAccessorStore;
+import org.drools.base.ClassObjectType;
+import org.drools.base.ValueType;
+import org.drools.base.evaluators.EqualityEvaluatorsDefinition;
+import org.drools.base.evaluators.Operator;
+import org.drools.common.InternalWorkingMemory;
+import org.drools.examples.manners.Context;
+import org.drools.examples.manners.Count;
+import org.drools.examples.manners.Guest;
+import org.drools.examples.manners.Path;
+import org.drools.examples.manners.Seating;
+import org.drools.persistence.DroolsXid;
+import org.drools.persistence.StatefulSessionSnapshotter;
+import org.drools.persistence.Transaction;
+import org.drools.persistence.memory.MemoryPersistenceManager;
+import org.drools.persistence.memory.MemoryXaResource;
+import org.drools.rule.Declaration;
+import org.drools.rule.InvalidRuleException;
+import org.drools.rule.Pattern;
+import org.drools.rule.Package;
+import org.drools.rule.Rule;
+import org.drools.rule.VariableConstraint;
+import org.drools.spi.BetaNodeFieldConstraint;
+import org.drools.spi.Consequence;
+import org.drools.spi.ConsequenceException;
+import org.drools.spi.Evaluator;
+import org.drools.spi.InternalReadAccessor;
+import org.drools.spi.KnowledgeHelper;
+import org.drools.spi.Tuple;
+import org.drools.transaction.MockByteArraySnapshotter;
+
+import junit.framework.TestCase;
+
+public class MemoryPersistenceSessionTest extends TestCase {
+    private byte[]          data1 = new byte[]{1, 1, 1, 1, 1};
+    private byte[]          data2 = new byte[]{1, 1, 1, 1, 0};
+    private byte[]          data3 = new byte[]{1, 1, 1, 0, 0};
+
+    ClassFieldAccessorStore store;
+
+    public void testSave() throws Exception {
+        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        Package pkg = new Package( "org.drools.test" );
+        pkg.addGlobal( "list", List.class );
+        pkg.setClassFieldAccessorCache( new ClassFieldAccessorCache( Thread.currentThread().getContextClassLoader() ) );
+        store = pkg.getClassFieldAccessorStore();
+        store.setEagerWire( true );
+        
+        pkg.addRule( getFindPersonRule() );        
+        ruleBase.addPackage( pkg );
+        
+
+        StatefulSession session = ruleBase.newStatefulSession();
+        List list = new ArrayList();
+        session.setGlobal( "list", list );
+        Person p1 = new Person("boba fet", 500);
+        session.insert( p1 );
+        
+        MemoryPersistenceManager pm = new MemoryPersistenceManager( new StatefulSessionSnapshotter( session ) );
+        pm.save();
+        
+        
+        Person p2 = new Person("boba fet", 500);
+        Person p3 = new Person("boba fet", 500);
+        session.insert( p2 );
+        session.insert( p3 );        
+        session.insert( new String( "boba fet" ) );
+        assertEquals( 4, ((InternalWorkingMemory)session).getObjectStore().size() );
+        session.fireAllRules();        
+        assertEquals(3, list.size() );        
+        
+        pm.load();
+        list.clear();
+        session.insert( new String( "boba fet" ) );
+        session.fireAllRules();        
+        assertEquals( 1, list.size() );             
+        assertEquals( 2, ((InternalWorkingMemory)session).getObjectStore().size() );
+    }
+    
+    public void testTransactionWithRollback() throws Exception {
+        RuleBase ruleBase = RuleBaseFactory.newRuleBase();
+        Package pkg = new Package( "org.drools.test" );
+        pkg.addGlobal( "list", List.class );
+        pkg.setClassFieldAccessorCache( new ClassFieldAccessorCache( Thread.currentThread().getContextClassLoader() ) );
+        store = pkg.getClassFieldAccessorStore();
+        store.setEagerWire( true );
+        
+        pkg.addRule( getFindPersonRule() );        
+        ruleBase.addPackage( pkg );
+        
+
+        StatefulSession session = ruleBase.newStatefulSession();
+        List list = new ArrayList();
+        session.setGlobal( "list", list );
+        Person p1 = new Person("boba fet", 500);
+        session.insert( p1 );
+        
+        MemoryPersistenceManager pm = new MemoryPersistenceManager( new StatefulSessionSnapshotter( session ) );
+        Transaction t = pm.getTransaction();
+        t.start();
+        
+        
+        Person p2 = new Person("boba fet", 500);
+        Person p3 = new Person("boba fet", 500);
+        session.insert( p2 );
+        session.insert( p3 );        
+        session.insert( new String( "boba fet" ) );
+        assertEquals( 4, ((InternalWorkingMemory)session).getObjectStore().size() );
+        session.fireAllRules();        
+        assertEquals(3, list.size() );        
+        
+        t.rollback();
+        list.clear();
+        session.insert( new String( "boba fet" ) );
+        session.fireAllRules();        
+        assertEquals( 1, list.size() );             
+        assertEquals( 2, ((InternalWorkingMemory)session).getObjectStore().size() );
+    }    
+
+    private Rule getFindPersonRule() throws IntrospectionException,
+                                    InvalidRuleException {
+        ClassObjectType stringType = new ClassObjectType( String.class );
+        ClassObjectType personType = new ClassObjectType( Person.class );
+
+        final Rule rule = new Rule( "find person" );
+
+        // -----------
+        // $s : String( )
+        // -----------
+        final Pattern stringPattern = new Pattern( 0,
+                                                   stringType,
+                                                   "$s" );
+        rule.addPattern( stringPattern );
+        final Declaration sDeclaration = rule.getDeclaration( "$s" );
+
+        // -----------
+        // $p : Person( name == $s)
+        // -----------
+        final Pattern personPattern = new Pattern( 1,
+                                                   personType,
+                                                   "$p" );
+        EqualityEvaluatorsDefinition evals = new EqualityEvaluatorsDefinition();
+        Evaluator eval = evals.getEvaluator( ValueType.OBJECT_TYPE,
+                                             Operator.EQUAL,
+                                             null );
+        personPattern.addConstraint( getBoundVariableConstraint( personPattern,
+                                                                 "name",
+                                                                 sDeclaration,
+                                                                 eval ) );
+
+        rule.addPattern( personPattern );
+
+        final Declaration pDeclaration = rule.getDeclaration( "$p" );
+
+        final Consequence consequence = new Consequence() {
+
+            public void evaluate(KnowledgeHelper drools,
+                                 WorkingMemory workingMemory) throws ConsequenceException {
+                try {
+                    Rule rule = drools.getRule();
+                    Tuple tuple = drools.getTuple();
+
+                    Person p = (Person) drools.get( pDeclaration );
+
+                    List list = (List) workingMemory.getGlobal( "list" );
+                    list.add( p );
+
+                } catch ( Exception e ) {
+                    e.printStackTrace();
+                    throw new ConsequenceException( e );
+                }
+            }
+
+            public void readExternal(ObjectInput in) throws IOException,
+                                                    ClassNotFoundException {
+
+            }
+
+            public void writeExternal(ObjectOutput out) throws IOException {
+
+            }
+        };
+
+        rule.setConsequence( consequence );
+
+        return rule;
+    }
+
+    public boolean assertEquals(byte[] bytes1,
+                                byte[] bytes2) {
+        if ( bytes1.length != bytes2.length ) {
+            return false;
+        }
+
+        for ( int i = 0; i < bytes1.length; i++ ) {
+            if ( bytes1[i] != bytes2[i] ) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private BetaNodeFieldConstraint getBoundVariableConstraint(final Pattern pattern,
+                                                               final String fieldName,
+                                                               final Declaration declaration,
+                                                               final Evaluator evaluator) throws IntrospectionException {
+        final Class clazz = ((ClassObjectType) pattern.getObjectType()).getClassType();
+
+        final InternalReadAccessor extractor = store.getReader( clazz,
+                                                                fieldName,
+                                                                getClass().getClassLoader() );
+
+        return new VariableConstraint( extractor,
+                                       declaration,
+                                       evaluator );
+    }
+}




More information about the jboss-svn-commits mailing list