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