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