wburrows 2004/12/07 17:33:52
Modified: src/webdav/server/org/apache/slide/webdav/method
AbstractWebdavMethod.java
Log:
Defect 32250: fixes to solve db deadlocks when client transaction used.
Revision Changes Path
1.66 +63 -20
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.65
retrieving revision 1.66
diff -u -r1.65 -r1.66
--- AbstractWebdavMethod.java 7 Dec 2004 17:47:47 -0000 1.65
+++ AbstractWebdavMethod.java 8 Dec 2004 01:33:52 -0000 1.66
@@ -405,23 +405,31 @@
globalLockObtained = true;
}
- try {
- // retrive to check it exists, otherwise it can't have locks
- structure.retrieve(slideToken, requestUri);
- // clear expired lock-tokens
- UnlockListenerImpl listener = new
UnlockListenerImpl(slideToken, token, config, req, resp);
- lock.clearExpiredLocks(slideToken, requestUri, listener);
-
- if (listener.getUnlockCount() > 0) {
- // If we have have cleared any lock or any lock-null
resource in
- // the previous step we commit this changes, otherwise
they will
- // be lost if executeRequest() exits with an exception
(e.g.
- // because of Not Found 404)
- token.commit();
- token.begin();
+ /*
+ * Check for object existence and cleanup locks but only if this
is
+ * not a request to finalize an external transaction. Otherwise
we are
+ * making calls to the store that require a transaction to be in
process
+ * while we're trying to commit or abort the current transaction.
+ */
+ if (!isEndofTransactionRequest()) {
+ try {
+ // retrive to check it exists, otherwise it can't have
locks
+ structure.retrieve(slideToken, requestUri);
+ // clear expired lock-tokens
+ UnlockListenerImpl listener = new
UnlockListenerImpl(slideToken, token, config, req, resp);
+ lock.clearExpiredLocks(slideToken, requestUri, listener);
+
+ if (listener.getUnlockCount() > 0) {
+ // If we have have cleared any lock or any lock-null
resource in
+ // the previous step we commit this changes,
otherwise they will
+ // be lost if executeRequest() exits with an
exception (e.g.
+ // because of Not Found 404)
+ token.commit();
+ token.begin();
+ }
+ } catch (ObjectNotFoundException e) {
+ // ignore, it can't have locks
}
- } catch (ObjectNotFoundException e) {
- // ignore, it can't have locks
}
boolean done = false;
@@ -504,8 +512,16 @@
protected void executeRedirect() throws AccessDeniedException,
LinkedObjectNotFoundException,
ObjectLockedException, RevisionDescriptorNotFoundException,
ServiceAccessException,
VetoException, WebdavException, IOException {
+
boolean responseIsRedirected = false;
- if (!requestHeaders.getApplyToRedirectRef(false)) {
+
+ /*
+ * Check whether to apply to redirect ref but only if this is not an
+ * external transaction request to commit or abort the current
transaction.
+ * Otherwise db deadlock can occur.
+ */
+ if (!requestHeaders.getApplyToRedirectRef(false)
+ && !isEndofTransactionRequest()) {
try {
NodeRevisionDescriptors revisionDescriptors
= content.retrieve(slideToken, requestUri);
@@ -551,6 +567,7 @@
// TODO not sure, but this makes nonOwnerUsesLocktoken
testcase passing
}
}
+
if (!responseIsRedirected) {
executeRequest();
}
@@ -558,6 +575,32 @@
// --------------------------------------------------------- Public
Methods
+
+ /**
+ * Returns a boolean indicating whether this request is an
+ * external transaction request to commit or abort the
+ * current transaction. These requests must be given a
+ * short path to UnlockMethod.execute() that avoids db
+ * interaction -- even reads.
+ *
+ * @return true if the current request is an external transaction commit
or abort request.
+ */
+ public boolean isEndofTransactionRequest()
+ {
+ /*
+ * if this is an UnlockMethod and has a transaction
+ * command set in the request then this request is
+ * trying to commit or abort an external transaction.
+ */
+ if (this instanceof UnlockMethod)
+ {
+ UnlockMethod meth = (UnlockMethod)this;
+ if (meth.getCommand() != UnlockMethod.NO_TRANSACTION)
+ return true;
+ }
+
+ return false;
+ }
/**
* Returns the configuration of the WebdavServlet.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]