[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