[jboss-svn-commits] JBL Code SVN: r32671 - in labs/jbosstm/workspace/hornetq_txlog: src and 11 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Apr 28 08:44:38 EDT 2010


Author: jhalliday
Date: 2010-04-28 08:44:37 -0400 (Wed, 28 Apr 2010)
New Revision: 32671

Added:
   labs/jbosstm/workspace/hornetq_txlog/README.txt
   labs/jbosstm/workspace/hornetq_txlog/build.xml
   labs/jbosstm/workspace/hornetq_txlog/src/
   labs/jbosstm/workspace/hornetq_txlog/src/org/
   labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/
   labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/
   labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/
   labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalEnvironmentBean.java
   labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalTxLog.java
   labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqObjectStoreAdaptor.java
   labs/jbosstm/workspace/hornetq_txlog/tests/
   labs/jbosstm/workspace/hornetq_txlog/tests/src/
   labs/jbosstm/workspace/hornetq_txlog/tests/src/org/
   labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/
   labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/
   labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/
   labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/
   labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/Test.java
   labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/XAResourceImpl.java
Log:
Added prototype HornetQ journal based objectstore.


Added: labs/jbosstm/workspace/hornetq_txlog/README.txt
===================================================================
--- labs/jbosstm/workspace/hornetq_txlog/README.txt	                        (rev 0)
+++ labs/jbosstm/workspace/hornetq_txlog/README.txt	2010-04-28 12:44:37 UTC (rev 32671)
@@ -0,0 +1,20 @@
+
+This is the prototype for an ObjectStore implementation based on HornetQ's Journal.
+
+ at author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+
+Building:
+
+Clebert has not got around to modularizing the journal for use separate from HornetQ yet
+( HORNETQ-274 ) so for now you'll need to build HornetQ trunk or grab hornetq-core.jar
+from a maven repo. You'll also need netty as the journal currently depends on it despite
+not using it for networking. You probably want the .so for the libAIO version of the journal
+too - fish it out of hornetq's svn or compile it for your platform. Finally you need JBossTS
+trunk.
+
+Tweak build.xml as needed so it can find these things, then run 'ant'.
+
+Testing:
+
+There is a trivially simple multithreaded test that can be tweaked to give some approximate
+performance numbers. Try 'ant test'.

Added: labs/jbosstm/workspace/hornetq_txlog/build.xml
===================================================================
--- labs/jbosstm/workspace/hornetq_txlog/build.xml	                        (rev 0)
+++ labs/jbosstm/workspace/hornetq_txlog/build.xml	2010-04-28 12:44:37 UTC (rev 32671)
@@ -0,0 +1,91 @@
+<project name="hornetq-journal-objectstore" default="dist" basedir=".">
+
+    <description>
+        use the HornetQ journal impl to back a JBossTS TxLog impl.
+    </description>
+
+    <property name="jbossts.home" value="/home/jhalli/IdeaProjects/jboss/jbossts_trunk/install"/>
+
+    <property name="build.dir" location="build"/>
+    <property name="src.dir" location="src"/>
+    <property name="tests.src.dir" location="tests/src"/>
+
+    <path id="build.classpath">
+        <fileset dir="${jbossts.home}/lib">
+            <include name="*.jar"/>
+            <include name="ext/*.jar"/>
+        </fileset>
+        <fileset dir="/home/jhalli/.m2/repository">
+            <include name="org/hornetq/hornetq-core/2.1.0.r9031/hornetq-core-2.1.0.r9031.jar"/>
+            <include name="org/jboss/netty/netty/3.2.0.BETA1/netty-3.2.0.BETA1.jar"/>
+        </fileset>
+    </path>
+
+    <target name="fetchdeps">
+        <exec command="mvn">
+            <arg value="org.apache.maven.plugins:maven-dependency-plugin:2.1:get"/>
+            <arg value="-DrepoUrl=https://repository.jboss.org/nexus/content/groups/public/"/>
+            <arg value="-Dartifact=org.hornetq:hornetq-core:2.1.0.r9031"/>
+        </exec>
+        <exec command="mvn">
+            <arg value="org.apache.maven.plugins:maven-dependency-plugin:2.1:get"/>
+            <arg value="-DrepoUrl=https://repository.jboss.org/nexus/content/groups/public/"/>
+            <arg value="-Dartifact=org.jboss.netty:netty:3.2.0.BETA1"/>
+        </exec>
+    </target>
+
+    <target name="init">
+        <tstamp/>
+        <mkdir dir="${build.dir}"/>
+    </target>
+
+    <target name="clean">
+        <delete dir="${build.dir}"/>
+    </target>
+
+    <target name="compile" depends="init"
+            description="compile the source ">
+
+        <javac srcdir="${src.dir}" destdir="${build.dir}" debug="true">
+            <classpath refid="build.classpath"/>
+        </javac>
+
+    </target>
+
+    <target name="dist" depends="compile">
+        <jar jarfile="${build.dir}/hornetq-objectstore.jar">
+            <fileset dir="${build.dir}" includes="org/jboss/jbossts/hornetq/*.class"/>
+        </jar>
+    </target>
+
+    <target name="compile.tests" depends="dist"
+            description="compile the tests source ">
+
+        <javac srcdir="${tests.src.dir}" destdir="${build.dir}" debug="true">
+            <classpath>
+                <path refid="build.classpath"/>
+                <pathelement location="${build.dir}/hornetq-objectstore.jar"/>
+            </classpath>
+
+        </javac>
+
+    </target>
+
+    <target name="test" depends="compile.tests">
+        <java classname="org.jboss.jbossts.hornetq/tests.Test" fork="true">
+
+            <jvmarg value="-Xdebug"/>
+            <jvmarg value="-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"/>
+
+            <!--<jvmarg value="-agentpath:/usr/local/javastuff/jprofiler602/bin/linux-x64/libjprofilerti.so=port=8849"/>-->
+            <jvmarg value="-Djprofiler.64bit=true"/>
+
+            <env key="LD_LIBRARY_PATH" value="/home/jhalli/IdeaProjects/jboss/hornetq_trunk/native/bin/"/>
+            <classpath>
+                <path refid="build.classpath"/>
+                <pathelement location="${build.dir}"/>
+            </classpath>
+        </java>
+    </target>
+
+</project>
\ No newline at end of file

Added: labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalEnvironmentBean.java
===================================================================
--- labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalEnvironmentBean.java	                        (rev 0)
+++ labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalEnvironmentBean.java	2010-04-28 12:44:37 UTC (rev 32671)
@@ -0,0 +1,283 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.hornetq;
+
+import java.io.File;
+
+/**
+ * A JavaBean containing assorted configuration properties for the HornetQ Journal based transaction logging system.
+ *
+ * TODO: create matching MBean
+ * http://hornetq.sourceforge.net/docs/hornetq-2.0.0.BETA5/user-manual/en/html/persistence.html#configuring.message.journal.journal-type
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+public class HornetqJournalEnvironmentBean
+{
+    private volatile int fileSize = 1024*1024*2;
+
+    private volatile int minFiles = 4;
+
+    private volatile int compactMinFiles = 0;
+
+    private volatile int compactPercentage = 100;
+
+    private volatile String filePrefix = "jbossts";
+
+    private volatile String fileExtension = "txlog";
+
+    private volatile int maxIO = 10;
+
+    private volatile String storeDir = System.getProperty("user.dir") + File.separator + "HornetqJournalTxLog";
+
+    private volatile boolean syncWrites = true;
+
+    private volatile boolean syncDeletes = true;
+
+
+    /**
+     * Returns the desired size in bytes of each log file.
+     * Minimum 1024.
+     *
+     * Default: 2MB (2097152 bytes)
+     *
+     * @return The individual log file size, in bytes.
+     */
+    public int getFileSize()
+    {
+        return fileSize;
+    }
+
+    /**
+     * Sets the desired size in bytes for each log file.
+     * 
+     * @param fileSize the individual log file size, in bytes.
+     */
+    public void setFileSize(int fileSize)
+    {
+        this.fileSize = fileSize;
+    }
+
+    /**
+     * Returns the minimum number of log files to use.
+     * Minimum 2.
+     *
+     * Default: 4
+     *
+     * @return the minimum number of individual log files.
+     */
+    public int getMinFiles()
+    {
+        return minFiles;
+    }
+
+    /**
+     * Sets the minimum number of log files to use.
+     *
+     * @param minFiles the minimum number of individual log files.
+     */
+    public void setMinFiles(int minFiles)
+    {
+        this.minFiles = minFiles;
+    }
+
+    /**
+     * TODO
+     *
+     * Default: 0
+     *
+     * @return
+     */
+    public int getCompactMinFiles()
+    {
+        return compactMinFiles;
+    }
+
+    /**
+     * TODO
+     *
+     * @param compactMinFiles
+     */
+    public void setCompactMinFiles(int compactMinFiles)
+    {
+        this.compactMinFiles = compactMinFiles;
+    }
+
+    /**
+     * TODO
+     *
+     * Default: 100
+     *
+     * @return
+     */
+    public int getCompactPercentage()
+    {
+        return compactPercentage;
+    }
+
+    /**
+     * TODO
+     *
+     * @param compactPercentage
+     */
+    public void setCompactPercentage(int compactPercentage)
+    {
+        this.compactPercentage = compactPercentage;
+    }
+
+    /**
+     * Returns the prefix to be used when naming each log file.
+     *
+     * Default: "jbossts"
+     *
+     * @return the prefix used to construct individual log file names.
+     */
+    public String getFilePrefix()
+    {
+        return filePrefix;
+    }
+
+    /**
+     * Sets the prefix to be used when naming each log file.
+     *
+     * @param filePrefix the prefix used to construct individual log file names.
+     */
+    public void setFilePrefix(String filePrefix)
+    {
+        this.filePrefix = filePrefix;
+    }
+
+    /**
+     * Returns the suffix to be used then naming each log file.
+     *
+     * Default: "txlog"
+     *
+     * @return the suffix used to construct individual log file names.
+     */
+    public String getFileExtension()
+    {
+        return fileExtension;
+    }
+
+    /**
+     * Sets the suffix to be used when naming each log file.
+     *
+     * @param fileExtension the suffix used to construct individual log file names.
+     */
+    public void setFileExtension(String fileExtension)
+    {
+        this.fileExtension = fileExtension;
+    }
+
+    /**
+     * TODO
+     * Minimum 1.
+     *
+     * Default: 10
+     *
+     * @return
+     */
+    public int getMaxIO()
+    {
+        return maxIO;
+    }
+
+    /**
+     * TODO
+     *
+     * @param maxIO
+     */
+    public void setMaxIO(int maxIO)
+    {
+        this.maxIO = maxIO;
+    }
+
+    /**
+     * Returns the log directory path
+     *
+     * Default: {user.dir}/HornetqJournalTxLog
+     *
+     * @return the log directory name
+     */
+    public String getStoreDir()
+    {
+        return storeDir;
+    }
+
+    /**
+     * Sets the log directory path.
+     *
+     * @param storeDir the path to the log directory.
+     */
+    public void setStoreDir(String storeDir)
+    {
+        this.storeDir = storeDir;
+    }
+
+    /**
+     * Returns the sync setting for transaction log write operations.
+     * To preserve ACID properties this value must be set to true, in which case
+     * log write operations block until data is forced to the physical storage device.
+     * Turn sync off only if you don't care about data integrity.
+     *
+     * Default: true.
+     *
+     * @return true if log writes should be synchronous, false otherwise.
+     */
+    public boolean isSyncWrites()
+    {
+        return syncWrites;
+    }
+
+    /**
+     * Sets if log write operations should be synchronous or not.
+     *
+     * @param syncWrites true for synchronous operation, false otherwise.
+     */
+    public void setSyncWrites(boolean syncWrites)
+    {
+        this.syncWrites = syncWrites;
+    }
+
+    /**
+     * Returns the sync setting for transaction log delete operations.
+     * For optimal crash recovery this value should be set to true.
+     * Ansychronous deletes may give rise to unnecessary crash recovery complications.
+     *
+     * Default: true.
+     * 
+     * @return true if log deletes should be synchronous, false otherwise.
+     */
+    public boolean isSyncDeletes()
+    {
+        return syncDeletes;
+    }
+
+    /**
+     * Sets if log delete operations should be synchronous or not.
+     *
+     * @param syncDeletes true for synchronous operation, false otherwise.
+     */
+    public void setSyncDeletes(boolean syncDeletes)
+    {
+        this.syncDeletes = syncDeletes;
+    }
+}

Added: labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalTxLog.java
===================================================================
--- labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalTxLog.java	                        (rev 0)
+++ labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqJournalTxLog.java	2010-04-28 12:44:37 UTC (rev 32671)
@@ -0,0 +1,222 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.hornetq;
+
+import com.arjuna.ats.arjuna.objectstore.ObjectStoreType;
+import com.arjuna.ats.arjuna.objectstore.TxLog;
+import com.arjuna.ats.arjuna.state.OutputObjectState;
+import com.arjuna.ats.arjuna.state.OutputBuffer;
+import com.arjuna.ats.arjuna.state.InputBuffer;
+import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
+import com.arjuna.ats.arjuna.common.Uid;
+
+import com.arjuna.ats.internal.arjuna.common.UidHelper;
+import org.hornetq.core.journal.*;
+import org.hornetq.core.journal.impl.JournalImpl;
+import org.hornetq.core.journal.impl.AIOSequentialFileFactory;
+import org.hornetq.core.journal.impl.NIOSequentialFileFactory;
+
+import java.io.SyncFailedException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Implementation of the TxLog interfaces backed by HornetQ's journal.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+public class HornetqJournalTxLog implements TxLog
+{
+    private final Journal journal;
+    private final Map<Uid, RecordInfo> state = new ConcurrentHashMap<Uid, RecordInfo>();
+    private final Object uidMappingLock = new Object();
+    private long maxID = 0;
+    private final boolean syncWrites;
+    private final boolean syncDeletes;
+
+    private static final byte RECORD_TYPE = 0x00;
+    private static HornetqJournalTxLog _instance;
+
+    public void stop() throws Exception {
+        journal.stop();
+    }
+
+    public void start() throws Exception {
+
+        journal.start();
+
+        List<RecordInfo> committedRecords = new LinkedList<RecordInfo>();
+        List<PreparedTransactionInfo> preparedTransactions = new LinkedList<PreparedTransactionInfo>();
+        TransactionFailureCallback failureCallback = new TransactionFailureCallback() {
+            public void failedTransaction(long l, java.util.List<org.hornetq.core.journal.RecordInfo> recordInfos, java.util.List<org.hornetq.core.journal.RecordInfo> recordInfos1) {
+                System.err.println("This should never get called");
+            }
+        };
+
+        JournalLoadInformation journalLoadInformation = journal.load(committedRecords, preparedTransactions, failureCallback);
+        maxID = journalLoadInformation.getMaxID();
+
+        if(!preparedTransactions.isEmpty()) {
+            System.err.println("This should never happen");
+        }
+
+        for(RecordInfo record : committedRecords) {
+            InputBuffer inputBuffer = new InputBuffer(record.data);
+            Uid uid = UidHelper.unpackFrom(inputBuffer);
+            state.put(uid, record);
+            // don't unpack the rest yet, we may never need it.
+            //String typeName = inputBuffer.unpackString();
+            //InputObjectState inputObjectState = new InputObjectState(uid, typeName, inputBuffer.unpackBytes());
+        }
+
+        System.out.println("HornetqJournalTxLog started");
+    }
+
+
+    public synchronized static HornetqJournalTxLog getInstance() {
+        return _instance;
+    }
+
+    public HornetqJournalTxLog(HornetqJournalEnvironmentBean envBean) {
+
+        syncWrites = envBean.isSyncWrites();
+        syncDeletes = envBean.isSyncDeletes();
+
+        SequentialFileFactory sequentialFileFactory;
+        if(AIOSequentialFileFactory.isSupported()) {
+            sequentialFileFactory = new AIOSequentialFileFactory(envBean.getStoreDir());
+        } else {
+            sequentialFileFactory = new NIOSequentialFileFactory(envBean.getStoreDir());
+        }
+
+        journal = new JournalImpl(envBean.getFileSize(), envBean.getMinFiles(), envBean.getCompactMinFiles(),
+                        envBean.getCompactPercentage(), sequentialFileFactory, envBean.getFilePrefix(),
+                        envBean.getFileExtension(), envBean.getMaxIO());
+
+        // wiring kludge:
+        if(_instance == null) {
+            _instance = this;
+        }
+    }
+
+
+    /**
+     * Remove the object's committed state.
+     *
+     * @param uid  The object to work on.
+     * @param typeName The type of the object to work on.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean remove_committed(Uid uid, String typeName) throws ObjectStoreException
+    {
+        try {
+            long id = getIdFromUid(uid); // look up the id *before* doing the remove from state, or it won't be there any more.
+            state.remove(uid);
+            journal.appendDeleteRecord(id, syncDeletes);
+        } catch(Exception e) {
+            throw new ObjectStoreException(e);
+        }
+
+        return true;
+    }
+
+    /**
+     * Write a new copy of the object's committed state.
+     *
+     * @param uid    The object to work on.
+     * @param typeName   The type of the object to work on.
+     * @param txData The state to write.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean write_committed(Uid uid, String typeName, OutputObjectState txData) throws ObjectStoreException
+    {
+        // TODO: handle rewrite using appendUpdateRecord
+        try {
+            OutputBuffer outputBuffer = new OutputBuffer();
+            UidHelper.packInto(uid, outputBuffer);
+            outputBuffer.packString(typeName);
+            outputBuffer.packBytes(txData.buffer());
+            long id = getIdFromUid(uid);
+            byte[] data = outputBuffer.buffer();
+
+            journal.appendAddRecord(id, RECORD_TYPE, data, syncWrites);
+            RecordInfo record = new RecordInfo(id, RECORD_TYPE, data, false);
+            state.put(uid, record);
+        } catch(Exception e) {
+            throw new ObjectStoreException(e.toString());
+        }
+
+        return true;
+    }
+
+    /**
+     * Some object store implementations may be running with automatic
+     * sync disabled. Calling this method will ensure that any states are
+     * flushed to disk.
+     */
+    @Override
+    public void sync() throws SyncFailedException, ObjectStoreException
+    {
+        // null-op in this impl.
+    }
+
+    /**
+     * The type of the object store. This is used to order the
+     * instances in the intentions list.
+     *
+     * @return the type of the record.
+     * @see com.arjuna.ats.arjuna.coordinator.RecordType
+     */
+    @Override
+    public int typeIs()
+    {
+        return ObjectStoreType.USER_DEF_0;
+    }
+
+    /**
+     * @return the "name" of the object store. Where in the hierarchy it appears, e.g., /ObjectStore/MyName/...
+     */
+    @Override
+    public String getStoreName()
+    {
+        return this.getClass().getSimpleName(); // TODO: add instance file path?
+    }
+
+    /////////////////////////////////
+
+    private long getIdFromUid(Uid uid) {
+        synchronized (uidMappingLock) {
+            RecordInfo record = state.get(uid);
+            if(record != null) {
+                return record.id;
+            } else {
+                maxID++;
+                return maxID;
+            }
+        }
+    }
+}

Added: labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqObjectStoreAdaptor.java
===================================================================
--- labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqObjectStoreAdaptor.java	                        (rev 0)
+++ labs/jbosstm/workspace/hornetq_txlog/src/org/jboss/jbossts/hornetq/HornetqObjectStoreAdaptor.java	2010-04-28 12:44:37 UTC (rev 32671)
@@ -0,0 +1,263 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.hornetq;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
+import com.arjuna.ats.arjuna.objectstore.ObjectStore;
+import com.arjuna.ats.arjuna.objectstore.TxLog;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.arjuna.state.OutputObjectState;
+
+import java.io.SyncFailedException;
+
+/**
+ * Adaptor class that wraps the TxLog impl to make it look like a ObjectStore.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+public class HornetqObjectStoreAdaptor extends ObjectStore
+{
+    private final TxLog txLog = HornetqJournalTxLog.getInstance();
+
+    /**
+     * Read the object's shadowed state.
+     *
+     * @param u  The object to work on.
+     * @param tn The type of the object to work on.
+     * @return the state of the object.
+     */
+    @Override
+    public InputObjectState read_uncommitted(Uid u, String tn) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Remove the object's uncommitted state.
+     *
+     * @param u  The object to work on.
+     * @param tn The type of the object to work on.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean remove_uncommitted(Uid u, String tn) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Read the object's committed state.
+     *
+     * @param u  The object to work on.
+     * @param tn The type of the object to work on.
+     * @return the state of the object.
+     */
+    @Override
+    public InputObjectState read_committed(Uid u, String tn) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Remove the object's committed state.
+     *
+     * @param u  The object to work on.
+     * @param tn The type of the object to work on.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean remove_committed(Uid u, String tn) throws ObjectStoreException
+    {
+        return txLog.remove_committed(u, tn);
+    }
+
+    /**
+     * Hide the object's state in the object store. Used by crash
+     * recovery.
+     *
+     * @param u  The object to work on.
+     * @param tn The type of the object to work on.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean hide_state(Uid u, String tn) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Reveal a hidden object's state.
+     *
+     * @param u  The object to work on.
+     * @param tn The type of the object to work on.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean reveal_state(Uid u, String tn) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Commit the object's state in the object store.
+     *
+     * @param u  The object to work on.
+     * @param tn The type of the object to work on.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean commit_state(Uid u, String tn) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * @param u  The object to query.
+     * @param tn The type of the object to query.
+     * @return the current state of the object's state (e.g., shadowed,
+     *         committed ...) [StateStatus]
+     */
+    @Override
+    public int currentState(Uid u, String tn) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+
+    /**
+     * Write a copy of the object's uncommitted state.
+     *
+     * @param u    The object to work on.
+     * @param tn   The type of the object to work on.
+     * @param buff The state to write.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean write_uncommitted(Uid u, String tn, OutputObjectState buff) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Write a new copy of the object's committed state.
+     *
+     * @param u    The object to work on.
+     * @param tn   The type of the object to work on.
+     * @param buff The state to write.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean write_committed(Uid u, String tn, OutputObjectState buff) throws ObjectStoreException
+    {
+        return txLog.write_committed(u, tn, buff);
+    }
+
+    /**
+     * Obtain all of the Uids for a specified type.
+     *
+     * @param s    The type to scan for.
+     * @param buff The object state in which to store the Uids
+     * @param m    The file type to look for (e.g., committed, shadowed). [StateStatus]
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean allObjUids(String s, InputObjectState buff, int m) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Obtain all types of objects stored in the object store.
+     *
+     * @param buff The state in which to store the types.
+     * @return <code>true</code> if no errors occurred, <code>false</code>
+     *         otherwise.
+     */
+    @Override
+    public boolean allTypes(InputObjectState buff) throws ObjectStoreException
+    {
+        throw new ObjectStoreException("This should never be called");
+    }
+
+    /**
+     * Suppress directories of the specified type from
+     * allTypes etc?
+     */
+    @Override
+    protected boolean supressEntry(String name)
+    {
+        return false;
+    }
+
+    /**
+     * The type of the object store. This is used to order the
+     * instances in the intentions list.
+     *
+     * @return the type of the record.
+     * @see com.arjuna.ats.arjuna.coordinator.RecordType
+     */
+    @Override
+    public int typeIs()
+    {
+        return txLog.typeIs();
+    }
+
+    /**
+     * Some object store implementations may be running with automatic
+     * sync disabled. Calling this method will ensure that any states are
+     * flushed to disk.
+     */
+    @Override
+    public void sync() throws SyncFailedException, ObjectStoreException
+    {
+        txLog.sync();
+    }
+
+    /**
+     * @return the "name" of the object store. Where in the hierarchy it appears, e.g., /ObjectStore/MyName/...
+     */
+    @Override
+    public String getStoreName()
+    {
+        return txLog.getStoreName();
+    }
+}
+
+/*
+RecoveryStore
+    public boolean allObjUids (String s, InputObjectState buff, int m) throws ObjectStoreException;
+    public boolean allObjUids (String s, InputObjectState buff) throws ObjectStoreException;
+    public boolean allTypes (InputObjectState buff) throws ObjectStoreException;
+    public int currentState (Uid u, String tn) throws ObjectStoreException;
+    public boolean hide_state (Uid u, String tn) throws ObjectStoreException;
+    public boolean reveal_state (Uid u, String tn) throws ObjectStoreException;
+    public InputObjectState read_committed (Uid u, String tn) throws ObjectStoreException;
+    public boolean isType (Uid u, String tn, int st) throws ObjectStoreException;
+*/
\ No newline at end of file

Added: labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/Test.java
===================================================================
--- labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/Test.java	                        (rev 0)
+++ labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/Test.java	2010-04-28 12:44:37 UTC (rev 32671)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.hornetq.tests;
+
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
+import org.jboss.jbossts.hornetq.HornetqJournalEnvironmentBean;
+import org.jboss.jbossts.hornetq.HornetqJournalTxLog;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAResource;
+import java.util.Date;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Basic performance test harness for the ObjectStore.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+public class Test
+{
+    public static void main(String[] args) throws Exception {
+
+        HornetqJournalEnvironmentBean hornetqJournalEnvironmentBean = new HornetqJournalEnvironmentBean();
+        hornetqJournalEnvironmentBean.setStoreDir("/home/jhalli/IdeaProjects/jboss/scratch/jmsjournal/");
+        new HornetqJournalTxLog(hornetqJournalEnvironmentBean);
+        HornetqJournalTxLog.getInstance().start();
+
+        arjPropertyManager.getCoordinatorEnvironmentBean().setCommitOnePhase(false);
+        arjPropertyManager.getCoordinatorEnvironmentBean().setActionStore("org.jboss.jbossts.hornetq.HornetqObjectStoreAdaptor");
+        //arjPropertyManager.getCoordinatorEnvironmentBean().setActionStore("com.arjuna.ats.internal.arjuna.objectstore.VolatileStore");
+
+        testLoop(200000, 40);
+
+        HornetqJournalTxLog.getInstance().stop();
+    }
+
+    private static void testLoop(int iterations, int threads) throws Exception {
+
+        int NUM_TX = iterations;
+        int BATCH_SIZE = 100;
+        AtomicInteger count = new AtomicInteger(NUM_TX/BATCH_SIZE);
+        final int nThreads = threads;
+        CyclicBarrier cyclicBarrier = new CyclicBarrier(nThreads +1); // workers + self
+        ExecutorService executorService = Executors.newCachedThreadPool();
+
+        for(int i = 0; i < nThreads; i++) {
+            executorService.execute(new TestWorkerTask(cyclicBarrier, count, BATCH_SIZE));
+        }
+
+        System.out.println(new Date());
+        long start = System.nanoTime();
+
+        cyclicBarrier.await();
+        cyclicBarrier.await();
+
+        long end = System.nanoTime();
+        System.out.println(new Date());
+
+        long duration_ms = (end - start) / 1000000L;
+
+        System.out.println("  total time (ms): "+duration_ms);
+        System.out.println("average time (ms): "+(1.0*duration_ms)/NUM_TX);
+        System.out.println("tx / second: "+(1000.0/((1.0*duration_ms)/NUM_TX)));
+        System.out.println(""+nThreads+" threads");
+
+        //Thread.sleep(Long.MAX_VALUE);
+
+        executorService.shutdown();
+    }
+}
+
+class TestWorkerTask implements Runnable {
+
+    CyclicBarrier cyclicBarrier;
+    AtomicInteger count;
+    int batch_size = 0;
+
+    TestWorkerTask(CyclicBarrier cyclicBarrier, AtomicInteger count, int batch_size) {
+        this.cyclicBarrier = cyclicBarrier;
+        this.count = count;
+        this.batch_size = batch_size;
+    }
+
+    public void run() {
+        try {
+
+            int x = 0;
+
+            TransactionManager tm = new TransactionManagerImple();
+            cyclicBarrier.await();
+
+            while(count.decrementAndGet() >= 0) {
+
+                for(int i = 0; i < batch_size; i++) {
+
+                    tm.begin();
+                    Transaction t = tm.getTransaction();
+                    XAResource xaResource = new XAResourceImpl();
+                    t.enlistResource(xaResource);
+                    tm.commit();
+
+                    x++;
+                }
+
+            }
+            //System.out.println("done working "+x);
+            cyclicBarrier.await();
+        }
+         catch(Exception e) {
+            e.printStackTrace();
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/XAResourceImpl.java
===================================================================
--- labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/XAResourceImpl.java	                        (rev 0)
+++ labs/jbosstm/workspace/hornetq_txlog/tests/src/org/jboss/jbossts/hornetq/tests/XAResourceImpl.java	2010-04-28 12:44:37 UTC (rev 32671)
@@ -0,0 +1,106 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * and individual contributors as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.hornetq.tests;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+
+/**
+ * Dummy implementation of the XAResource interface for test purposes.
+ *
+ *  @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+public class XAResourceImpl implements XAResource
+{
+
+    private int txTimeout;
+
+    private Xid currentXid;
+
+    public void commit(Xid xid, boolean b) throws XAException
+    {
+        //System.out.println("XAResourceImpl.commit(Xid="+xid+", b="+b+")");
+        if(!xid.equals(currentXid)) {
+            System.out.println("XAResourceImpl.commit - wrong Xid!");
+        }
+
+        currentXid = null;
+    }
+
+    public void end(Xid xid, int i) throws XAException {
+        //System.out.println("XAResourceImpl.end(Xid="+xid+", b="+i+")");
+    }
+
+    public void forget(Xid xid) throws XAException {
+        //System.out.println("XAResourceImpl.forget(Xid="+xid+")");
+        if(!xid.equals(currentXid)) {
+            System.out.println("XAResourceImpl.forget - wrong Xid!");
+        }
+        currentXid = null;
+    }
+
+    public int getTransactionTimeout() throws XAException {
+        System.out.println("XAResourceImpl.getTransactionTimeout() [returning "+txTimeout+"]");
+        return txTimeout;
+    }
+
+    public boolean isSameRM(XAResource xaResource) throws XAException {
+        System.out.println("XAResourceImpl.isSameRM(xaResource="+xaResource+")");
+        return false;
+    }
+
+    public int prepare(Xid xid) throws XAException {
+        //System.out.println("XAResourceImpl.prepare(Xid="+xid+")");
+        return XAResource.XA_OK;
+    }
+
+    public Xid[] recover(int i) throws XAException {
+        System.out.println("XAResourceImpl.recover(i="+i+")");
+        return new Xid[0];
+    }
+
+    public void rollback(Xid xid) throws XAException {
+        System.out.println("XAResourceImpl.rollback(Xid="+xid+")");
+        if(!xid.equals(currentXid)) {
+            System.out.println("XAResourceImpl.rollback - wrong Xid!");
+        }
+        currentXid = null;
+    }
+
+    public boolean setTransactionTimeout(int i) throws XAException {
+        //System.out.println("XAResourceImpl.setTransactionTimeout(i="+i+")");
+        txTimeout= i;
+        return true;
+    }
+
+    public void start(Xid xid, int i) throws XAException {
+        //System.out.println("XAResourceImpl.start(Xid="+xid+", i="+i+")");
+        if(currentXid != null) {
+            System.out.println("XAResourceImpl.start - wrong Xid!");
+        }
+        currentXid = xid;
+    }
+
+    public String toString() {
+        return new String("XAResourceImple("+txTimeout+", "+currentXid+")");
+    }
+}



More information about the jboss-svn-commits mailing list