[jboss-svn-commits] JBL Code SVN: r36506 - in labs/jbosstm/trunk/ArjunaCore/arjuna: classes/com/arjuna/ats/internal/arjuna/objectstore and 1 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Fri Jan 7 05:20:34 EST 2011
Author: jhalliday
Date: 2011-01-07 05:20:34 -0500 (Fri, 07 Jan 2011)
New Revision: 36506
Added:
labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/
labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBean.java
labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBeanMBean.java
labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalStore.java
labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqObjectStoreAdaptor.java
Modified:
labs/jbosstm/trunk/ArjunaCore/arjuna/build.xml
Log:
Add HornetQ Journal based objectstore impl to trunk. JBTM-782
Modified: labs/jbosstm/trunk/ArjunaCore/arjuna/build.xml
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/build.xml 2011-01-06 23:23:30 UTC (rev 36505)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/build.xml 2011-01-07 10:20:34 UTC (rev 36506)
@@ -22,6 +22,8 @@
<property name="modulename" value="arjuna"/>
+ <property name="global.ext.libs" value="hornetq-core.jar,jboss-logging.jar"/><!-- jboss-logging-tools.jar -->
+
<import file="../../sharedbuild.xml"/>
<target name="init" depends="sharedbuild.init">
@@ -40,7 +42,7 @@
</additional.classpath>
</compile-tests.macro>
</target>
-
+
<!--
run tests that match a given pattern, for example
ant testone -DONECLASS="**/*ObjectStoreAPIJMXTest.java"
Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBean.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBean.java 2011-01-07 10:20:34 UTC (rev 36506)
@@ -0,0 +1,287 @@
+/*
+ * 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 com.arjuna.ats.internal.arjuna.objectstore.hornetq;
+
+import com.arjuna.common.internal.util.propertyservice.PropertyPrefix;
+
+import java.io.File;
+
+/**
+ * A JavaBean containing assorted configuration properties for the HornetQ Journal based transaction logging system.
+ *
+ * Parameters on this file serve a similar role to their counterparts in HornetQ.
+ * The HornetQ docs therefore provide relevant information on usage:
+ * http://hornetq.sourceforge.net/docs/hornetq-2.1.1.Final/user-manual/en/html/persistence.html#configuring.message.journal.journal-type
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+ at PropertyPrefix(prefix = "com.arjuna.ats.arjuna.hornetqjournal.")
+public class HornetqJournalEnvironmentBean implements HornetqJournalEnvironmentBeanMBean
+{
+ private volatile int fileSize = 1024*1024*2;
+
+ private volatile int minFiles = 4;
+
+ private volatile int compactMinFiles = 10;
+
+ private volatile int compactPercentage = 30;
+
+ private volatile String filePrefix = "jbossts";
+
+ private volatile String fileExtension = "txlog";
+
+ private volatile int maxIO = 1;
+
+ private volatile String storeDir = System.getProperty("user.dir") + File.separator + "HornetqJournalStore";
+
+ 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;
+ }
+
+ /**
+ * Gets the minimal number of files before we can consider compacting.
+ *
+ * Default: 10
+ *
+ * @return the threshold file count.
+ */
+ public int getCompactMinFiles()
+ {
+ return compactMinFiles;
+ }
+
+ /**
+ * Sets the minimal number of files before we can consider compacting.
+ *
+ * @param compactMinFiles the threshold file count.
+ */
+ public void setCompactMinFiles(int compactMinFiles)
+ {
+ this.compactMinFiles = compactMinFiles;
+ }
+
+ /**
+ * Gets the percentage minimum capacity usage at which to start compacting.
+ *
+ * Default: 30
+ *
+ * @return the threshold percentage.
+ */
+ public int getCompactPercentage()
+ {
+ return compactPercentage;
+ }
+
+ /**
+ * Sets the percentage minimum capacity usage at which to start compacting.
+ *
+ * @param compactPercentage the threshold percentage.
+ */
+ 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;
+ }
+
+ /**
+ * Gets the maximum write requests queue depth.
+ * Minimum 1. Use 1 for NIO. For AIO, recommended 500.
+ *
+ * Default: 1
+ *
+ * @return the max number of outstanding requests.
+ */
+ public int getMaxIO()
+ {
+ return maxIO;
+ }
+
+ /**
+ * Sets the maximum write requests queue depth.
+ *
+ * @param maxIO the max number of outstanding requests.
+ */
+ public void setMaxIO(int maxIO)
+ {
+ this.maxIO = maxIO;
+ }
+
+ /**
+ * Returns the log directory path
+ *
+ * Default: {user.dir}/HornetqJournalStore
+ *
+ * @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.
+ * Asynchronous 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/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBeanMBean.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBeanMBean.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalEnvironmentBeanMBean.java 2011-01-07 10:20:34 UTC (rev 36506)
@@ -0,0 +1,49 @@
+/*
+ * 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 com.arjuna.ats.internal.arjuna.objectstore.hornetq;
+
+/**
+ * A JMX MBean interface containing configuration for the HornetQ Journal based transaction logging system.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com)
+ */
+public interface HornetqJournalEnvironmentBeanMBean
+{
+ public int getFileSize();
+
+ public int getMinFiles();
+
+ public int getCompactMinFiles();
+
+ public int getCompactPercentage();
+
+ public String getFilePrefix();
+
+ public String getFileExtension();
+
+ public int getMaxIO();
+
+ public String getStoreDir();
+
+ public boolean isSyncWrites();
+
+ public boolean isSyncDeletes();
+}
Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalStore.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalStore.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqJournalStore.java 2011-01-07 10:20:34 UTC (rev 36506)
@@ -0,0 +1,256 @@
+/*
+ * 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 com.arjuna.ats.internal.arjuna.objectstore.hornetq;
+
+import com.arjuna.ats.arjuna.state.InputObjectState;
+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.File;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Implementation of the tx store backed by HornetQ's journal.
+ * This is a bean suitable for hooking into the app server lifecycle.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+public class HornetqJournalStore
+{
+ private final Journal journal;
+
+ private final ConcurrentMap<String,Map<Uid, RecordInfo>> content = new ConcurrentHashMap<String, Map<Uid, RecordInfo>>();
+
+ private final Object uidMappingLock = new Object();
+ private final boolean syncWrites;
+ private final boolean syncDeletes;
+ private long maxID = 0;
+
+ private final String storeDirCanonicalPath;
+
+ private static final byte RECORD_TYPE = 0x00;
+
+ 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);
+ String typeName = inputBuffer.unpackString();
+ getContentForType(typeName).put(uid, record);
+ // don't unpack the rest yet, we may never need it. read_committed does it on demand.
+ }
+
+ System.out.println("HornetqJournalStore started foo");
+ }
+
+ public HornetqJournalStore(HornetqJournalEnvironmentBean envBean) throws IOException {
+
+ System.out.println("HornetqJournalStore ctor");
+
+ syncWrites = envBean.isSyncWrites();
+ syncDeletes = envBean.isSyncDeletes();
+
+ File storeDir = new File(envBean.getStoreDir());
+ if(!storeDir.exists() && !storeDir.mkdirs()) {
+ throw new IOException("Failed to create store dir "+storeDir.getCanonicalPath()); // TODO i18n
+ }
+ storeDirCanonicalPath = storeDir.getCanonicalPath();
+
+ 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());
+ }
+
+
+ /**
+ * 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.
+ * @throws ObjectStoreException if things go wrong.
+ */
+ public boolean remove_committed(Uid uid, String typeName) throws ObjectStoreException
+ {
+ try {
+ long id = getId(uid, typeName); // look up the id *before* doing the remove from state, or it won't be there any more.
+ getContentForType(typeName).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.
+ * @throws ObjectStoreException if things go wrong.
+ */
+ public boolean write_committed(Uid uid, String typeName, OutputObjectState txData) throws ObjectStoreException
+ {
+ try {
+ OutputBuffer outputBuffer = new OutputBuffer();
+ UidHelper.packInto(uid, outputBuffer);
+ outputBuffer.packString(typeName);
+ outputBuffer.packBytes(txData.buffer());
+ long id = getId(uid, typeName);
+ byte[] data = outputBuffer.buffer();
+
+ // yup, there is a race condition here.
+ if(getContentForType(typeName).containsKey(uid)) {
+ journal.appendUpdateRecord(id, RECORD_TYPE, data, syncWrites);
+ } else {
+ journal.appendAddRecord(id, RECORD_TYPE, data, syncWrites);
+ }
+
+ RecordInfo record = new RecordInfo(id, RECORD_TYPE, data, false);
+ getContentForType(typeName).put(uid, record);
+ } catch(Exception e) {
+ throw new ObjectStoreException(e);
+ }
+
+ return true;
+ }
+
+ /**
+ * Read the object's committed state.
+ *
+ * @param uid The object to work on.
+ * @param typeName The type of the object to work on.
+ * @return the state of the object.
+ * @throws ObjectStoreException if things go wrong.
+ */
+ public InputObjectState read_committed(Uid uid, String typeName) throws ObjectStoreException
+ {
+ RecordInfo record = getContentForType(typeName).get(uid);
+ if(record == null) {
+ return null;
+ }
+
+ // this repeated unpacking is a little inefficient - subclass RecordInfo to hold unpacked form too?
+ // not too much of an issue as log reads are done for recovery only.
+ try {
+ InputBuffer inputBuffer = new InputBuffer(record.data);
+ Uid unpackedUid = UidHelper.unpackFrom(inputBuffer);
+ String unpackedTypeName = inputBuffer.unpackString();
+ InputObjectState inputObjectState = new InputObjectState(uid, typeName, inputBuffer.unpackBytes());
+ return inputObjectState;
+ } catch(Exception e) {
+ throw new ObjectStoreException(e);
+ }
+ }
+
+ public boolean contains(Uid uid, String typeName) {
+ RecordInfo record = getContentForType(typeName).get(uid);
+ return record != null;
+ }
+
+ /**
+ * @return the "name" of the object store. Where in the hierarchy it appears, e.g., /ObjectStore/MyName/...
+ */
+ public String getStoreName()
+ {
+ return this.getClass().getSimpleName()+":"+storeDirCanonicalPath;
+ }
+
+ public String[] getKnownTypes() {
+ return content.keySet().toArray(new String[content.size()]);
+ }
+
+ public Uid[] getUidsForType(String typeName) {
+ Set<Uid> keySet = getContentForType(typeName).keySet();
+ return keySet.toArray(new Uid[keySet.size()]);
+ }
+
+ /////////////////////////////////
+
+ private Map<Uid, RecordInfo> getContentForType(String typeName) {
+ Map<Uid, RecordInfo> result = content.get(typeName);
+ if(result == null) {
+ content.putIfAbsent(typeName, new ConcurrentHashMap<Uid, RecordInfo>());
+ result = content.get(typeName);
+ }
+ return result;
+ }
+
+ private long getId(Uid uid, String typeName) {
+ synchronized (uidMappingLock) {
+ RecordInfo record = getContentForType(typeName).get(uid);
+ if(record != null) {
+ return record.id;
+ } else {
+ maxID++;
+ return maxID;
+ }
+ }
+ }
+}
Added: labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqObjectStoreAdaptor.java
===================================================================
--- labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqObjectStoreAdaptor.java (rev 0)
+++ labs/jbosstm/trunk/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/objectstore/hornetq/HornetqObjectStoreAdaptor.java 2011-01-07 10:20:34 UTC (rev 36506)
@@ -0,0 +1,417 @@
+/*
+ * 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 com.arjuna.ats.internal.arjuna.objectstore.hornetq;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
+import com.arjuna.ats.arjuna.objectstore.ObjectStoreAPI;
+import com.arjuna.ats.arjuna.objectstore.StateStatus;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.arjuna.state.OutputObjectState;
+import com.arjuna.ats.internal.arjuna.common.UidHelper;
+import com.arjuna.common.internal.util.propertyservice.BeanPopulator;
+
+import java.io.IOException;
+import java.io.SyncFailedException;
+import java.util.HashSet;
+import java.util.Set;
+
+/* transaction-jboss-beans.xml:
+
+ <bean name="HornetqJournalEnvironmentBean" class="com.arjuna.ats.internal.arjuna.objectstore.hornetq.HornetqJournalEnvironmentBean">
+ <property name="storeDir">${jboss.server.data.dir}/tx-object-store/HornetqJournalStore</property>
+ </bean>
+ <bean name="HornetqJournalStore" class="com.arjuna.ats.internal.arjuna.objectstore.hornetq.HornetqJournalStore">
+ <constructor>
+ <parameter><inject bean="HornetqJournalEnvironmentBean"/></parameter>
+ </constructor>
+ </bean>
+ <bean name="HornetqObjectStoreAdaptor" class="com.arjuna.ats.internal.arjuna.objectstore.hornetq.HornetqObjectStoreAdaptor">
+ <constructor>
+ <parameter><inject bean="HornetqJournalStore"/></parameter>
+ </constructor>
+ </bean>
+ <bean name="TxStoreManager" class="com.arjuna.ats.arjuna.objectstore.StoreManager">
+ <constructor>
+ <parameter><inject bean="HornetqObjectStoreAdaptor"/></parameter>
+ <parameter><null/></parameter>
+ </constructor>
+ </bean>
+
+ TODO wire to RecMgr/TxMgr lifecycle deps
+
+*/
+
+/**
+ * Adaptor class that wraps the store to make it look like an ObjectStore.
+ *
+ * @author Jonathan Halliday (jonathan.halliday at redhat.com), 2010-03
+ */
+public class HornetqObjectStoreAdaptor implements ObjectStoreAPI
+{
+ private final HornetqJournalStore store;
+
+ // used for standalone bootstrap via StoreManager
+ public HornetqObjectStoreAdaptor() throws IOException {
+
+ HornetqJournalEnvironmentBean envBean = BeanPopulator.getDefaultInstance(HornetqJournalEnvironmentBean.class);
+
+ this.store = new HornetqJournalStore(envBean);
+ }
+
+ // used for beans wiring type bootstrap when running embedded.
+ public HornetqObjectStoreAdaptor(HornetqJournalStore store) {
+ this.store = store;
+ }
+
+ @Override
+ public void start()
+ {
+ try {
+ store.start();
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void stop()
+ {
+ try {
+ store.stop();
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 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");
+ }
+
+
+ private String ensureTypenamePrefix(String typeName)
+ {
+ if(!typeName.startsWith("/")) {
+ typeName = "/"+typeName;
+ }
+ return typeName;
+ }
+
+ /**
+ * Read the object's committed state.
+ *
+ * @param u The object to work on.
+ * @param typeName The type of the object to work on.
+ * @return the state of the object.
+ */
+ @Override
+ public InputObjectState read_committed(Uid u, String typeName) throws ObjectStoreException
+ {
+ typeName = ensureTypenamePrefix(typeName);
+
+ return store.read_committed(u, typeName);
+ }
+
+ /**
+ * Remove the object's committed state.
+ *
+ * @param u 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 u, String typeName) throws ObjectStoreException
+ {
+ typeName = ensureTypenamePrefix(typeName);
+
+ return store.remove_committed(u, typeName);
+ }
+
+ /**
+ * 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 typeName 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 typeName) throws ObjectStoreException
+ {
+ typeName = ensureTypenamePrefix(typeName);
+
+ if( store.contains(u, typeName)) {
+ return StateStatus.OS_COMMITTED;
+ } else {
+ return StateStatus.OS_UNKNOWN;
+ }
+ }
+
+
+ /**
+ * 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 typeName 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 typeName, OutputObjectState buff) throws ObjectStoreException
+ {
+ typeName = ensureTypenamePrefix(typeName);
+
+ return store.write_committed(u, typeName, buff);
+ }
+
+ @Override
+ public boolean allObjUids(String typeName, InputObjectState foundInstances) throws ObjectStoreException
+ {
+ typeName = ensureTypenamePrefix(typeName);
+
+ return allObjUids(typeName, foundInstances, StateStatus.OS_UNKNOWN);
+ }
+
+ /**
+ * Obtain all of the Uids for a specified type.
+ *
+ * @param typeName The type to scan for.
+ * @param foundInstances The object state in which to store the Uids
+ * @param matchState 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 typeName, InputObjectState foundInstances, int matchState) throws ObjectStoreException
+ {
+ boolean result = true;
+
+ typeName = ensureTypenamePrefix(typeName);
+
+ Uid[] uids = store.getUidsForType(typeName);
+
+ OutputObjectState buffer = new OutputObjectState();
+
+ try
+ {
+ if(uids != null && (matchState == StateStatus.OS_UNKNOWN || matchState == StateStatus.OS_COMMITTED))
+ {
+ for (Uid uid: uids)
+ {
+ UidHelper.packInto(uid, buffer);
+ }
+ }
+ UidHelper.packInto(Uid.nullUid(), buffer);
+ }
+ catch (IOException e)
+ {
+ throw new ObjectStoreException("TODO");
+ }
+
+ foundInstances.setBuffer(buffer.buffer());
+
+ return result;
+ }
+
+
+ /**
+ * Obtain all types of objects stored in the object store.
+ *
+ * @param foundTypes 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 foundTypes) throws ObjectStoreException
+ {
+ boolean result = true;
+
+ String[] knownTypes = store.getKnownTypes();
+ Set<String> typeSet = new HashSet<String>();
+
+ if (knownTypes == null || knownTypes.length == 0)
+ return true;
+
+ OutputObjectState buffer = new OutputObjectState();
+
+ try
+ {
+ for (String typeName: knownTypes)
+ {
+ if(typeName.startsWith("/")) {
+ typeName = typeName.substring(1);
+ }
+
+ if(typeName.contains("/")) {
+ String value = "";
+ String[] parents = typeName.split("/");
+ for(String parent : parents) {
+ if(parent.length() == 0) {
+ continue;
+ }
+ if(value.length() > 0) {
+ value = value+"/";
+ }
+ value = value+parent;
+ if(!typeSet.contains(value)) {
+ typeSet.add(value);
+ buffer.packString(value);
+ }
+ }
+ } else {
+ buffer.packString(typeName);
+ }
+ }
+ buffer.packString("");
+ }
+ catch (IOException e)
+ {
+ throw new ObjectStoreException(e);
+ }
+
+ foundTypes.setBuffer(buffer.buffer());
+
+ return result;
+ }
+
+ /**
+ * 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.
+ }
+
+ /**
+ * @return the "name" of the object store. Where in the hierarchy it appears, e.g., /ObjectStore/MyName/...
+ */
+ @Override
+ public String getStoreName()
+ {
+ return store.getStoreName();
+ }
+
+ @Override
+ public boolean fullCommitNeeded()
+ {
+ return false;
+ }
+
+ /**
+ * Is the current state of the object the same as that provided as the last
+ * parameter?
+ *
+ * @param u The object to work on.
+ * @param tn The type of the object.
+ * @param st The expected type of the object. [StateType]
+ * @return <code>true</code> if the current state is as expected,
+ * <code>false</code> otherwise.
+ */
+ @Override
+ public boolean isType(Uid u, String tn, int st) throws ObjectStoreException
+ {
+ return false;
+ }
+}
\ No newline at end of file
More information about the jboss-svn-commits
mailing list