OK, fixed this provisionally. I found this code in the PUT method:

                if (contentLength == -1) {
                        contentLength = 
revisionContent.getContentBytes().length;
                }

which will buffer the whole content in memory and just added my stuff to it

                if (contentLength == -1 || retryUponConflict) {
                        contentLength = 
revisionContent.getContentBytes().length;
                }


However, this is not a really good soltution...

Oliver

On Mon, 13 Dec 2004 16:43:33 +0100, Oliver Zeigermann
<[EMAIL PROTECTED]> wrote:
> Oooops,
> 
> there still seems to be a problem with this. When a PUT fails then the
> stream containing the content will be empty, so you can not repeat it.
> I guess I will introduce a new parameter that makes the content stream
> into a tmp file for multiple access...
> 
> Is this a good idea?
> 
> Oliver
> 
> 
> 
> On Tue, 7 Dec 2004 18:17:33 +0100, Oliver Zeigermann
> <[EMAIL PROTECTED]> wrote:
> > Folks,
> >
> > everyone who has watched some of my evil commits knows my style:
> > Simple and dirty. This one is no different. I had to make
> > ConcurrencyConflictException an error to let it come through untouched
> > to the abstract request. A cleaner solution would be to add the
> > exception to all store methods and pass it up properly, but this would
> > cause so many API incompatibilites that it should be deferred to 3.0
> > or so.
> >
> > For now, any better ideas?
> >
> > Oliver
> >
> > On 7 Dec 2004 17:03:03 -0000, [EMAIL PROTECTED]
> >
> >
> > <[EMAIL PROTECTED]> wrote:
> > > ozeigermann    2004/12/07 09:03:03
> > >
> > >   Modified:    src/stores/org/apache/slide/store/impl/rdbms
> > >                         MySqlRDBMSAdapter.java
> > >                src/webdav/server/org/apache/slide/webdav/method
> > >                         AbstractWebdavMethod.java
> > >                src/stores/org/apache/slide/store/txfile
> > >                         AbstractTxFileStoreService.java
> > >   Added:       src/share/org/apache/slide/store
> > >                         ConcurrencyConflictException.java
> > >   Log:
> > >   Added rudimentary support for internal and transparent repeat
> > >   of conflicting transactions.
> > >
> > >   Revision  Changes    Path
> > >   1.11      +7 -5      
> > > jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/MySqlRDBMSAdapter.java
> > >
> > >   Index: MySqlRDBMSAdapter.java
> > >   ===================================================================
> > >   RCS file: 
> > > /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/MySqlRDBMSAdapter.java,v
> > >   retrieving revision 1.10
> > >   retrieving revision 1.11
> > >   diff -u -r1.10 -r1.11
> > >   --- MySqlRDBMSAdapter.java    11 Nov 2004 17:15:35 -0000      1.10
> > >   +++ MySqlRDBMSAdapter.java    7 Dec 2004 17:03:02 -0000       1.11
> > >   @@ -35,6 +35,7 @@
> > >    import org.apache.slide.content.*;
> > >    import org.apache.slide.common.*;
> > >    import org.apache.slide.macro.ConflictException;
> > >   +import org.apache.slide.store.ConcurrencyConflictException;
> > >    import org.apache.slide.structure.ObjectNotFoundException;
> > >    import org.apache.slide.util.logger.Logger;
> > >
> > >   @@ -61,7 +62,8 @@
> > >            switch (e.getErrorCode()) {
> > >                case 1213 : // thread was deadlock victim
> > >                    getLogger().log(e.getErrorCode() + ": Deadlock 
> > > resolved on " + uri, LOG_CHANNEL, Logger.WARNING);
> > >   -                return new ServiceAccessException(service, new 
> > > ConflictException(uri));
> > >   +                throw new ConcurrencyConflictException(e, uri);
> > >   +//              throw new ServiceAccessException(this, new 
> > > ConflictException(uri));
> > >
> > >                default :
> > >                    getLogger().log(
> > >
> > >   1.64      +112 -45   
> > > 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.63
> > >   retrieving revision 1.64
> > >   diff -u -r1.63 -r1.64
> > >   --- AbstractWebdavMethod.java 6 Dec 2004 08:54:13 -0000       1.63
> > >   +++ AbstractWebdavMethod.java 7 Dec 2004 17:03:02 -0000       1.64
> > >   @@ -61,12 +61,19 @@
> > >    import org.apache.slide.content.NodeRevisionContent;
> > >    import org.apache.slide.content.NodeRevisionDescriptor;
> > >    import org.apache.slide.content.NodeRevisionDescriptors;
> > >   +import org.apache.slide.content.RevisionDescriptorNotFoundException;
> > >    import org.apache.slide.content.NodeProperty.NamespaceCache;
> > >   +import org.apache.slide.event.VetoException;
> > >    import org.apache.slide.lock.Lock;
> > >    import org.apache.slide.lock.NodeLock;
> > >   +import org.apache.slide.lock.ObjectLockedException;
> > >   +import org.apache.slide.macro.ConflictException;
> > >    import org.apache.slide.macro.Macro;
> > >    import org.apache.slide.search.Search;
> > >   +import org.apache.slide.security.AccessDeniedException;
> > >    import org.apache.slide.security.Security;
> > >   +import org.apache.slide.store.ConcurrencyConflictException;
> > >   +import org.apache.slide.structure.LinkedObjectNotFoundException;
> > >    import org.apache.slide.structure.ObjectNode;
> > >    import org.apache.slide.structure.ObjectNotFoundException;
> > >    import org.apache.slide.structure.Structure;
> > >   @@ -185,6 +192,9 @@
> > >        private static final GenericLock GLOBAL_WRITE_LOCK = new 
> > > GenericLock("GLOBAL WRITE", EXCLUSIVE_LOCK,
> > >                new PrintWriterLogger(new PrintWriter(System.out), 
> > > LOG_CHANNEL, false));
> > >
> > >   +
> > >   +    private static final int DEFAULT_MAX_RETRY_REPEATS = 1;
> > >   +
> > >        // ----------------------------------------------------- Instance 
> > > Variables
> > >
> > >   @@ -413,53 +423,32 @@
> > >                } catch (ObjectNotFoundException e) {
> > >                    // ignore, it can't have locks
> > >                }
> > >   +
> > >   +            boolean done = false;
> > >   +            boolean retryUponConflict = isRepeatUponConflict() && 
> > > !slideToken.isExternalTransaction();
> > >   +            int retries = getMaxRetryRepeats();
> > >
> > >   -            boolean responseIsRedirected = false;
> > >   -            if (!requestHeaders.getApplyToRedirectRef(false)) {
> > >   -                try {
> > >   -                    NodeRevisionDescriptors revisionDescriptors
> > >   -                            = content.retrieve(slideToken, requestUri);
> > >   -                    NodeRevisionDescriptor revisionDescriptor
> > >   -                            = content.retrieve(slideToken, 
> > > revisionDescriptors);
> > >   -                    if (WebdavUtils.isRedirectref(revisionDescriptor)) 
> > > {
> > >   -                        NodeProperty refTarget
> > >   -                                = 
> > > revisionDescriptor.getProperty(P_REFTARGET);
> > >   -
> > >   -                        // Add the header indicating that this 
> > > redirect is the
> > >   -                        // result of a redirect reference.
> > >   -                        resp.addHeader(H_REDIRECT_REF,
> > >   -                                refTarget.getValue().toString());
> > >   -
> > >   -                        // Set the location header for the redirect.
> > >   -                        resp.addHeader("Location",
> > >   -                                refTarget.getValue().toString());
> > >   -
> > >   -                        // Determine the appropriate status code.
> > >   -                        boolean permanent
> > >   -                                = 
> > > revisionDescriptor.propertyValueContains(
> > >   -                                P_REDIRECT_LIFETIME, "permanent");
> > >   -                        if (permanent) {
> > >   -                            
> > > resp.setStatus(WebdavStatus.SC_MOVED_PERMANENTLY);
> > >   -                            resp.addHeader(H_CACHE_CONTROL, 
> > > PRIVATE_CACHE);
> > >   -                        }
> > >   -                        else {
> > >   -                            
> > > resp.setStatus(WebdavStatus.SC_MOVED_TEMPORARILY);
> > >   -                            resp.addHeader(H_CACHE_CONTROL, NO_CACHE);
> > >   -                        }
> > >   +            ConcurrencyConflictException finalCce = null;
> > >
> > >   -                        // Set this flag so that we don't attempt to 
> > > execute the
> > >   -                        // request on the redirect reference itself.
> > >   -                        responseIsRedirected = true;
> > >   +            while (!done && retries != 0) {
> > >   +                try {
> > >   +                    executeRedirect();
> > >   +                    done = true;
> > >   +                } catch (ConcurrencyConflictException cce) {
> > >   +                    finalCce = cce;
> > >   +                    if (retryUponConflict) {
> > >   +                        retries--;
> > >   +                        token.getLogger().log(cce.getMessage(), 
> > > LOG_CHANNEL, Logger.WARNING);
> > >   +                        token.rollback();
> > >   +                        token.begin();
> > >   +                    } else {
> > >   +                        break;
> > >                        }
> > >                    }
> > >   -                catch (ObjectNotFoundException notFound) {
> > >   -                    token.getLogger().log("Error while trying to send 
> > > redirect",
> > >   -                            notFound, LOG_CHANNEL, Logger.ERROR);
> > >   -                }
> > >                }
> > >   -
> > >   -            if (!responseIsRedirected) {
> > >   -                executeRequest();
> > >   +            if (!done) {
> > >   +                // rethrow it as an ordinary conflict exception
> > >   +                throw new ConflictException(finalCce.getUri(), 
> > > finalCce);
> > >                }
> > >
> > >                if (!slideToken.isExternalTransaction() && 
> > > transactionIsStarted) {
> > >   @@ -512,6 +501,57 @@
> > >            }
> > >        }
> > >
> > >   +    protected void executeRedirect() throws AccessDeniedException, 
> > > LinkedObjectNotFoundException,
> > >   +            ObjectLockedException, 
> > > RevisionDescriptorNotFoundException, ServiceAccessException,
> > >   +            VetoException, WebdavException, IOException {
> > >   +        boolean responseIsRedirected = false;
> > >   +        if (!requestHeaders.getApplyToRedirectRef(false)) {
> > >   +            try {
> > >   +                NodeRevisionDescriptors revisionDescriptors
> > >   +                        = content.retrieve(slideToken, requestUri);
> > >   +                NodeRevisionDescriptor revisionDescriptor
> > >   +                        = content.retrieve(slideToken, 
> > > revisionDescriptors);
> > >   +                if (WebdavUtils.isRedirectref(revisionDescriptor)) {
> > >   +                    NodeProperty refTarget
> > >   +                            = 
> > > revisionDescriptor.getProperty(P_REFTARGET);
> > >   +
> > >   +                    // Add the header indicating that this redirect is 
> > > the
> > >   +                    // result of a redirect reference.
> > >   +                    resp.addHeader(H_REDIRECT_REF,
> > >   +                            refTarget.getValue().toString());
> > >   +
> > >   +                    // Set the location header for the redirect.
> > >   +                    resp.addHeader("Location",
> > >   +                            refTarget.getValue().toString());
> > >   +
> > >   +                    // Determine the appropriate status code.
> > >   +                    boolean permanent
> > >   +                            = revisionDescriptor.propertyValueContains(
> > >   +                            P_REDIRECT_LIFETIME, "permanent");
> > >   +                    if (permanent) {
> > >   +                        
> > > resp.setStatus(WebdavStatus.SC_MOVED_PERMANENTLY);
> > >   +                        resp.addHeader(H_CACHE_CONTROL, PRIVATE_CACHE);
> > >   +                    }
> > >   +                    else {
> > >   +                        
> > > resp.setStatus(WebdavStatus.SC_MOVED_TEMPORARILY);
> > >   +                        resp.addHeader(H_CACHE_CONTROL, NO_CACHE);
> > >   +                    }
> > >   +
> > >   +                    // Set this flag so that we don't attempt to 
> > > execute the
> > >   +                    // request on the redirect reference itself.
> > >   +                    responseIsRedirected = true;
> > >   +                }
> > >   +            }
> > >   +            catch (ObjectNotFoundException notFound) {
> > >   +                token.getLogger().log("Error while trying to send 
> > > redirect",
> > >   +                        notFound, LOG_CHANNEL, Logger.ERROR);
> > >   +            }
> > >   +        }
> > >   +        if (!responseIsRedirected) {
> > >   +            executeRequest();
> > >   +        }
> > >   +    }
> > >   +
> > >        // --------------------------------------------------------- 
> > > Public Methods
> > >
> > >   @@ -921,6 +961,33 @@
> > >                    "sequential-mode"));
> > >        }
> > >
> > >   +    /**
> > >   +     * Checks if Slide is configured to internally repeat a request if 
> > > it conflicts with other
> > >   +     * concurrent ones.
> > >   +     */
> > >   +    protected boolean isRepeatUponConflict() {
> > >   +        return 
> > > "true".equalsIgnoreCase(token.getNamespaceConfig().getParameter(
> > >   +                "repeat-upon-conflict"));
> > >   +    }
> > >   +
> > >   +    /**
> > >   +     * Checks if Slide is configured to internally repeat a request if 
> > > it conflicts with other
> > >   +     * concurrent ones.
> > >   +     */
> > >   +    protected int getMaxRetryRepeats() {
> > >   +        String maxRepeat = 
> > > token.getNamespaceConfig().getParameter("max-retry-repeat");
> > >   +        if (maxRepeat != null) {
> > >   +            try {
> > >   +                int repeats = Integer.parseInt(maxRepeat);
> > >   +                return repeats;
> > >   +            } catch (NumberFormatException nfe) {
> > >   +                token.getLogger().log("max-retry-repeat must be an 
> > > integer, using default",
> > >   +                        LOG_CHANNEL_LOCKING, Logger.WARNING);
> > >   +            }
> > >   +        }
> > >   +        return DEFAULT_MAX_RETRY_REPEATS;
> > >   +    }
> > >   +
> > >        protected void assureGlobalLocks() {
> > >            if (this instanceof FineGrainedLockingMethod && 
> > > isFineGrainSequential()) {
> > >                synchronized (ATOMIC_LOCKING_MONITOR) {
> > >
> > >   1.17      +7 -4      
> > > 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.16
> > >   retrieving revision 1.17
> > >   diff -u -r1.16 -r1.17
> > >   --- AbstractTxFileStoreService.java   9 Aug 2004 09:35:20 -0000       
> > > 1.16
> > >   +++ AbstractTxFileStoreService.java   7 Dec 2004 17:03:02 -0000       
> > > 1.17
> > >   @@ -38,6 +38,7 @@
> > >    import javax.transaction.xa.XAResource;
> > >    import javax.transaction.xa.Xid;
> > >
> > >   +import org.apache.slide.store.ConcurrencyConflictException;
> > >    import org.apache.slide.util.logger.TxLogger;
> > >    import org.apache.slide.util.logger.Logger;
> > >
> > >   @@ -408,7 +409,9 @@
> > >                    getLogChannel(),
> > >                    Logger.INFO);
> > >
> > >   -            throw new ServiceAccessException(this, new 
> > > ConflictException(uri));
> > >   +//            throw new ServiceAccessException(this, new 
> > > ConflictException(uri));
> > >   +            throw new 
> > > ConcurrencyConflictException(((ResourceManagerException) 
> > > cause).getStatus(),
> > >   +                    ((ResourceManagerException) cause).getMessage(), 
> > > uri);
> > >
> > >            } else {
> > >
> > >   1.1                  
> > > jakarta-slide/src/share/org/apache/slide/store/ConcurrencyConflictException.java
> > >
> > >   Index: ConcurrencyConflictException.java
> > >   ===================================================================
> > >   /*
> > >    * $Header: 
> > > /home/cvs/jakarta-slide/src/share/org/apache/slide/store/ConcurrencyConflictException.java,v
> > >  1.1 2004/12/07 17:03:03 ozeigermann Exp $
> > >    * $Revision: 1.1 $
> > >    * $Date: 2004/12/07 17:03:03 $
> > >    *
> > >    * ====================================================================
> > >    *
> > >    * Copyright 1999-2002 The Apache Software Foundation
> > >    *
> > >    * Licensed under the Apache License, Version 2.0 (the "License");
> > >    * you may not use this file except in compliance with the License.
> > >    * You may obtain a copy of the License at
> > >    *
> > >    *     http://www.apache.org/licenses/LICENSE-2.0
> > >    *
> > >    * Unless required by applicable law or agreed to in writing, software
> > >    * distributed under the License is distributed on an "AS IS" BASIS,
> > >    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> > > implied.
> > >    * See the License for the specific language governing permissions and
> > >    * limitations under the License.
> > >    *
> > >    */
> > >
> > >   package org.apache.slide.store;
> > >
> > >   import java.sql.SQLException;
> > >
> > >   /**
> > >    * Exception gets thrown from the store layer upon failure caused by
> > >    * other concurrent requests. Such failures include deadlocks, 
> > > unserializable
> > >    * transactions and other spurious behaviour caused by insufficient 
> > > isolation.
> > >    *
> > >    * @version $Revision: 1.1 $
> > >    */
> > >   public class ConcurrencyConflictException extends Error {
> > >
> > >       protected int errorCode;
> > >       protected String uri;
> > >
> > >       public ConcurrencyConflictException(int errorCode, String message, 
> > > String uri) {
> > >           super(message);
> > >           this.errorCode = errorCode;
> > >           this.uri = uri;
> > >       }
> > >
> > >       public ConcurrencyConflictException(SQLException e, String uri) {
> > >           this(e.getErrorCode(), e.getMessage(), uri);
> > >       }
> > >
> > >       public String toString() {
> > >           StringBuffer buf = new StringBuffer();
> > >
> > >           if (uri != null) {
> > >               buf.append(uri).append(": ");
> > >           }
> > >           if (getMessage() != null) {
> > >               buf.append(getMessage());
> > >           }
> > >           if (errorCode != -1) {
> > >               buf.append("(").append(errorCode).append(")");
> > >           }
> > >           return buf.toString();
> > >       }
> > >       /**
> > >        * @return Returns the errorCode.
> > >        */
> > >       public int getErrorCode() {
> > >           return errorCode;
> > >       }
> > >       /**
> > >        * @return Returns the uri.
> > >        */
> > >       public String getUri() {
> > >           return uri;
> > >       }
> > >   }
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > > For additional commands, e-mail: [EMAIL PROTECTED]
> > >
> > >
> >
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to