[Mulgara-svn] r647 - in branches/mgr-73/src/jar: resolver-memory/java/org/mulgara/resolver/memory resolver-spi/java/org/mulgara/resolver/spi resolver-store/java/org/mulgara/resolver/store
ronald at mulgara.org
ronald at mulgara.org
Mon Feb 18 13:44:00 UTC 2008
Author: ronald
Date: 2008-02-18 05:44:00 -0800 (Mon, 18 Feb 2008)
New Revision: 647
Added:
branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java
Modified:
branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java
branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java
branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java
branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java
branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java
branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java
branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java
Log:
XAResource implementation fixes:
* added AbstractXAResource as a common superclass for XAResource
implementations; it properly manages the resource-manager and transation
lifecycles.
* changed StatementStoreXAResource and MemoryXAResource to subclass new
AbstractXAResource; this fixes current MemoryXAResource failures when using
local transactions.
Modified: branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java
===================================================================
--- branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java 2008-02-18 13:37:11 UTC (rev 646)
+++ branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolver.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -84,8 +84,10 @@
*/
private final Set<Stating> statingSet;
- private XAResolverSession xaResolverSession;
+ private final XAResource xares;
+ private final XAResolverSession xaResolverSession;
+
//
// Constructors
//
@@ -105,34 +107,30 @@
* is {@link NodePool#NONE}
*/
MemoryResolver(ResolverSession resolverSession,
- Resolver systemResolver,
long rdfType,
- long systemModel,
URI modelTypeURI,
Set<Stating> statingSet)
throws ResolverFactoryException {
-
- // Validate "modelType" parameter
- if (modelTypeURI == null) {
- throw new IllegalArgumentException("Model type can't be null");
- }
-
- // Initialize fields
- memoryModelTypeURI = modelTypeURI;
- this.rdfType = rdfType;
- this.resolverSession = resolverSession;
- this.statingSet = statingSet;
- this.xaResolverSession = null;
+ this(resolverSession, rdfType, modelTypeURI, statingSet, null, null);
}
-
MemoryResolver(long rdfType,
- long systemModel,
URI modelTypeURI,
Set<Stating> statingSet,
- XAResolverSession resolverSession)
+ XAResolverSession resolverSession,
+ ResolverFactory resolverFactory)
throws ResolverFactoryException {
-
+ this(resolverSession, rdfType, modelTypeURI, statingSet, resolverSession,
+ resolverFactory);
+ }
+
+ private MemoryResolver(ResolverSession resolverSession,
+ long rdfType,
+ URI modelTypeURI,
+ Set<Stating> statingSet,
+ XAResolverSession xaResolverSession,
+ ResolverFactory resolverFactory)
+ throws ResolverFactoryException {
// Validate "modelType" parameter
if (modelTypeURI == null) {
throw new IllegalArgumentException("Model type can't be null");
@@ -143,20 +141,21 @@
this.rdfType = rdfType;
this.resolverSession = resolverSession;
this.statingSet = statingSet;
- this.xaResolverSession = resolverSession;
+ this.xaResolverSession = xaResolverSession;
+
+ this.xares = (xaResolverSession != null) ?
+ new MemoryXAResource(10, xaResolverSession, resolverFactory) :
+ new DummyXAResource(10);
}
+
//
// Methods implementing Resolver
//
public XAResource getXAResource() {
- if (xaResolverSession != null) {
- return new MemoryXAResource(10, xaResolverSession);
- } else {
- return new DummyXAResource(10);
- }
+ return xares;
}
Modified: branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java
===================================================================
--- branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java 2008-02-18 13:37:11 UTC (rev 646)
+++ branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryResolverFactory.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -74,11 +74,6 @@
/**
- * The preallocated local node representing the system model (<code>#</code>).
- */
- private long systemModel;
-
- /**
* The {@link Stating}s which occur in all models created by resolvers
* created by this factory.
*/
@@ -105,8 +100,6 @@
rdfType = initializer.preallocate(new URIReferenceImpl(RDF.TYPE));
initializer.preallocate(new URIReferenceImpl(modelTypeURI));
- systemModel = initializer.getSystemModel();
-
// Claim mulgara:MemoryModel
initializer.addModelType(modelTypeURI, this);
@@ -136,7 +129,6 @@
public void setDatabaseMetadata(DatabaseMetadata metadata) {
rdfType = metadata.getRdfTypeNode();
- systemModel = metadata.getSystemModelNode();
}
@@ -222,9 +214,7 @@
) throws ResolverFactoryException {
if (logger.isDebugEnabled()) logger.debug("Creating memory resolver");
return new MemoryResolver(resolverSession,
- systemResolver,
rdfType,
- systemModel,
modelTypeURI,
statingSet);
}
@@ -234,8 +224,9 @@
assert sessionFactory != null;
if (logger.isDebugEnabled()) logger.debug("Creating memory resolver factory");
try {
- return new MemoryResolver(rdfType, systemModel, modelTypeURI, statingSet,
- (XAResolverSession) sessionFactory.newWritableResolverSession());
+ return new MemoryResolver(rdfType, modelTypeURI, statingSet,
+ (XAResolverSession) sessionFactory.newWritableResolverSession(),
+ this);
} catch (ResolverSessionFactoryException er) {
throw new ResolverFactoryException("Failed to obtain a new ResolverSession", er);
}
Modified: branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java
===================================================================
--- branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java 2008-02-18 13:37:11 UTC (rev 646)
+++ branches/mgr-73/src/jar/resolver-memory/java/org/mulgara/resolver/memory/MemoryXAResource.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -27,23 +27,15 @@
package org.mulgara.resolver.memory;
-// Java 2 standard packages
-import java.util.*;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-// Third party packages
-import org.apache.log4j.Logger;
-
-
+import org.mulgara.resolver.spi.AbstractXAResource;
+import org.mulgara.resolver.spi.AbstractXAResource.RMInfo;
+import org.mulgara.resolver.spi.AbstractXAResource.TxInfo;
+import org.mulgara.resolver.spi.ResolverFactory;
import org.mulgara.store.xa.SimpleXAResource;
-import org.mulgara.store.xa.SimpleXAResourceException;
import org.mulgara.store.xa.XAResolverSession;
/**
- * A dummy implementation of the {@link XAResource} interface which logs the
- * calls made to it, but otherwise ignores them.
+ * Implements the XAResource for the {@link MemoryResolver}.
*
* @created 2004-05-12
* @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
@@ -54,38 +46,8 @@
* Technoogies, Inc.</a>
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
-
-public class MemoryXAResource implements XAResource
-{
- /** Logger. */
- private static final Logger logger =
- Logger.getLogger(MemoryXAResource.class.getName());
-
- /**
- * Map from keyed from the {@link Integer} value of the various flags
- * defined in {@link XAResource} and mapping to the formatted name for that
- * flag.
- */
- private final static Map flagMap = new HashMap();
-
- static {
- flagMap.put(new Integer(XAResource.TMENDRSCAN), "TMENDRSCAN");
- flagMap.put(new Integer(XAResource.TMFAIL), "TMFAIL");
- flagMap.put(new Integer(XAResource.TMJOIN), "TMJOIN");
- flagMap.put(new Integer(XAResource.TMONEPHASE), "TMONEPHASE");
- flagMap.put(new Integer(XAResource.TMRESUME), "TMRESUME");
- flagMap.put(new Integer(XAResource.TMSTARTRSCAN), "TMSTARTRSCAN");
- flagMap.put(new Integer(XAResource.TMSUCCESS), "TMSUCCESS");
- flagMap.put(new Integer(XAResource.TMSUCCESS), "TMSUSPEND");
- }
-
- /** The transaction timeout value in seconds. */
- private int transactionTimeout = 0;
-
- private XAResolverSession session;
- private boolean rollback;
- private Xid xid;
-
+public class MemoryXAResource
+ extends AbstractXAResource<RMInfo<MemoryXAResource.MemoryTxInfo>,MemoryXAResource.MemoryTxInfo> {
//
// Constructor
//
@@ -94,209 +56,56 @@
* Construct a {@link MemoryXAResource} with a specified transaction timeout.
*
* @param transactionTimeout transaction timeout period, in seconds
+ * @param session the underlying resolver-session to use
+ * @param resolverFactory the resolver-factory we belong to
*/
public MemoryXAResource(int transactionTimeout,
- XAResolverSession session)
- {
- logger.debug("<init> Creating MemoryXAResource: " + this);
- this.transactionTimeout = transactionTimeout * 100;
- this.session = session;
- this.rollback = false;
+ XAResolverSession session,
+ ResolverFactory resolverFactory) {
+ super(transactionTimeout, resolverFactory, newTxInfo(session));
}
- //
- // Methods implementing XAResource
- //
-
- public void start(Xid xid, int flags) throws XAException
- {
- logger.debug("Start " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
- switch (flags) {
- case XAResource.TMRESUME:
- logger.debug("Resuming transaction on " + System.identityHashCode(xid));
- break;
- case XAResource.TMNOFLAGS:
- try {
- session.refresh(new SimpleXAResource[] {});
- this.xid = xid;
- } catch (SimpleXAResourceException es) {
- logger.warn("Failed to refresh phases", es);
- throw new XAException(XAException.XAER_RMFAIL);
- }
- break;
- default:
- rollback = true;
- logger.error("Unrecognised flags in start: " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
- throw new XAException(XAException.XAER_INVAL);
- }
+ protected RMInfo<MemoryTxInfo> newResourceManager() {
+ return new RMInfo<MemoryTxInfo>();
}
- public int prepare(Xid xid) throws XAException
- {
- logger.debug("Prepare " + System.identityHashCode(xid));
- logger.debug("Prepare always returns XA_OK, never XA_RDONLY");
-
- if (rollback) {
- logger.error("Attempting to prepare in failed transaction");
- throw new XAException(XAException.XA_RBROLLBACK);
- }
- if (!xid.equals(this.xid)) {
- logger.error("Attempting to prepare unknown transaction.");
- throw new XAException(XAException.XAER_NOTA);
- }
-
- try {
- session.prepare();
- } catch (SimpleXAResourceException es) {
- logger.warn("Attempt to prepare store failed", es);
- throw new XAException(XAException.XA_RBROLLBACK);
- }
-
- return XA_OK;
+ private static MemoryTxInfo newTxInfo(XAResolverSession session) {
+ MemoryTxInfo ti = new MemoryTxInfo();
+ ti.session = session;
+ return ti;
}
- public void commit(Xid xid, boolean onePhase) throws XAException
- {
- logger.debug("Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase);
- if (rollback) {
- logger.error("Attempting to commit in failed transaction");
- throw new XAException(XAException.XA_RBROLLBACK);
- }
- if (!xid.equals(this.xid)) {
- logger.error("Attempting to commit unknown transaction.");
- throw new XAException(XAException.XAER_NOTA);
- }
+ //
+ // Methods implementing XAResource
+ //
- try {
- if (onePhase) {
- // Check return value is XA_OK.
- prepare(xid);
- }
- } catch (Throwable th) {
- this.rollback = true;
- logger.error("Attempt to prepare in onePhaseCommit failed.", th);
- throw new XAException(XAException.XA_RBROLLBACK);
+ protected void doStart(MemoryTxInfo tx, int flags, boolean isNew) throws Exception {
+ if (flags == TMNOFLAGS || flags == TMJOIN) {
+ tx.session.refresh(new SimpleXAResource[] {});
}
-
- try {
- session.commit();
- } catch (Throwable th) {
- // This is a serious problem since the database is now in an
- // inconsistent state.
- // Make sure the exception is logged.
- logger.fatal("Failed to commit resource in transaction " + xid, th);
- throw new XAException(XAException.XAER_RMERR);
- }
}
- public void end(Xid xid, int flags) throws XAException
- {
- logger.debug("End xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+ protected void doEnd(MemoryTxInfo tx, int flags) {
}
- public void forget(Xid xid) throws XAException
- {
- logger.debug("Forget xid=" + System.identityHashCode(xid));
+ protected int doPrepare(MemoryTxInfo tx) throws Exception {
+ tx.session.prepare();
+ return XA_OK;
}
- public int getTransactionTimeout() throws XAException
- {
- logger.debug("Get transaction timeout: " + transactionTimeout);
- return transactionTimeout;
+ protected void doCommit(MemoryTxInfo tx) throws Exception {
+ tx.session.commit();
}
- public boolean isSameRM(XAResource xaResource) throws XAException
- {
- logger.debug("Is same resource manager? " + (xaResource == this) + " :: " + xaResource + " on " + this);
- return xaResource == this;
+ protected void doRollback(MemoryTxInfo tx) throws Exception {
+ tx.session.rollback();
}
- public Xid[] recover(int flag) throws XAException
- {
- logger.debug("Recover flag=" + formatFlags(flag));
- throw new XAException(XAException.XAER_RMERR);
+ protected void doForget(MemoryTxInfo tx) {
}
- public void rollback(Xid xid) throws XAException
- {
- logger.debug("Rollback " + System.identityHashCode(xid));
-
- boolean fatalError = false;
-
- if (!xid.equals(this.xid)) {
- logger.error("Attempting to rollback unknown transaction.");
- fatalError = true;
- }
-
- try {
- session.rollback();
- } catch (Throwable th) {
- // This is a serious problem since the database is now in an
- // inconsistent state.
- // Make sure the exception is logged.
- logger.fatal("Failed to rollback resource in transaction " + xid, th);
- fatalError = true;
- }
-
- if (fatalError) {
- logger.fatal("Fatal error occured while rolling back transaction " + xid + " in manager for " + this.xid);
- throw new XAException(XAException.XAER_RMERR);
- }
+ static class MemoryTxInfo extends TxInfo {
+ /** the underlying resolver-session to use */
+ public XAResolverSession session;
}
-
- public boolean setTransactionTimeout(int transactionTimeout)
- throws XAException
- {
- logger.debug("Set transaction timeout: " + transactionTimeout);
- this.transactionTimeout = transactionTimeout;
- return true;
- }
-
- //
- // Internal methods
- //
-
- /**
- * Format bitmasks defined by {@link XAResource}.
- *
- * @param flags a bitmask composed from the constants defined in
- * {@link XAResource}
- * @return a formatted representation of the <var>flags</var>
- */
- private static String formatFlags(int flags)
- {
- // Short-circuit evaluation if we've been explicitly passed no flags
- if (flags == XAResource.TMNOFLAGS) {
- return "TMNOFLAGS";
- }
-
- StringBuffer buffer = new StringBuffer();
-
- // Add any flags that are present
- for (Iterator i = flagMap.entrySet().iterator(); i.hasNext(); ) {
- Map.Entry entry = (Map.Entry)i.next();
- int entryFlag = ((Integer)entry.getKey()).intValue();
-
- // If this flag is present, add it to the formatted output and remove
- // from the bitmask
- if ((entryFlag & flags) == entryFlag) {
- if (buffer.length() > 0) {
- buffer.append(",");
- }
- buffer.append(entry.getValue());
- flags &= ~entryFlag;
- }
- }
-
- // We would expect to have removed all flags by this point
- // If there's some unknown flag we've missed, format it as hexadecimal
- if (flags != 0) {
- if (buffer.length() > 0) {
- buffer.append(",");
- }
- buffer.append("0x").append(Integer.toHexString(flags));
- }
-
- return buffer.toString();
- }
}
Added: branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java
===================================================================
--- branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java (rev 0)
+++ branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -0,0 +1,446 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * The Original Code is the Kowari Metadata Store.
+ *
+ * The Initial Developer of the Original Code is Plugged In Software Pty
+ * Ltd (http://www.pisoftware.com, mailto:info at pisoftware.com). Portions
+ * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
+ * Plugged In Software Pty Ltd. All Rights Reserved.
+ *
+ * Contributor(s): N/A.
+ *
+ * [NOTE: The text of this Exhibit A may differ slightly from the text
+ * of the notices in the Source Code files of the Original Code. You
+ * should use the text of this Exhibit A rather than the text found in the
+ * Original Code Source Code for Your Modifications.]
+ *
+ */
+
+package org.mulgara.resolver.spi;
+
+// Java 2 standard packages
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+// Third party packages
+import org.apache.log4j.Logger;
+
+/**
+ * A skeleton XAResource implementation. This handles the basic
+ * resource-manager and transaction management and ensures correct {@link
+ * #isSameRM} implementation. Subclasses must implement the actual
+ * functionality in the {@link #doStart}, {@link #doPrepare}, {@link
+ * #doCommit}, and {@link #doRollback} methods.
+ *
+ * @created 2008-02-16
+ * @author Ronald Tschalär
+ * @licence Open Software License v3.0
+ */
+public abstract class AbstractXAResource<R extends AbstractXAResource.RMInfo<T>,T extends AbstractXAResource.TxInfo>
+ extends DummyXAResource {
+ /** Logger. */
+ private static final Logger logger =
+ Logger.getLogger(AbstractXAResource.class.getName());
+
+ protected static final Map<ResolverFactory,RMInfo<? extends TxInfo>> resourceManagers =
+ new WeakHashMap<ResolverFactory,RMInfo<? extends TxInfo>>();
+
+ protected final R resourceManager;
+ protected final T tmpTxInfo;
+
+
+ //
+ // Constructor
+ //
+
+ /**
+ * Construct an XAResource.
+ *
+ * @param transactionTimeout transaction timeout period, in seconds
+ * @param resolverFactory the resolver-factory we belong to
+ * @param txInfo the initial transaction-info
+ */
+ public AbstractXAResource(int transactionTimeout,
+ ResolverFactory resolverFactory,
+ T txInfo) {
+ super(transactionTimeout);
+
+ synchronized (resourceManagers) {
+ @SuppressWarnings("unchecked")
+ R rmgr = (R) resourceManagers.get(resolverFactory);
+ if (rmgr == null)
+ resourceManagers.put(resolverFactory, rmgr = newResourceManager());
+ this.resourceManager = rmgr;
+ }
+
+ this.tmpTxInfo = txInfo;
+ }
+
+ /**
+ * Create a new resource-manager instance - invoked only from the
+ * constructor and only when no resource-manager instance exists for the
+ * given resolver-factory.
+ */
+ protected abstract R newResourceManager();
+
+ //
+ // Methods implementing XAResource
+ //
+
+ public void start(Xid xid, int flags) throws XAException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Start xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+ logger.debug("xid.format=" + xid.getFormatId() + " xid.gblTxId=" + Arrays.toString(xid.getGlobalTransactionId()) + " xid.brnchQual=" + Arrays.toString(xid.getBranchQualifier()));
+ }
+
+ T tx = resourceManager.transactions.get(new XidWrapper(xid));
+ boolean isNew = false;
+
+ switch (flags) {
+ case XAResource.TMRESUME:
+ if (tx == null) {
+ logger.error("Attempting to resume unknown transaction.");
+ throw new XAException(XAException.XAER_NOTA);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("Resuming transaction on xid=" + System.identityHashCode(xid));
+ }
+ break;
+
+ case XAResource.TMNOFLAGS:
+ if (tx != null) {
+ logger.warn("Received plain start for existing tx");
+ logger.warn("xid.format=" + xid.getFormatId() + " xid.gblTxId=" + Arrays.toString(xid.getGlobalTransactionId()) + " xid.brnchQual=" + Arrays.toString(xid.getBranchQualifier()));
+ throw new XAException(XAException.XAER_DUPID);
+ }
+ // fallthrough
+
+ case XAResource.TMJOIN:
+ if (tx == null) {
+ resourceManager.transactions.put(new XidWrapper(xid), tx = tmpTxInfo);
+ isNew = true;
+ }
+ break;
+
+ default:
+ // XXX: is this correct? Or should we actually roll back here?
+ if (tx != null)
+ tx.rollback = true;
+ logger.error("Unrecognised flags in start: xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+ throw new XAException(XAException.XAER_INVAL);
+ }
+
+ try {
+ doStart(tx, flags, isNew);
+ } catch (Throwable t) {
+ logger.warn("Failed to do start", t);
+ resourceManager.transactions.remove(new XidWrapper(xid));
+ throw new XAException(XAException.XAER_RMFAIL);
+ }
+ }
+
+ public void end(Xid xid, int flags) throws XAException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("End xid=" + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
+ }
+
+ T tx = resourceManager.transactions.get(new XidWrapper(xid));
+ if (tx == null) {
+ logger.error("Attempting to end unknown transaction.");
+ throw new XAException(XAException.XAER_NOTA);
+ }
+
+ try {
+ doEnd(tx, flags);
+ } catch (Throwable t) {
+ logger.warn("Failed to do end", t);
+ resourceManager.transactions.remove(new XidWrapper(xid));
+ throw new XAException(XAException.XAER_RMFAIL);
+ }
+ }
+
+ public int prepare(Xid xid) throws XAException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Prepare xid=" + System.identityHashCode(xid));
+ }
+
+ T tx = resourceManager.transactions.get(new XidWrapper(xid));
+ if (tx == null) {
+ logger.error("Attempting to prepare unknown transaction.");
+ throw new XAException(XAException.XAER_NOTA);
+ }
+
+ if (tx.rollback) {
+ logger.info("Attempting to prepare in failed transaction");
+ rollback(xid);
+ throw new XAException(XAException.XA_RBROLLBACK);
+ }
+
+ try {
+ int sts = doPrepare(tx);
+ if (sts == XA_RDONLY)
+ resourceManager.transactions.remove(new XidWrapper(xid));
+ return sts;
+ } catch (Throwable t) {
+ logger.warn("Attempt to prepare failed", t);
+ rollback(xid);
+ throw new XAException(XAException.XA_RBROLLBACK);
+ }
+ }
+
+ public void commit(Xid xid, boolean onePhase) throws XAException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase);
+ }
+
+ T tx = resourceManager.transactions.get(new XidWrapper(xid));
+ if (tx == null) {
+ logger.error("Attempting to commit unknown transaction.");
+ throw new XAException(XAException.XAER_NOTA);
+ }
+ if (tx.rollback) {
+ logger.error("Attempting to commit in failed transaction");
+ rollback(xid);
+ throw new XAException(XAException.XA_RBROLLBACK);
+ }
+
+ try {
+ if (onePhase) {
+ int sts = doPrepare(tx);
+ if (sts == XA_RDONLY) {
+ resourceManager.transactions.remove(new XidWrapper(xid));
+ return;
+ }
+ }
+ } catch (Throwable th) {
+ logger.error("Attempt to prepare in onePhaseCommit failed.", th);
+ rollback(xid);
+ throw new XAException(XAException.XA_RBROLLBACK);
+ }
+
+ boolean clean = true;
+ try {
+ doCommit(tx);
+ } catch (XAException xae) {
+ if (isHeuristic(xae)) {
+ clean = false;
+ }
+ throw xae;
+ } catch (Throwable th) {
+ // This is a serious problem since the database is now in an
+ // inconsistent state.
+ // Make sure the exception is logged.
+ logger.fatal("Failed to commit resource in transaction " + xid, th);
+ throw new XAException(XAException.XAER_RMERR);
+ } finally {
+ if (clean) {
+ resourceManager.transactions.remove(new XidWrapper(xid));
+ }
+ }
+ }
+
+ public void rollback(Xid xid) throws XAException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Rollback xid=" + System.identityHashCode(xid));
+ }
+
+ T tx = resourceManager.transactions.get(new XidWrapper(xid));
+ if (tx == null) {
+ logger.error("Attempting to rollback unknown transaction.");
+ throw new XAException(XAException.XAER_NOTA);
+ }
+
+ boolean clean = true;
+ try {
+ doRollback(tx);
+ } catch (XAException xae) {
+ if (isHeuristic(xae)) {
+ clean = false;
+ }
+ throw xae;
+ } catch (Throwable th) {
+ // This is a serious problem since the database is now in an
+ // inconsistent state.
+ // Make sure the exception is logged.
+ logger.fatal("Failed to rollback resource in transaction " + xid, th);
+ throw new XAException(XAException.XAER_RMERR);
+ } finally {
+ if (clean) {
+ resourceManager.transactions.remove(new XidWrapper(xid));
+ }
+ }
+ }
+
+ public void forget(Xid xid) throws XAException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Forget xid=" + System.identityHashCode(xid));
+ }
+
+ T tx = resourceManager.transactions.get(new XidWrapper(xid));
+ if (tx == null) {
+ logger.error("Attempting to forget unknown transaction.");
+ throw new XAException(XAException.XAER_NOTA);
+ }
+
+ boolean clean = true;
+ try {
+ doForget(tx);
+ } catch (XAException xae) {
+ if (xae.errorCode == XAException.XAER_RMERR) {
+ clean = false;
+ }
+ throw xae;
+ } catch (Throwable th) {
+ logger.error("Failed to forget transaction " + xid, th);
+ clean = false;
+ throw new XAException(XAException.XAER_RMERR);
+ } finally {
+ if (clean) {
+ resourceManager.transactions.remove(new XidWrapper(xid));
+ }
+ }
+ }
+
+ public Xid[] recover(int flag) throws XAException {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Recover flag=" + formatFlags(flag));
+ }
+
+ throw new XAException(XAException.XAER_RMERR);
+ }
+
+ public boolean isSameRM(XAResource xaResource) throws XAException {
+ boolean same = (xaResource instanceof AbstractXAResource) &&
+ ((AbstractXAResource)xaResource).resourceManager == resourceManager;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Is same resource manager? " + same + " :: " + xaResource + " on " + this);
+ }
+
+ return same;
+ }
+
+ /**
+ * Invoked on start with valid flags and tx state.
+ *
+ * @param tx the transaction being started; always non-null
+ * @param flags one of TMNOFLAGS, TMRESUME, or TMJOIN
+ * @param isNew true if <var>tx</var> was created as part of this start()
+ * @throws Exception
+ */
+ protected abstract void doStart(T tx, int flags, boolean isNew) throws Exception;
+
+ /**
+ * Invoked on end().
+ *
+ * @param tx the transaction being ended; always non-null
+ * @param flags one of TMSUCCESS, TMFAIL, or TMSUSPEND
+ * @throws Exception
+ */
+ protected abstract void doEnd(T tx, int flags) throws Exception;
+
+ /**
+ * Invoked on prepare() or commit(onePhase=true).
+ *
+ * @param tx the transaction being prepared; always non-null
+ * @return XA_OK or XA_RDONLY
+ * @throws Exception
+ */
+ protected abstract int doPrepare(T tx) throws Exception;
+
+ /**
+ * Invoked on commit().
+ *
+ * @param tx the transaction being committed; always non-null
+ * @throws Exception
+ */
+ protected abstract void doCommit(T tx) throws Exception;
+
+ /**
+ * Invoked on (explicit or implicit) rollback().
+ *
+ * @param tx the transaction being rolled back; always non-null
+ * @throws Exception
+ */
+ protected abstract void doRollback(T tx) throws Exception;
+
+ /**
+ * Invoked on forget().
+ *
+ * @param tx the transaction to forget; always non-null
+ * @throws Exception
+ */
+ protected abstract void doForget(T tx) throws Exception;
+
+ private static boolean isHeuristic(XAException xae) {
+ return (xae.errorCode == XAException.XA_HEURHAZ || xae.errorCode == XAException.XA_HEURCOM ||
+ xae.errorCode == XAException.XA_HEURRB || xae.errorCode == XAException.XA_HEURMIX);
+ }
+
+
+ /** The resource-manager info */
+ public static class RMInfo<T extends TxInfo> {
+ /** the list of active transactions */
+ public final Map<XidWrapper,T> transactions =
+ Collections.synchronizedMap(new HashMap<XidWrapper,T>());
+ }
+
+ /** The info pertaining to a single transaction */
+ public static class TxInfo {
+ /** true if this transaction has been marked for rollback */
+ public boolean rollback;
+ }
+
+ /**
+ * Xid-wrapper that implements hashCode() and equals(). JTA does not require
+ * Xid's to implement hashCode() and equals(), so in order to be able to use
+ * them as keys in a map we need to wrap them with something that implements
+ * them based on the individual fields of the Xid.
+ */
+ public static class XidWrapper {
+ private final Xid xid;
+ private final int hash;
+
+ public XidWrapper(Xid xid) {
+ this.xid = xid;
+ this.hash = Arrays.hashCode(xid.getBranchQualifier());
+ }
+
+ public int hashCode() {
+ return hash;
+ }
+
+ public boolean equals(Object other) {
+ Xid o;
+
+ if (other instanceof XidWrapper) {
+ o = ((XidWrapper)other).xid;
+ } else if (other instanceof Xid) {
+ o = (Xid)other;
+ } else {
+ return false;
+ }
+
+ if (o == xid)
+ return true;
+ return o.getFormatId() == xid.getFormatId() &&
+ Arrays.equals(o.getGlobalTransactionId(), xid.getGlobalTransactionId()) &&
+ Arrays.equals(o. getBranchQualifier(), xid. getBranchQualifier());
+ }
+ }
+}
Property changes on: branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/AbstractXAResource.java
___________________________________________________________________
Name: svn:keywords
+ Id HeadURL Revision
Name: svn:eol-style
+ native
Modified: branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java
===================================================================
--- branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java 2008-02-18 13:37:11 UTC (rev 646)
+++ branches/mgr-73/src/jar/resolver-spi/java/org/mulgara/resolver/spi/DummyXAResource.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -61,7 +61,7 @@
* defined in {@link XAResource} and mapping to the formatted name for that
* flag.
*/
- private final static Map<Integer,String> flagMap = new HashMap<Integer,String>();
+ protected final static Map<Integer,String> flagMap = new HashMap<Integer,String>();
static {
flagMap.put(new Integer(XAResource.TMENDRSCAN), "TMENDRSCAN");
@@ -75,7 +75,7 @@
}
/** The transaction timeout value in seconds. */
- private int transactionTimeout = 0;
+ protected int transactionTimeout = 0;
//
// Constructor
@@ -88,7 +88,7 @@
*/
public DummyXAResource(int transactionTimeout) {
if (logger.isDebugEnabled()) {
- logger.debug("Creating DummyXAResource with timeout " + transactionTimeout);
+ logger.debug("Creating " + getClass().getName() + " with timeout " + transactionTimeout);
}
this.transactionTimeout = transactionTimeout;
}
@@ -173,7 +173,7 @@
* @param flags a bitmask composed from the constants defined in {@link XAResource}
* @return a formatted representation of the <var>flags</var>
*/
- private static final String formatFlags(int flags) {
+ protected static final String formatFlags(int flags) {
// Short-circuit evaluation if we've been explicitly passed no flags
if (flags == XAResource.TMNOFLAGS) {
return "TMNOFLAGS";
Modified: branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java
===================================================================
--- branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java 2008-02-18 13:37:11 UTC (rev 646)
+++ branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolver.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -131,7 +131,8 @@
long systemModel,
URI modelTypeURI,
XAResolverSession resolverSession,
- XAStatementStore statementStore)
+ XAStatementStore statementStore,
+ ResolverFactory resolverFactory)
throws IllegalArgumentException, ResolverFactoryException
{
// Validate parameters
@@ -153,7 +154,8 @@
this.xaresource = new StatementStoreXAResource(
10, // transaction timeout in seconds
resolverSession,
- new SimpleXAResource[] { statementStore });
+ new SimpleXAResource[] { statementStore },
+ resolverFactory);
}
StatementStoreResolver(Resolver systemResolver,
@@ -161,7 +163,8 @@
long systemModel,
URI modelTypeURI,
XAResolverSession resolverSession,
- XAStatementStore statementStore)
+ XAStatementStore statementStore,
+ ResolverFactory resolverFactory)
throws IllegalArgumentException, ResolverFactoryException
{
// Validate parameters
@@ -182,7 +185,8 @@
this.xaresource = new StatementStoreXAResource(
10, // transaction timeout in seconds
resolverSession,
- new SimpleXAResource[] { statementStore });
+ new SimpleXAResource[] { statementStore },
+ resolverFactory);
}
@@ -374,7 +378,7 @@
+ resolverSession.globalize(statements.getObject()) + " "
+ resolverSession.globalize(model) + "]", e);
} catch (Exception eg) {
- throw new ResolverException("Failed to globalize in debug", eg);
+ throw new ResolverException("Failed to globalize in debug", eg);
}
throw new ResolverException("Couldn't make statement " + occurs + " in " + model, e);
} catch (TuplesException e) {
Modified: branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java
===================================================================
--- branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java 2008-02-18 13:37:11 UTC (rev 646)
+++ branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreResolverFactory.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -195,7 +195,8 @@
: (XAResolverSession) resolverSessionFactory.newReadOnlyResolverSession(),
allowWrites
? statementStore.newWritableStatementStore()
- : statementStore.newReadOnlyStatementStore());
+ : statementStore.newReadOnlyStatementStore(),
+ this);
} catch (ResolverSessionFactoryException er) {
throw new ResolverFactoryException(
"Failed to obtain a new ResolverSession", er);
@@ -216,7 +217,8 @@
:
(XAResolverSession) resolverSessionFactory.newReadOnlyResolverSession(),
allowWrites ? statementStore.newWritableStatementStore()
- : statementStore.newReadOnlyStatementStore());
+ : statementStore.newReadOnlyStatementStore(),
+ this);
} catch (ResolverSessionFactoryException er) {
throw new ResolverFactoryException(
"Failed to obtain a new ResolverSession", er);
Modified: branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java
===================================================================
--- branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java 2008-02-18 13:37:11 UTC (rev 646)
+++ branches/mgr-73/src/jar/resolver-store/java/org/mulgara/resolver/store/StatementStoreXAResource.java 2008-02-18 13:44:00 UTC (rev 647)
@@ -28,22 +28,22 @@
package org.mulgara.resolver.store;
// Java 2 standard packages
-import java.util.*;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
+import java.util.HashSet;
+import java.util.Set;
// Third party packages
import org.apache.log4j.Logger;
-
+import org.mulgara.resolver.spi.AbstractXAResource;
+import org.mulgara.resolver.spi.AbstractXAResource.RMInfo;
+import org.mulgara.resolver.spi.AbstractXAResource.TxInfo;
+import org.mulgara.resolver.spi.ResolverFactory;
import org.mulgara.store.xa.SimpleXAResource;
import org.mulgara.store.xa.SimpleXAResourceException;
import org.mulgara.store.xa.XAResolverSession;
/**
- * A dummy implementation of the {@link XAResource} interface which logs the
- * calls made to it, but otherwise ignores them.
+ * Implements the XAResource for the {@link StatementStoreResolver}.
*
* @created 2004-05-12
* @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a>
@@ -55,40 +55,15 @@
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
-public class StatementStoreXAResource implements XAResource
-{
+public class StatementStoreXAResource
+ extends AbstractXAResource<RMInfo<StatementStoreXAResource.StatementStoreTxInfo>, StatementStoreXAResource.StatementStoreTxInfo> {
/** Logger. */
private static final Logger logger =
Logger.getLogger(StatementStoreXAResource.class.getName());
- /**
- * Map from keyed from the {@link Integer} value of the various flags
- * defined in {@link XAResource} and mapping to the formatted name for that
- * flag.
- */
- private final static Map flagMap = new HashMap();
-
- static {
- flagMap.put(new Integer(XAResource.TMENDRSCAN), "TMENDRSCAN");
- flagMap.put(new Integer(XAResource.TMFAIL), "TMFAIL");
- flagMap.put(new Integer(XAResource.TMJOIN), "TMJOIN");
- flagMap.put(new Integer(XAResource.TMONEPHASE), "TMONEPHASE");
- flagMap.put(new Integer(XAResource.TMRESUME), "TMRESUME");
- flagMap.put(new Integer(XAResource.TMSTARTRSCAN), "TMSTARTRSCAN");
- flagMap.put(new Integer(XAResource.TMSUCCESS), "TMSUCCESS");
- flagMap.put(new Integer(XAResource.TMSUSPEND), "TMSUSPEND");
- }
-
- /** The transaction timeout value in seconds. */
- private int transactionTimeout = 0;
-
- private SimpleXAResource[] resources;
- private XAResolverSession session;
- private boolean rollback;
- private Xid xid;
// Used to prevent multiple calls to prepare on the store layer.
// Set of session's that have been prepared.
- private static Set preparing = new HashSet();
+ public static Set<XAResolverSession> preparing = new HashSet<XAResolverSession>();
//
// Constructor
@@ -98,296 +73,127 @@
* Construct a {@link StatementStoreXAResource} with a specified transaction timeout.
*
* @param transactionTimeout transaction timeout period, in seconds
+ * @param session the underlying resolver-session to use
+ * @param resources
+ * @param resolverFactory the resolver-factory we belong to
*/
public StatementStoreXAResource(int transactionTimeout,
XAResolverSession session,
- SimpleXAResource[] resources)
- {
- if (logger.isDebugEnabled()) {
- logger.debug("<init> Creating StatementStoreXAResource: " + this);
- }
- this.transactionTimeout = transactionTimeout * 100;
- this.resources = resources;
- this.session = session;
+ SimpleXAResource[] resources,
+ ResolverFactory resolverFactory) {
+ super(transactionTimeout, resolverFactory, newTxInfo(session, resources));
}
+ protected RMInfo<StatementStoreTxInfo> newResourceManager() {
+ return new RMInfo<StatementStoreTxInfo>();
+ }
+
+ private static StatementStoreTxInfo newTxInfo(XAResolverSession session,
+ SimpleXAResource[] resources) {
+ StatementStoreTxInfo ti = new StatementStoreTxInfo();
+ ti.session = session;
+ ti.resources = resources;
+ return ti;
+ }
+
//
// Methods implementing XAResource
//
- public void start(Xid xid, int flags) throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("Start " + System.identityHashCode(xid) + " flags=" +
- formatFlags(flags), new Throwable());
- }
- switch (flags) {
- case XAResource.TMNOFLAGS:
- try {
- session.refresh(resources);
- this.xid = xid;
- this.rollback = false;
- } catch (SimpleXAResourceException es) {
- logger.error("Failed to obtain phases", es);
- throw new XAException(XAException.XAER_RMFAIL);
- }
- break;
- case XAResource.TMRESUME:
- if (!xid.equals(this.xid)) {
- logger.error("Attempt to resume resource in wrong transaction.");
- throw new XAException(XAException.XAER_INVAL);
- }
- break;
- case XAResource.TMJOIN:
- if (!xid.equals(this.xid)) {
- logger.error("Attempt to join with wrong transaction.");
- throw new XAException(XAException.XAER_INVAL);
- }
- break;
- default: // Currently fall-through.
- rollback = true;
- logger.warn("Unrecognised flags in start: " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
- if (logger.isDebugEnabled()) {
- logger.debug("This XAResource = " + System.identityHashCode(this.xid));
- }
- throw new XAException(XAException.XAER_INVAL);
+ protected void doStart(StatementStoreTxInfo tx, int flags, boolean isNew) throws Exception {
+ if (flags == TMNOFLAGS) {
+ tx.session.refresh(tx.resources);
}
}
- public int prepare(Xid xid) throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("XAResource " + this + " Prepare " + System.identityHashCode(xid) + " With Session: " + System.identityHashCode(session));
- }
+ protected void doEnd(StatementStoreTxInfo tx, int flags) {
+ }
- if (rollback) {
- logger.error("Attempting to prepare in failed transaction");
- throw new XAException(XAException.XA_RBROLLBACK);
- }
- if (!xid.equals(this.xid)) {
- logger.error("Attempting to prepare unknown transaction.");
- throw new XAException(XAException.XAER_NOTA);
- }
- synchronized(preparing) {
- if (preparing.contains(session)) {
+ protected int doPrepare(StatementStoreTxInfo tx) throws Exception {
+ synchronized (preparing) {
+ if (preparing.contains(tx.session)) {
return XA_OK;
} else {
- preparing.add(session);
+ preparing.add(tx.session);
}
}
try {
- session.prepare();
+ tx.session.prepare();
} catch (SimpleXAResourceException es) {
- logger.warn("Attempt to prepare store failed", es);
- synchronized(preparing) {
- preparing.remove(session);
+ synchronized (preparing) {
+ preparing.remove(tx.session);
}
- throw new XAException(XAException.XA_RBROLLBACK);
+ throw es;
}
return XA_OK;
}
- public void commit(Xid xid, boolean onePhase) throws XAException
- {
+ protected void doCommit(StatementStoreTxInfo tx) throws Exception {
try {
- if (logger.isDebugEnabled()) {
- logger.debug("XAResource " + this + " Commit xid=" + System.identityHashCode(xid) + " onePhase=" + onePhase + " session=" + System.identityHashCode(session));
- }
- if (rollback) {
- logger.error("Attempting to commit in failed transaction");
- throw new XAException(XAException.XA_RBROLLBACK);
- }
- if (!xid.equals(this.xid)) {
- logger.error("Attempting to commit unknown transaction.");
- throw new XAException(XAException.XAER_NOTA);
- }
- try {
- if (onePhase) {
- // Currently prepare only returns XA_OK, and throws an exception on failure.
- prepare(xid);
- }
- } catch (Throwable th) {
- this.rollback = true;
- logger.error("Attempt to prepare in onePhaseCommit failed.", th);
- throw new XAException(XAException.XA_RBROLLBACK);
- }
-
- try {
- session.commit();
- } catch (Throwable th) {
- // This is a serious problem since the database is now in an
- // inconsistent state.
- // Make sure the exception is logged.
- logger.fatal("Failed to commit resource in transaction " + xid, th);
- throw new XAException(XAException.XAER_RMERR);
- }
+ tx.session.commit();
} finally {
- cleanup("commit");
+ cleanup("commit", tx);
}
-
}
- public void end(Xid xid, int flags) throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("End " + System.identityHashCode(xid) + " flags=" + formatFlags(flags));
- }
- }
-
- public void forget(Xid xid) throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("Forget xid=" + System.identityHashCode(xid));
- }
+ protected void doForget(StatementStoreTxInfo tx) throws Exception {
try {
- synchronized(preparing) {
- if (preparing.contains(session)) {
- rollback(xid);
+ synchronized (preparing) {
+ if (preparing.contains(tx.session)) {
+ doRollback(tx);
}
}
} finally {
- cleanup("forget");
+ cleanup("forget", tx);
}
}
- public int getTransactionTimeout() throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("Get transaction timeout: " + transactionTimeout);
- }
- return transactionTimeout;
- }
-
- public boolean isSameRM(XAResource xaResource) throws XAException
- {
- return xaResource == this;
- }
-
- public Xid[] recover(int flag) throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("Recover flag=" + formatFlags(flag));
- }
- throw new XAException(XAException.XAER_RMERR);
- }
-
- public void rollback(Xid xid) throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("Rollback " + System.identityHashCode(xid));
- }
-
- boolean fatalError = false;
-
- if (!xid.equals(this.xid)) {
- logger.error("Attempting to rollback unknown transaction.");
- fatalError = true;
- }
-
+ protected void doRollback(StatementStoreTxInfo tx) throws Exception {
try {
- if (logger.isDebugEnabled()) {
- logger.debug("Rolling back phase");
- }
- session.rollback();
- } catch (Throwable th) {
- // This is a serious problem since the database is now in an
- // inconsistent state.
- // Make sure the exception is logged.
- logger.fatal("Failed to rollback resource in transaction " + xid, th);
- fatalError = true;
+ tx.session.rollback();
} finally {
- cleanup("rollback");
+ cleanup("rollback", tx);
}
-
- if (fatalError) {
- logger.fatal("Fatal error occured while rolling back transaction " + xid + " in manager for " + this.xid);
- throw new XAException(XAException.XAER_RMERR);
- }
}
- public boolean setTransactionTimeout(int transactionTimeout)
- throws XAException
- {
- if (logger.isDebugEnabled()) {
- logger.debug("Set transaction timeout: " + transactionTimeout);
- }
- this.transactionTimeout = transactionTimeout;
- return true;
- }
-
//
// Internal methods
//
- /**
- * Format bitmasks defined by {@link XAResource}.
- *
- * @param flags a bitmask composed from the constants defined in
- * {@link XAResource}
- * @return a formatted representation of the <var>flags</var>
- */
- private static String formatFlags(int flags)
- {
- // Short-circuit evaluation if we've been explicitly passed no flags
- if (flags == XAResource.TMNOFLAGS) {
- return "TMNOFLAGS";
- }
-
- StringBuffer buffer = new StringBuffer();
-
- // Add any flags that are present
- for (Iterator i = flagMap.entrySet().iterator(); i.hasNext(); ) {
- Map.Entry entry = (Map.Entry)i.next();
- int entryFlag = ((Integer)entry.getKey()).intValue();
-
- // If this flag is present, add it to the formatted output and remove
- // from the bitmask
- if ((entryFlag & flags) == entryFlag) {
- if (buffer.length() > 0) {
- buffer.append(",");
- }
- buffer.append(entry.getValue());
- flags &= ~entryFlag;
- }
- }
-
- // We would expect to have removed all flags by this point
- // If there's some unknown flag we've missed, format it as hexadecimal
- if (flags != 0) {
- if (buffer.length() > 0) {
- buffer.append(",");
- }
- buffer.append("0x").append(Integer.toHexString(flags));
- }
-
- return buffer.toString();
- }
-
-
- private void cleanup(String operation) {
+ private void cleanup(String operation, StatementStoreTxInfo tx) {
if (logger.isDebugEnabled()) {
logger.debug("Performing cleanup from " + operation);
}
try {
- synchronized(preparing) {
- if (preparing.contains(session)) {
- preparing.remove(session);
+ synchronized (preparing) {
+ if (preparing.contains(tx.session)) {
+ preparing.remove(tx.session);
} else {
- logger.debug("Already committed/rolledback in this transaction");
+ if (logger.isDebugEnabled()) {
+ logger.debug("Already committed/rolledback in this transaction");
+ }
}
}
} finally {
try {
if (logger.isDebugEnabled()) {
- logger.debug("Releasing session after " + operation + " " + session);
+ logger.debug("Releasing session after " + operation + " " + tx.session);
}
- session.release();
- session = null;
+ tx.session.release();
+ tx.session = null;
} catch (SimpleXAResourceException es) {
logger.error("Attempt to release store failed", es);
}
}
}
+
+ static class StatementStoreTxInfo extends TxInfo {
+ /** the underlying resolver-session to use */
+ public XAResolverSession session;
+
+ /** the underlying resources */
+ public SimpleXAResource[] resources;
+ }
}
More information about the Mulgara-svn
mailing list