You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by oz...@apache.org on 2004/06/23 11:57:15 UTC
cvs commit: jakarta-slide/src/share/org/apache/slide/structure StructureImpl.java
ozeigermann 2004/06/23 02:57:15
Modified: src/share/org/apache/slide/common SlideToken.java
SlideTokenImpl.java SlideTokenWrapper.java
src/stores/org/apache/slide/store/txfile
TxXMLFileDescriptorsStore.java
TxFileContentStore.java
AbstractTxFileStoreService.java
src/webdav/server/org/apache/slide/webdav WebdavServlet.java
src/webdav/server/org/apache/slide/webdav/method
AbstractWebdavMethod.java TransactionMethod.java
src/share/org/apache/slide/structure StructureImpl.java
Added: src/share/org/apache/slide/transaction
ExternalTransactionContext.java
Log:
Added initial version of external tx support.
TODO:
- This has been tested with the file store only. It is very likely that the RDBMS will not work, yet
- SlideTokenWrapper badly fixed
- Transaction method is provisional only. Will be replaced.
Revision Changes Path
1.17 +7 -4 jakarta-slide/src/share/org/apache/slide/common/SlideToken.java
Index: SlideToken.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/common/SlideToken.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- SlideToken.java 11 Feb 2004 11:30:11 -0000 1.16
+++ SlideToken.java 23 Jun 2004 09:57:14 -0000 1.17
@@ -261,5 +261,8 @@
public boolean isForceLock();
public void setForceLock(boolean forceLock);
+
+ public boolean isExternalTransaction();
+ public void setExternalTx();
}
1.11 +15 -3 jakarta-slide/src/share/org/apache/slide/common/SlideTokenImpl.java
Index: SlideTokenImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/common/SlideTokenImpl.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- SlideTokenImpl.java 11 Feb 2004 11:30:11 -0000 1.10
+++ SlideTokenImpl.java 23 Jun 2004 09:57:14 -0000 1.11
@@ -121,6 +121,8 @@
private Hashtable lockCache = new Hashtable();
private Hashtable resolveCache = new Hashtable();
private Hashtable matchPrincipalCache = new Hashtable();
+
+ private boolean isExternalTransaction = false;
// ------------------------------------------------------------- Properties
@@ -386,6 +388,16 @@
public void setForceSecurity(boolean forceSecurity) {
throw new UnsupportedOperationException();
+ }
+
+
+ public boolean isExternalTransaction() {
+ return isExternalTransaction;
+ }
+
+
+ public void setExternalTx() {
+ isExternalTransaction = true;
}
}
1.11 +15 -4 jakarta-slide/src/share/org/apache/slide/common/SlideTokenWrapper.java
Index: SlideTokenWrapper.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/common/SlideTokenWrapper.java,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- SlideTokenWrapper.java 11 Feb 2004 11:30:11 -0000 1.10
+++ SlideTokenWrapper.java 23 Jun 2004 09:57:14 -0000 1.11
@@ -52,7 +52,8 @@
*/
public SlideTokenWrapper(SlideToken token, boolean forceStoreEnlistment) {
this.wrappedToken = token;
- this.forceStoreEnlistment = forceStoreEnlistment;
+ // FIXME
+ this.forceStoreEnlistment = true;// forceStoreEnlistment;
this.forceSecurity = token.isForceSecurity();
this.forceLock = token.isForceLock();
}
@@ -332,5 +333,15 @@
public Boolean checkMatchPrincipalCache(SubjectNode checkSubject, SubjectNode matchSubject) {
return wrappedToken.checkMatchPrincipalCache(checkSubject, matchSubject);
}
+
+ public boolean isExternalTransaction() {
+ return wrappedToken.isExternalTransaction();
+ }
+
+
+ public void setExternalTx() {
+ wrappedToken.setExternalTx();
+ }
+
}
1.14 +107 -35 jakarta-slide/src/stores/org/apache/slide/store/txfile/TxXMLFileDescriptorsStore.java
Index: TxXMLFileDescriptorsStore.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/txfile/TxXMLFileDescriptorsStore.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- TxXMLFileDescriptorsStore.java 10 May 2004 09:48:41 -0000 1.13
+++ TxXMLFileDescriptorsStore.java 23 Jun 2004 09:57:14 -0000 1.14
@@ -59,8 +59,10 @@
extends AbstractTxFileStoreService
implements NodeStore, LockStore, RevisionDescriptorsStore, RevisionDescriptorStore, SecurityStore {
- protected static final String LOG_CHANNEL = TxFileContentStore.class.getName();
+ protected static final String LOG_CHANNEL = "file-meta-store";
+ protected static final int DEBUG_LEVEL = Logger.DEBUG;
+
protected static final String ENCODING_PARAMETER = "encoding";
protected static final String DEFER_SAVING_PARAMETER = "defer-saving";
@@ -68,6 +70,9 @@
protected String characterEncoding = "UTF-8"; // a save choice
protected boolean deferSaving = false; // the save choice
+ protected Map suspendedContexts = new HashMap();
+ protected Map activeContexts = new HashMap();
+
public void setParameters(Hashtable parameters)
throws ServiceParameterErrorException, ServiceParameterMissingException {
@@ -119,6 +124,10 @@
xfd.storeObject(object);
if (deferSaving) {
xfd.registerForSaving();
+ TxContext txContext = getActiveTxContext();
+ if (txContext != null) {
+ txContext.register(uri, xfd);
+ }
} else {
xfd.save();
}
@@ -131,6 +140,12 @@
public void removeObject(Uri uri, ObjectNode object) throws ServiceAccessException, ObjectNotFoundException {
XMLResourceDescriptor xfd = getFileDescriptor(uri);
xfd.delete();
+ if (deferSaving) {
+ TxContext txContext = getActiveTxContext();
+ if (txContext != null) {
+ txContext.deregister(uri);
+ }
+ }
}
/*
@@ -377,6 +392,16 @@
return "TxXMLFileDescriptorsStore at " + storeDir + " working on " + workDir;
}
+ public synchronized void commit(Xid xid, boolean onePhase) throws XAException {
+ super.commit(xid, onePhase);
+ activeContexts.remove(XidWrapper.wrap(xid));
+ }
+
+ public synchronized void rollback(Xid xid) throws XAException {
+ super.rollback(xid);
+ activeContexts.remove(XidWrapper.wrap(xid));
+ }
+
public synchronized int prepare(Xid xid) throws XAException {
Object txId = XidWrapper.wrap(xid);
getLogger().log(
@@ -386,7 +411,7 @@
try {
if (deferSaving) {
// save all descriptors registered for saving
- TxContext txContext = getActiveTxContext();
+ TxContext txContext = (TxContext) activeContexts.get(txId);
// really should not, but only to be sure...
if (txContext != null) {
try {
@@ -406,6 +431,11 @@
Logger.CRITICAL);
throw new XAException(sae.toString());
}
+ } else {
+ getLogger().log(
+ "Thread " + Thread.currentThread() + " could prepare *unknown* transaction branch " + txId,
+ LOG_CHANNEL,
+ Logger.WARNING);
}
}
int status = rm.prepareTransaction(txId);
@@ -427,22 +457,55 @@
}
}
+ public synchronized void end(Xid xid, int flags) throws XAException {
+ if (getActiveTxId() == null) {
+ throw new XAException(XAException.XAER_INVAL);
+ }
+ Object txId = XidWrapper.wrap(xid);
+ Thread currentThread = Thread.currentThread();
+ getLogger().log(
+ "Thread "
+ + currentThread
+ + (flags == TMSUSPEND ? " suspends" : flags == TMFAIL ? " fails" : " ends")
+ + " work on behalf of transaction branch "
+ + txId,
+ LOG_CHANNEL,
+ DEBUG_LEVEL);
+
+ switch (flags) {
+ case TMSUSPEND :
+ suspendedContexts.put(txId, getActiveTxContext());
+ activeTransactionBranch.set(null);
+ break;
+ case TMFAIL :
+ try {
+ rm.markTransactionForRollback(XidWrapper.wrap(xid));
+ } catch (ResourceManagerException e) {
+ throw createXAException(e);
+ }
+ activeTransactionBranch.set(null);
+ break;
+ case TMSUCCESS :
+ activeTransactionBranch.set(null);
+ break;
+ }
+ }
+
public synchronized void start(Xid xid, int flags) throws XAException {
Xid txId = XidWrapper.wrap(xid);
+ Thread currentThread = Thread.currentThread();
getLogger().log(
"Thread "
- + Thread.currentThread()
- + " starts work on behalf of transaction branch "
- + txId
- + " with flags "
- + flags,
+ + currentThread
+ + (flags == TMNOFLAGS ? " starts" : flags == TMJOIN ? " joins" : " resumes")
+ + " work on behalf of transaction branch "
+ + txId,
LOG_CHANNEL,
- Logger.DEBUG);
+ DEBUG_LEVEL);
switch (flags) {
// a new transaction
case TMNOFLAGS :
- getLogger().log("Starting new transaction branch", LOG_CHANNEL, Logger.DEBUG);
if (getActiveTxId() != null) {
throw new XAException(XAException.XAER_INVAL);
}
@@ -450,12 +513,12 @@
rm.startTransaction(txId);
TxContext txContext = new TxContext(txId);
activeTransactionBranch.set(txContext);
+ activeContexts.put(txId, txContext);
} catch (ResourceManagerException e) {
throw createXAException(e);
}
break;
case TMJOIN :
- getLogger().log("Thread of control joins known transaction branch", LOG_CHANNEL, Logger.DEBUG);
if (getActiveTxId() != null) {
throw new XAException(XAException.XAER_INVAL);
}
@@ -468,11 +531,17 @@
}
TxContext txContext = new TxContext(txId);
activeTransactionBranch.set(txContext);
- activeTransactionBranch.set(txId);
+ activeContexts.put(txId, txContext);
break;
case TMRESUME :
- getLogger().log("Thread of control resume work on known transaction branch", LOG_CHANNEL, Logger.DEBUG);
- // XXX we do not suspend, so we do not resume
+ if (getActiveTxId() != null) {
+ throw new XAException(XAException.XAER_INVAL);
+ }
+ txContext = (TxContext) suspendedContexts.get(txId);
+ if (txContext == null) {
+ throw new XAException(XAException.XAER_NOTA);
+ }
+ activeTransactionBranch.set(txContext);
break;
}
}
@@ -487,28 +556,23 @@
* Either returns a cached file descriptor or loads it from DB
*/
protected XMLResourceDescriptor getFileDescriptor(Uri uri) throws ServiceAccessException, ObjectNotFoundException {
- try {
- TxContext txContext = getActiveTxContext();
- XMLResourceDescriptor xfd;
- if (txContext != null) {
- xfd = txContext.lookup(uri);
- if (xfd == null) {
- Object txId = txContext.xid;
- xfd = new XMLResourceDescriptor(uri, this, rm, txId, characterEncoding);
- xfd.load();
- if (txId != null) {
- txContext.register(uri, xfd);
- }
- }
- } else {
- xfd = new XMLResourceDescriptor(uri, this, rm, null, characterEncoding);
+ TxContext txContext = getActiveTxContext();
+ XMLResourceDescriptor xfd;
+ if (txContext != null) {
+ xfd = txContext.lookup(uri);
+ if (xfd == null) {
+ Object txId = txContext.xid;
+ xfd = new XMLResourceDescriptor(uri, this, rm, txId, characterEncoding);
xfd.load();
+ if (txId != null) {
+ txContext.register(uri, xfd);
+ }
}
- return xfd;
- } catch (ServiceAccessException e) {
- throwInternalError(e, uri.toString());
- return null; // XXX
+ } else {
+ xfd = new XMLResourceDescriptor(uri, this, rm, null, characterEncoding);
+ xfd.load();
}
+ return xfd;
}
protected TxContext getActiveTxContext() {
@@ -521,6 +585,10 @@
return (context == null ? null : context.xid);
}
+ protected String getLogChannel() {
+ return LOG_CHANNEL;
+ }
+
private static class TxContext {
public Xid xid;
public Map descriptors = new HashMap();
@@ -531,6 +599,10 @@
public void register(Uri uri, XMLResourceDescriptor xfd) {
descriptors.put(uri, xfd);
+ }
+
+ public void deregister(Uri uri) {
+ descriptors.remove(uri);
}
public XMLResourceDescriptor lookup(Uri uri) {
1.8 +8 -6 jakarta-slide/src/stores/org/apache/slide/store/txfile/TxFileContentStore.java
Index: TxFileContentStore.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/txfile/TxFileContentStore.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- TxFileContentStore.java 25 Feb 2004 15:14:27 -0000 1.7
+++ TxFileContentStore.java 23 Jun 2004 09:57:14 -0000 1.8
@@ -45,8 +45,8 @@
*/
public class TxFileContentStore extends AbstractTxFileStoreService implements ContentStore {
- protected static final String LOG_CHANNEL = TxFileContentStore.class.getName();
-
+ protected static final String LOG_CHANNEL = "file-content-store";
+
public NodeRevisionContent retrieveRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException, RevisionNotFoundException {
@@ -156,5 +156,7 @@
return "TxContentFileStore at " + storeDir + " working on " + workDir;
}
-
+ protected String getLogChannel() {
+ return LOG_CHANNEL;
+ }
}
1.13 +56 -55 jakarta-slide/src/stores/org/apache/slide/store/txfile/AbstractTxFileStoreService.java
Index: AbstractTxFileStoreService.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/txfile/AbstractTxFileStoreService.java,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- AbstractTxFileStoreService.java 10 May 2004 08:23:26 -0000 1.12
+++ AbstractTxFileStoreService.java 23 Jun 2004 09:57:14 -0000 1.13
@@ -55,7 +55,7 @@
*/
public abstract class AbstractTxFileStoreService extends AbstractServiceBase implements Status {
- protected static final String LOG_CHANNEL = AbstractTxFileStoreService.class.getName();
+ protected static final int DEBUG_LEVEL = Logger.DEBUG;
protected static final String STORE_DIR_PARAMETER = "rootpath";
protected static final String WORK_DIR_PARAMETER = "workpath";
@@ -98,7 +98,7 @@
if (urlEncodePathString != null) {
urlEncodePath = "true".equals(urlEncodePathString);
}
-
+
rm =
new FileResourceManager(
storeDir,
@@ -109,7 +109,7 @@
getLogger().log(
"File Store configured to " + storeDir + ", working directory " + workDir,
- LOG_CHANNEL,
+ getLogChannel(),
Logger.INFO);
String timeoutString = (String) parameters.get(TIMEOUT_PARAMETER);
@@ -117,11 +117,11 @@
try {
int timeout = Integer.parseInt(timeoutString);
rm.setDefaultTransactionTimeout(timeout * 1000);
- getLogger().log("Set timeout to " + timeoutString, LOG_CHANNEL, Logger.INFO);
+ getLogger().log("Set timeout to " + timeoutString, getLogChannel(), Logger.INFO);
} catch (NumberFormatException nfe) {
getLogger().log(
"Can not set timeout, '" + timeoutString + "' must be an integer!",
- LOG_CHANNEL,
+ getLogChannel(),
Logger.WARNING);
}
}
@@ -193,10 +193,11 @@
public synchronized int prepare(Xid xid) throws XAException {
Object txId = XidWrapper.wrap(xid);
+ Thread currentThread = Thread.currentThread();
getLogger().log(
- "Thread " + Thread.currentThread() + " prepares transaction branch " + txId,
- LOG_CHANNEL,
- Logger.DEBUG);
+ "Thread " + currentThread + " prepares transaction branch " + txId,
+ getLogChannel(),
+ DEBUG_LEVEL);
try {
int status = rm.prepareTransaction(txId);
switch (status) {
@@ -209,9 +210,9 @@
}
} catch (ResourceManagerException e) {
getLogger().log(
- "Thread " + Thread.currentThread() + " failed to prepare transaction branch " + txId,
+ "Thread " + currentThread + " failed to prepare transaction branch " + txId,
e,
- LOG_CHANNEL,
+ getLogChannel(),
Logger.CRITICAL);
throw createXAException(e);
}
@@ -219,19 +220,20 @@
public synchronized void rollback(Xid xid) throws XAException {
Object txId = XidWrapper.wrap(xid);
+ Thread currentThread = Thread.currentThread();
getLogger().log(
- "Thread " + Thread.currentThread() + " rolls back transaction branch " + txId,
- LOG_CHANNEL,
- Logger.DEBUG);
+ "Thread " + currentThread + " rolls back transaction branch " + txId,
+ getLogChannel(),
+ DEBUG_LEVEL);
try {
rm.rollbackTransaction(txId);
activeTransactionBranch.set(null);
} catch (ResourceManagerException e) {
getLogger().log(
- "Thread " + Thread.currentThread() + " failed to roll back transaction branch " + txId,
+ "Thread " + currentThread + " failed to roll back transaction branch " + txId,
e,
- LOG_CHANNEL,
+ getLogChannel(),
Logger.CRITICAL);
throw createXAException(e);
}
@@ -239,10 +241,11 @@
public synchronized void commit(Xid xid, boolean onePhase) throws XAException {
Object txId = XidWrapper.wrap(xid);
+ Thread currentThread = Thread.currentThread();
getLogger().log(
- "Thread " + Thread.currentThread() + " commits transaction branch " + txId,
- LOG_CHANNEL,
- Logger.DEBUG);
+ "Thread " + currentThread + " commits transaction branch " + txId,
+ getLogChannel(),
+ DEBUG_LEVEL);
try {
if (!onePhase && rm.getTransactionState(txId) != STATUS_PREPARED) {
@@ -253,9 +256,9 @@
activeTransactionBranch.set(null);
} catch (ResourceManagerException e) {
getLogger().log(
- "Thread " + Thread.currentThread() + " failed to commit transaction branch " + txId,
+ "Thread " + currentThread + " failed to commit transaction branch " + txId,
e,
- LOG_CHANNEL,
+ getLogChannel(),
Logger.CRITICAL);
throw createXAException(e);
}
@@ -263,26 +266,21 @@
public synchronized void end(Xid xid, int flags) throws XAException {
Object txId = XidWrapper.wrap(xid);
+ Thread currentThread = Thread.currentThread();
getLogger().log(
"Thread "
- + Thread.currentThread()
- + " ends work on behalf of transaction branch "
- + txId
- + " with flags "
- + flags,
- LOG_CHANNEL,
- Logger.DEBUG);
+ + currentThread
+ + (flags == TMSUSPEND ? " suspends" : flags == TMFAIL ? " fails" : " ends")
+ + " work on behalf of transaction branch "
+ + txId,
+ getLogChannel(),
+ DEBUG_LEVEL);
switch (flags) {
case TMSUSPEND :
- getLogger().log(
- "Thread of control suspends work on behalf of transaction branch",
- LOG_CHANNEL,
- Logger.DEBUG);
- // XXX we do not resume, so we do not suspend
+ activeTransactionBranch.set(null);
break;
case TMFAIL :
- getLogger().log("Transaction branch failed", LOG_CHANNEL, Logger.DEBUG);
try {
rm.markTransactionForRollback(XidWrapper.wrap(xid));
} catch (ResourceManagerException e) {
@@ -290,7 +288,6 @@
}
break;
case TMSUCCESS :
- getLogger().log("Transaction branch successfully completed", LOG_CHANNEL, Logger.DEBUG);
// not ineresting for us
break;
}
@@ -298,20 +295,19 @@
public synchronized void start(Xid xid, int flags) throws XAException {
Object txId = XidWrapper.wrap(xid);
+ Thread currentThread = Thread.currentThread();
getLogger().log(
"Thread "
- + Thread.currentThread()
- + " starts work on behalf of transaction branch "
- + txId
- + " with flags "
- + flags,
- LOG_CHANNEL,
- Logger.DEBUG);
+ + currentThread
+ + (flags == TMNOFLAGS ? " starts" : flags == TMJOIN ? " joins" : " resumes")
+ + " work on behalf of transaction branch "
+ + txId,
+ getLogChannel(),
+ DEBUG_LEVEL);
switch (flags) {
// a new transaction
case TMNOFLAGS :
- getLogger().log("Starting new transaction branch", LOG_CHANNEL, Logger.DEBUG);
if (getActiveTxId() != null) {
throw new XAException(XAException.XAER_INVAL);
}
@@ -323,7 +319,6 @@
}
break;
case TMJOIN :
- getLogger().log("Thread of control joins known transaction branch", LOG_CHANNEL, Logger.DEBUG);
if (getActiveTxId() != null) {
throw new XAException(XAException.XAER_INVAL);
}
@@ -337,8 +332,7 @@
activeTransactionBranch.set(txId);
break;
case TMRESUME :
- getLogger().log("Thread of control resume work on known transaction branch", LOG_CHANNEL, Logger.DEBUG);
- // XXX we do not suspend, so we do not resume
+ activeTransactionBranch.set(txId);
break;
}
}
@@ -353,7 +347,7 @@
+ txId
+ " for rollback. Cause: "
+ cause,
- LOG_CHANNEL,
+ getLogChannel(),
Logger.WARNING);
try {
@@ -376,7 +370,7 @@
+ txId
+ " for rollback. Cause: "
+ cause,
- LOG_CHANNEL,
+ getLogChannel(),
Logger.WARNING);
try {
@@ -413,7 +407,7 @@
+ " marked transaction branch "
+ txId
+ " for rollback",
- LOG_CHANNEL,
+ getLogChannel(),
Logger.INFO);
throw new ServiceAccessException(this, new ConflictException(uri));
@@ -421,11 +415,17 @@
} else {
getLogger().log(
- "Thread " + Thread.currentThread() + " marking transaction branch " + txId + " for rollback",
+ "Could not process URI '"
+ + uri
+ + "'! Thread "
+ + Thread.currentThread()
+ + " marking transaction branch "
+ + txId
+ + " for rollback",
cause,
- LOG_CHANNEL,
+ getLogChannel(),
Logger.WARNING);
-
+
if (txId != null) {
try {
rm.markTransactionForRollback(txId);
@@ -444,7 +444,7 @@
return txId;
}
- protected XAException createXAException(ResourceManagerException e) {
+ protected XAException createXAException(ResourceManagerException e) {
if (e.getStatus() == ResourceManagerException.ERR_DUP_TX) {
return new XAException(XAException.XAER_DUPID);
} else if (e.getStatus() == ResourceManagerException.ERR_TXID_INVALID) {
@@ -454,4 +454,5 @@
}
}
+ abstract protected String getLogChannel();
}
1.58 +7 -4 jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavServlet.java
Index: WebdavServlet.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavServlet.java,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- WebdavServlet.java 2 Apr 2004 07:30:28 -0000 1.57
+++ WebdavServlet.java 23 Jun 2004 09:57:14 -0000 1.58
@@ -183,8 +183,11 @@
private boolean isCollection(HttpServletRequest req) {
SlideToken slideToken = new SlideTokenWrapper(WebdavUtils.getSlideToken(req), false);
+ // FIXME
+ slideToken.setForceStoreEnlistment(false);
slideToken.setForceSecurity(false);
slideToken.setForceLock(false);
+
return WebdavUtils.isCollection(token, slideToken, WebdavUtils.getRelativePath(req, (WebdavServletConfig)getServletConfig()));
}
1.31 +59 -22 jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AbstractWebdavMethod.java
Index: AbstractWebdavMethod.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/AbstractWebdavMethod.java,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- AbstractWebdavMethod.java 18 Jun 2004 16:05:46 -0000 1.30
+++ AbstractWebdavMethod.java 23 Jun 2004 09:57:14 -0000 1.31
@@ -37,6 +37,9 @@
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+
import org.apache.slide.common.Domain;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.common.NestedSlideException;
@@ -59,6 +62,7 @@
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.Structure;
+import org.apache.slide.transaction.ExternalTransactionContext;
import org.apache.slide.util.Messages;
import org.apache.slide.util.XMLValue;
import org.apache.slide.util.logger.Logger;
@@ -302,25 +306,43 @@
parseRequestHeaders();
boolean transactionIsStarted = false;
+ boolean isExternalTx = false;
+ String txId = null;
try {
parseRequest();
- if (methodNeedsTransactionSupport()) {
+
+ ExternalTransactionContext externalTransaction = null;
+
+ txId = requestHeaders.getTxId();
+ if (txId != null) {
+ externalTransaction = ExternalTransactionContext.lookupContext(txId);
+ if (externalTransaction != null) {
+ Domain.log("Using external transaction " + txId, LOG_CHANNEL, Logger.INFO);
+ isExternalTx = true;
+ slideToken.setExternalTx();
+ // pure reads must be guaranteed to be inside transaction as well
+ slideToken.setForceStoreEnlistment(true);
+ Transaction tx = externalTransaction.getTransaction();
+ token.getTransactionManager().resume(tx);
+ transactionIsStarted = true;
+ }
+ }
+
+ if (!isExternalTx && methodNeedsTransactionSupport()) {
token.begin();
transactionIsStarted = true;
}
-
+
// clear expired lock-tokens
- try {
- UnlockListener listener =
- new UnlockListenerImpl( slideToken, token, config, req, resp );
- lock.clearExpiredLocks( slideToken, requestUri, listener );
-
- // if the URI has no more locks associated to it and is
- // a lock-null resource, we must attempt to delete it
-
- Enumeration locks = lock.enumerateLocks(slideToken, requestUri);
- if (!locks.hasMoreElements()) {
-
+ UnlockListener listener = new UnlockListenerImpl(slideToken, token, config, req, resp);
+ lock.clearExpiredLocks(slideToken, requestUri, listener);
+
+ // if the URI has no more locks associated to it and is
+ // a lock-null resource, we must attempt to delete it
+
+ Enumeration locks = lock.enumerateLocks(slideToken, requestUri);
+ if (!locks.hasMoreElements()) {
+ try {
NodeRevisionDescriptors revisionDescriptors = content.retrieve(slideToken, requestUri);
NodeRevisionDescriptor revisionDescriptor = content.retrieve(slideToken, revisionDescriptors);
if (isLockNull(revisionDescriptor)) {
@@ -329,36 +351,51 @@
ObjectNode node = structure.retrieve(slideToken, requestUri);
structure.remove(slideToken, node);
}
+ } catch (ObjectNotFoundException onfe) {
}
-
}
- catch (SlideException e) {}
executeRequest();
- if (methodNeedsTransactionSupport()) {
+ if (!isExternalTx && transactionIsStarted) {
token.commit();
transactionIsStarted = false;
}
} catch (WebdavException ex) {
// Ignore the WebDav Exception and assume that the response code
// is already set.
+ } catch (SlideException ex) {
+ int statusCode = getErrorCode( ex );
+ sendError( statusCode, ex );
+ throw new WebdavException( statusCode );
} catch (Exception ex) {
token.getLogger().log(ex,LOG_CHANNEL,Logger.ERROR);
int statusCode = WebdavStatus.SC_INTERNAL_SERVER_ERROR;
sendError( statusCode, ex );
throw new WebdavException( statusCode );
} finally {
- if (transactionIsStarted && methodNeedsTransactionSupport()) {
+ if (!isExternalTx && transactionIsStarted) {
// Something went wrong, we are here and the TA is still open
try {
token.rollback();
} catch (Exception e) {
}
}
+ if (isExternalTx) {
+ Transaction transaction;
+ try {
+ if (token.getStatus() == javax.transaction.Status.STATUS_ACTIVE) {
+ transaction = token.getTransactionManager().suspend();
+ if (transaction != null) {
+ ExternalTransactionContext.registerContext(txId, transaction);
+ }
+ }
+ } catch (SystemException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
}
-
}
-
// --------------------------------------------------------- Public Methods
1.3 +27 -4 jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/TransactionMethod.java
Index: TransactionMethod.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/TransactionMethod.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- TransactionMethod.java 5 Jun 2004 12:20:19 -0000 1.2
+++ TransactionMethod.java 23 Jun 2004 09:57:15 -0000 1.3
@@ -23,17 +23,20 @@
package org.apache.slide.webdav.method;
+import javax.transaction.Status;
+import javax.transaction.Transaction;
+
import org.apache.slide.common.Domain;
import org.apache.slide.common.NamespaceAccessToken;
import org.apache.slide.util.logger.Logger;
import org.apache.slide.webdav.WebdavException;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.util.TransactionConstants;
+import org.apache.slide.transaction.ExternalTransactionContext;
import org.apache.util.WebdavStatus;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
-
/**
* Subscribe Method.
*
@@ -73,6 +76,22 @@
String txId = requestHeaders.getTxId();
String method = requestHeaders.getTxMethod();
Domain.log("Transaction method called with method="+method+", txId: "+txId, LOG_CHANNEL, Logger.INFO);
+
+ if (method.equalsIgnoreCase("begin")) {
+ token.begin();
+ Transaction transaction = token.getTransactionManager().suspend();
+ ExternalTransactionContext.registerContext(txId, transaction);
+ slideToken.setExternalTx();
+ } else if (method.equalsIgnoreCase("commit")) {
+ // note that transaction has already been resumed by AbstractWebdavMethod
+ token.commit();
+ ExternalTransactionContext.deregisterContext(txId);
+ } else if (method.equalsIgnoreCase("rollback")) {
+ // note that transaction has already been resumed by AbstractWebdavMethod
+ token.rollback();
+ ExternalTransactionContext.deregisterContext(txId);
+ }
+
resp.setHeader(H_TRANSACTION_ID, txId);
resp.setStatus(WebdavStatus.SC_OK);
} catch (Exception e) {
@@ -81,4 +100,8 @@
throw new WebdavException( statusCode );
}
}
+
+ protected boolean methodNeedsTransactionSupport() {
+ return false;
+}
}
1.2 +84 -0 jakarta-slide/src/share/org/apache/slide/transaction/ExternalTransactionContext.java
1.46 +17 -7 jakarta-slide/src/share/org/apache/slide/structure/StructureImpl.java
Index: StructureImpl.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/StructureImpl.java,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- StructureImpl.java 5 Jun 2004 12:20:19 -0000 1.45
+++ StructureImpl.java 23 Jun 2004 09:57:15 -0000 1.46
@@ -339,8 +339,13 @@
}
if (parentObject != null) {
- // lock exclusively before anyone can get a read lock
- namespace.getUri(token, parentObject.getUri()).getStore().exclusiveTransientLock(parentObject.getUri().toString());
+ // lock exclusively before anyone can get a read lock
+ // do not lock in external transaction because this might lead to distributed deadlocks
+ // between Slide and store
+ if (!token.isExternalTransaction()) {
+ namespace.getUri(token, parentObject.getUri()).getStore().exclusiveTransientLock(
+ parentObject.getUri().toString());
+ }
securityHelper
.checkCredentials(token, courObject, namespaceConfig
@@ -531,7 +536,12 @@
Uri curUri = namespace.getUri(token, nodeToDelete.getUri());
Uri parentUri = curUri.getParentUri();
- parentUri.getStore().exclusiveTransientLock(parentUri.toString());
+ // lock exclusively before anyone can get a read lock
+ // do not lock in external transaction because this might lead to distributed deadlocks
+ // between Slide and store
+ if (!token.isExternalTransaction()) {
+ parentUri.getStore().exclusiveTransientLock(parentUri.toString());
+ }
ObjectNode parentNode = parentUri.getStore().retrieveObject(parentUri);
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org