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/05/06 11:17:54 UTC

cvs commit: jakarta-slide/src/share/org/apache/slide/store Store.java AbstractStore.java ExtendedStore.java

ozeigermann    2004/05/06 02:17:54

  Modified:    src/share/org/apache/slide/store Store.java
                        AbstractStore.java ExtendedStore.java
  Log:
  Added transient locks to avoid deadlocks when more than 
  one client uploads data.
  
  Revision  Changes    Path
  1.11      +12 -4     jakarta-slide/src/share/org/apache/slide/store/Store.java
  
  Index: Store.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/Store.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- Store.java	4 May 2004 12:06:26 -0000	1.10
  +++ Store.java	6 May 2004 09:17:54 -0000	1.11
  @@ -123,4 +123,12 @@
        */
       boolean useBinding();
   
  +    /**
  +     * Acquires an exclusive access lock to a resource. This lock is transient, i.e. it will
  +     * automatically be released when your transaction terminates. 
  +     * 
  +     * @param uri the URI of the resource you want to have exclusive access to 
  +     * @throws ServiceAccessException thrown if anything goes wrong, including the lock can not be acquired 
  +     */
  +    void exclusiveTransientLock(String uri) throws ServiceAccessException;
   }
  
  
  
  1.41      +8 -4      jakarta-slide/src/share/org/apache/slide/store/AbstractStore.java
  
  Index: AbstractStore.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/AbstractStore.java,v
  retrieving revision 1.40
  retrieving revision 1.41
  diff -u -r1.40 -r1.41
  --- AbstractStore.java	4 May 2004 12:06:26 -0000	1.40
  +++ AbstractStore.java	6 May 2004 09:17:54 -0000	1.41
  @@ -1612,4 +1612,8 @@
       public boolean useBinding() {
           return false;
       }
  +    
  +    public void exclusiveTransientLock(String uri) throws ServiceAccessException {
  +    }
  +
   }
  
  
  
  1.10      +83 -5     jakarta-slide/src/share/org/apache/slide/store/ExtendedStore.java
  
  Index: ExtendedStore.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/ExtendedStore.java,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- ExtendedStore.java	5 May 2004 12:07:30 -0000	1.9
  +++ ExtendedStore.java	6 May 2004 09:17:54 -0000	1.10
  @@ -24,7 +24,9 @@
   package org.apache.slide.store;
   
   import java.util.Enumeration;
  +import java.util.HashSet;
   import java.util.Hashtable;
  +import java.util.Iterator;
   import java.util.Vector;
   
   import org.apache.slide.common.ServiceAccessException;
  @@ -40,17 +42,24 @@
   import org.apache.slide.content.RevisionNotFoundException;
   import org.apache.slide.lock.LockTokenNotFoundException;
   import org.apache.slide.lock.NodeLock;
  +import org.apache.slide.macro.ConflictException;
   import org.apache.slide.security.NodePermission;
   import org.apache.slide.structure.LinkNode;
   import org.apache.slide.structure.ObjectAlreadyExistsException;
   import org.apache.slide.structure.ObjectNode;
   import org.apache.slide.structure.ObjectNotFoundException;
  -import org.apache.slide.util.*;
  +import org.apache.slide.util.ByteSizeLimitedObjectCache;
   import org.apache.slide.util.ObjectCache;
  +import org.apache.slide.util.TxLRUObjectCache;
  +import org.apache.slide.util.XidWrapper;
   
   import javax.transaction.xa.XAException;
   import javax.transaction.xa.Xid;
  +
  +import org.apache.slide.util.locking.impl.GenericLock;
  +import org.apache.slide.util.locking.impl.GenericLockManager;
   import org.apache.slide.util.logger.Logger;
  +import org.apache.slide.util.logger.StoreLogger;
   
   /**
    * Store that allows for transactional caching of data. Takes over much modified code from StandardStore.
  @@ -104,6 +113,9 @@
       protected static final String CACHE_MODE_OFF = "off";
       protected static final String DEFAULT_CACHE_MODE = CACHE_MODE_FULL;
   
  +    protected static final int DEFAULT_TLOCK_TIMEOUT = 20000; // 20 sec
  +    protected static final String TLOCK_TIMEOUT_PARAMETER = "tlock-timeout";
  +
       // there might be at least one active transaction branch per thread
       protected ThreadLocal activeTransactionBranch = new ThreadLocal();
   
  @@ -114,8 +126,17 @@
       protected TxCacheWrapper descriptorsCache;
       protected TxCacheWrapper descriptorCache;
   
  +    protected GenericLockManager lockManager;
  +    protected ThreadLocal locks = new ThreadLocal();
  +    protected long timeout;
  +
       protected boolean globalCacheOff;
   
  +
  +    public ExtendedStore() {
  +        lockManager = new GenericLockManager(1, new StoreLogger(getLogger(), LOG_CHANNEL));
  +    }
  +    
       public void setParameters(Hashtable parameters)
           throws ServiceParameterErrorException, ServiceParameterMissingException {
           super.setParameters(parameters);
  @@ -132,6 +153,17 @@
           long txContentCacheBytes = DEFAULT_TX_CONTENT_CACHE_BYTES;
           long maxByteSizePerEntry = DEFAULT_MAX_CONTENT_BYTES_PER_ENTRY;
   
  +        timeout = DEFAULT_TLOCK_TIMEOUT;
  +        String timeoutString = (String) parameters.get(TLOCK_TIMEOUT_PARAMETER);
  +        if (timeoutString != null) {
  +            try {
  +                timeout = Integer.parseInt(timeoutString) * 1000;
  +            } catch (NumberFormatException nfe) {
  +                getLogger().log("TLock timeout must be integer! Using default value", LOG_CHANNEL, Logger.WARNING);
  +            }
  +        }
  +        getLogger().log("Setting TLock timeout for store " + getName() + " to " + timeout / 1000 + " seconds", Logger.INFO);
  +
           String globalObjectCacheSizeString = (String) parameters.get(GLOBAL_OBJECT_CACHE_SIZE_PARAMETER);
           if (globalObjectCacheSizeString != null) {
               try {
  @@ -340,6 +372,31 @@
               noGlobalCacheInTx);
       }
   
  +    public void exclusiveTransientLock(String uri) throws ServiceAccessException {
  +        Xid txId = (Xid) activeTransactionBranch.get();
  +        try {
  +            GenericLock lock = (GenericLock) lockManager.atomicGetOrCreateLock(uri);
  +            if (lock.getLockLevel(txId) != 1) {
  +                Object owner = lock.getOwner();
  +                getLogger().log(
  +                    "Try lock: "
  +                        + txId
  +                        + " tries "
  +                        + uri
  +                        + (owner != null ? " ---> " + owner.toString() + " has it" : ""),
  +                    LOG_CHANNEL,
  +                    Logger.DEBUG);
  +                if (!lock.acquire(txId, 1, true, true, timeout)) {
  +                    throw new ServiceAccessException(this, new ConflictException(uri));
  +                }
  +                ((HashSet)locks.get()).add(lock);
  +                getLogger().log("Has lock: " + txId + " locks " + uri, LOG_CHANNEL, Logger.DEBUG);
  +            }
  +        } catch (InterruptedException e) {
  +            throw new ServiceAccessException(this, new ConflictException(uri));
  +        }
  +    }
  +
       //
       // overloaded content methods with caching 
       //
  @@ -825,6 +882,8 @@
       // 
   
       public void forget(Xid xid) throws XAException {
  +        releaseTransientLocks();
  +
           Xid txId = (Xid) XidWrapper.wrap(xid);
           activeTransactionBranch.set(null);
   
  @@ -838,6 +897,8 @@
       }
   
       public void rollback(Xid xid) throws XAException {
  +        releaseTransientLocks();
  +
           Xid txId = (Xid) XidWrapper.wrap(xid);
           activeTransactionBranch.set(null);
   
  @@ -851,6 +912,8 @@
       }
   
       public void commit(Xid xid, boolean onePhase) throws XAException {
  +        releaseTransientLocks();
  +
           Xid txId = (Xid) XidWrapper.wrap(xid);
           activeTransactionBranch.set(null);
   
  @@ -874,6 +937,8 @@
               Xid txId = (Xid) XidWrapper.wrap(xid);
               activeTransactionBranch.set(txId);
   
  +            locks.set(new HashSet());
  +
               objectsCache.getTxCache().start(txId);
               permissionsCache.getTxCache().start(txId);
               locksCache.getTxCache().start(txId);
  @@ -891,6 +956,19 @@
   
       public String toString() {
           return getName() + "(" + getClass().getName() + ")";
  +    }
  +
  +    protected void releaseTransientLocks() {
  +
  +        Xid txId = (Xid) activeTransactionBranch.get();
  +        for (Iterator it = ((HashSet)locks.get()).iterator(); it.hasNext();) {
  +            GenericLock lock = (GenericLock) it.next();
  +            lock.release(txId);
  +            getLogger().log(
  +                "Release lock: " + txId + " released " + lock.getResourceId().toString(),
  +                LOG_CHANNEL,
  +                Logger.DEBUG);
  +        }
       }
   
       protected Vector fillPermissionsCache(Uri uri) throws ServiceAccessException {
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org