[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