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/10/25 23:13:28 UTC
cvs commit: jakarta-slide/src/webdav/server/org/apache/slide/webdav/method PutMethod.java AbstractWebdavMethod.java FineGrainedLockingMethod.java GetMethod.java
ozeigermann 2004/10/25 14:13:28
Modified: src/webdav/server/org/apache/slide/webdav/method
PutMethod.java AbstractWebdavMethod.java
FineGrainedLockingMethod.java GetMethod.java
Log:
Added infrastructure for fine grained locks part #2:
Now PUT and GET should acquired all required locks and log what
they to to the INFO level for inspection. Will be changed to debug later
Revision Changes Path
1.84 +16 -5 jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java
Index: PutMethod.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -r1.83 -r1.84
--- PutMethod.java 12 Sep 2004 17:47:50 -0000 1.83
+++ PutMethod.java 25 Oct 2004 21:13:27 -0000 1.84
@@ -63,7 +63,7 @@
*/
public class PutMethod
extends AbstractWebdavMethod
- implements DeltavConstants, WriteMethod {
+ implements DeltavConstants, WriteMethod, FineGrainedLockingMethod {
// ----------------------------------------------------- Instance Variables
@@ -91,7 +91,18 @@
super(token, config);
}
-
+ /**
+ * @see org.apache.slide.webdav.method.FineGrainedLockingMethod#acquireFineGrainLocks()
+ */
+ public void acquireFineGrainLocks() {
+ acquireStandardLocks(resourcePath);
+ // lock history folder in case we have auto versioning turned on
+ acquireHistoryLocks(resourcePath);
+ // changes this and parent
+ acquireLock(resourcePath, WRITE_LOCK);
+ acquireParentLock(resourcePath, WRITE_LOCK);
+ }
+
// ------------------------------------------------------ Protected Methods
1.54 +146 -30 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.53
retrieving revision 1.54
diff -u -r1.53 -r1.54
--- AbstractWebdavMethod.java 24 Oct 2004 20:38:21 -0000 1.53
+++ AbstractWebdavMethod.java 25 Oct 2004 21:13:28 -0000 1.54
@@ -32,9 +32,11 @@
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
+import java.util.Set;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
@@ -43,9 +45,10 @@
import javax.transaction.Transaction;
import org.apache.commons.transaction.locking.GenericLock;
+import org.apache.commons.transaction.locking.GenericLockManager;
+import org.apache.commons.transaction.locking.LockManager;
import org.apache.commons.transaction.locking.MultiLevelLock;
import org.apache.commons.transaction.util.PrintWriterLogger;
-
import org.apache.slide.authenticate.CredentialsToken;
import org.apache.slide.common.Domain;
import org.apache.slide.common.NamespaceAccessToken;
@@ -68,6 +71,7 @@
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.Structure;
import org.apache.slide.transaction.ExternalTransactionContext;
+import org.apache.slide.util.Configuration;
import org.apache.slide.util.Messages;
import org.apache.slide.util.XMLValue;
import org.apache.slide.util.logger.Logger;
@@ -151,13 +155,19 @@
new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
};
+ protected static final int READ_LOCK = 1;
+ protected static final int WRITE_LOCK = 2;
+
// global read/write lock to allow for deadlock-free access
- private static final MultiLevelLock GLOBAL_LOCK = new GenericLock("global", 2, new PrintWriterLogger(
+ private static final MultiLevelLock GLOBAL_LOCK = new GenericLock("global", WRITE_LOCK, new PrintWriterLogger(
new PrintWriter(System.out), LOG_CHANNEL, false));
// monitor to assure all (fine grain) locks are acquired in an atomic block
private static final Object ATOMIC_LOCKING_MONITOR = new Object();
+ private static final LockManager FINE_LOCK_MANAGER = new GenericLockManager(WRITE_LOCK, new PrintWriterLogger(
+ new PrintWriter(System.out), LOG_CHANNEL, false));
+
// ----------------------------------------------------- Instance Variables
@@ -241,6 +251,11 @@
protected SlideToken slideToken;
/**
+ * Fine grain locks acquired by this method.
+ */
+ protected Set locks = new HashSet();
+
+ /**
* The request content (XML) Document.
*/
private Document requestContentDocument = null;
@@ -402,31 +417,33 @@
sendError( statusCode, ex );
throw new WebdavException( statusCode );
} finally {
- if (!slideToken.isExternalTransaction() && transactionIsStarted) {
- // Something went wrong, we are here and the TA is still open
- try {
- token.rollback();
- } catch (Exception e) {
- // TODO
- e.printStackTrace();
+ try {
+ if (!slideToken.isExternalTransaction() && transactionIsStarted) {
+ // Something went wrong, we are here and the TA is still
+ // open
+ try {
+ token.rollback();
+ } catch (Exception e) {
+ token.getLogger().log(e,LOG_CHANNEL,Logger.ERROR);
+ }
}
- }
- if (slideToken.isExternalTransaction()) {
- Transaction transaction;
- try {
- if (token.getStatus() == javax.transaction.Status.STATUS_ACTIVE) {
- transaction = token.getTransactionManager().suspend();
- if (transaction != null) {
- ExternalTransactionContext.registerContext(txId, transaction);
+ if (slideToken.isExternalTransaction()) {
+ 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) {
+ token.getLogger().log(e,LOG_CHANNEL,Logger.ERROR);
}
- } catch (SystemException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
}
- }
- if (globalLockObtained) {
- releaseGlobalLocks();
+ } finally {
+ if (globalLockObtained) {
+ releaseGlobalLocks();
+ }
}
}
}
@@ -779,9 +796,25 @@
return "true".equalsIgnoreCase( getConfig().getInitParameter(name) );
}
+ protected boolean isAutoCreateUsers() {
+ return ("true".equalsIgnoreCase(token.getNamespaceConfig().getParameter("auto-create-users")));
+ }
+
+ protected String getUsersPath() {
+ return token.getNamespaceConfig().getUsersPath();
+ }
+
+ protected String getRolesPath() {
+ return token.getNamespaceConfig().getRolesPath();
+ }
+
+ protected String getHistoryPath() {
+ return Domain.getParameter(I_HISTORYPATH, I_HISTORYPATH_DEFAULT);
+ }
+
/**
- * Checks whether the hack that restricts the size of collections in
- * the history collection is configured to be used.
+ * Checks whether the hack that restricts the size of collections in the
+ * history collection is configured to be used.
*/
protected boolean useHistoryCollectionHack() {
return "true".equalsIgnoreCase(token.getNamespaceConfig().getParameter("history-collection-hack"));
@@ -843,13 +876,96 @@
protected void releaseGlobalLocks() {
GLOBAL_LOCK.release(this);
- if (isFineGrainSequential()) {
+ if (this instanceof FineGrainedLockingMethod && isFineGrainSequential()) {
// no need to do this atomically
- ((FineGrainedLockingMethod)this).releaseFineGrainLocks();
+ releaseLocks();
}
}
+ protected void acquireHistoryLocks(String uri) {
+ // some writing request have an additional request to the history
+ // folder if auto versioning is turned on
+ if (Configuration.useVersionControl() && isAutoVersionControl(uri) && !isExcludedForVersionControl(uri)) {
+ acquireLock(getHistoryPath(), WRITE_LOCK);
+ }
+
+ }
+
+ protected void acquireStandardLocks(String uri) {
+ // all requests need read access from uri to root
+ List paths = getPathsToRoot(uri);
+ acquireLock(paths, READ_LOCK);
+ // all requests need read access to users and roles and even write
+ // when users are auto created
+ String usersPath = getUsersPath();
+ String rolesPath = getRolesPath();
+ acquireLock(usersPath, isAutoCreateUsers() ? WRITE_LOCK : READ_LOCK);
+ acquireLock(rolesPath, READ_LOCK);
+ // XXX adapt explicite calls to users and roles to general lock
+ // above
+ // this effectively gives a *single* lock for the users and roles folder
+ // each
+ if (uri.startsWith(getUsersPath())) {
+ acquireLock(usersPath, this instanceof WriteMethod ? WRITE_LOCK : READ_LOCK);
+ } else if (uri.startsWith(rolesPath)) {
+ acquireLock(rolesPath, this instanceof WriteMethod ? WRITE_LOCK : READ_LOCK);
+ }
+ // XXX adapt explicite read to history folder to general lock
+ // above
+ // this effectively gives a *single* lock for history folder
+ if (Configuration.useVersionControl() && uri.startsWith(getHistoryPath())) {
+ acquireLock(getHistoryPath(), READ_LOCK);
+ }
+ }
+
+ protected void acquireParentLock(String path, int level) {
+ int lastSlash = path.lastIndexOf('/');
+ if (lastSlash > 0) {
+ String parentPath = path.substring(0, lastSlash);
+ acquireLock(parentPath, level);
+ }
+ }
+
+ protected void acquireLock(String path, int level) {
+ MultiLevelLock lock = FINE_LOCK_MANAGER.atomicGetOrCreateLock(path);
+ try {
+ lock.acquire(this, level, true, true, Long.MAX_VALUE);
+ } catch (InterruptedException e) {
+ }
+ locks.add(lock);
+ token.getLogger().log((level == READ_LOCK ? "Read" : "Write") + " locking " + path, LOG_CHANNEL, Logger.INFO);
+ }
+
+ protected void acquireLock(List paths, int level) {
+ for (Iterator i = paths.iterator(); i.hasNext();) {
+ String path = (String) i.next();
+ acquireLock(path, level);
+ }
+ }
+ protected void releaseLocks() {
+ MultiLevelLock lock;
+ for (Iterator i = locks.iterator(); i.hasNext(); ) {
+ lock = (MultiLevelLock)i.next();
+ lock.release(this);
+ token.getLogger().log("Releasing " + lock.toString(), LOG_CHANNEL, Logger.INFO);
+ }
+ }
+
+ protected List getPathsToRoot(String uri) {
+ StringTokenizer tokenizer = new StringTokenizer(uri, "/");
+ List paths = new ArrayList(tokenizer.countTokens()+1);
+
+ paths.add("/");
+
+ String path = "";
+ while (tokenizer.hasMoreTokens()) {
+ path += "/" + tokenizer.nextToken();
+ paths.add(path);
+ }
+
+ return paths;
+ }
/**
* Returns the value of an integer init parameter of the servlet.
1.2 +3 -8 jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/FineGrainedLockingMethod.java
Index: FineGrainedLockingMethod.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/FineGrainedLockingMethod.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- FineGrainedLockingMethod.java 24 Oct 2004 20:38:21 -0000 1.1
+++ FineGrainedLockingMethod.java 25 Oct 2004 21:13:28 -0000 1.2
@@ -29,13 +29,8 @@
public interface FineGrainedLockingMethod {
/**
- * Acquires all necessary fine grain locks to execute the full request. Must be executed atomically.
+ * Acquires all necessary fine grain locks to execute the full request.
*/
void acquireFineGrainLocks();
-
- /**
- * Releases all fine grain locks of this method.
- */
- void releaseFineGrainLocks();
}
1.53 +10 -4 jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java
Index: GetMethod.java
===================================================================
RCS file: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -r1.52 -r1.53
--- GetMethod.java 23 Sep 2004 08:19:14 -0000 1.52
+++ GetMethod.java 25 Oct 2004 21:13:28 -0000 1.53
@@ -61,7 +61,7 @@
* GET method.
*
*/
-public class GetMethod extends AbstractWebdavMethod implements ReadMethod {
+public class GetMethod extends AbstractWebdavMethod implements ReadMethod, FineGrainedLockingMethod {
// -------------------------------------------------------------- Constants
@@ -122,6 +122,12 @@
super(token, config);
}
+ /**
+ * @see org.apache.slide.webdav.method.FineGrainedLockingMethod#acquireFineGrainLocks()
+ */
+ public void acquireFineGrainLocks() {
+ acquireStandardLocks(resourcePath);
+ }
// ------------------------------------------------------ Protected Methods
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org