pnever      2003/10/28 00:41:42

  Modified:    src/stores/org/apache/slide/store/txfile
                        AbstractTxFileStoreService.java StoreLogger.java
                        TxFileContentStore.java
                        TxXMLFileDescriptorsStore.java
                        XMLResourceDescriptor.java
               src/stores/org/apache/slide/store/txfile/rm/impl
                        FileResourceManager.java
  Log:
  Fixes to the TX store by Oliver Zeigermann:
  
  FIXES:
  
  AbstractTxFileStoreService:
  - Transaction will be marked for rollback upon system error or deadlock
  - minor flaws
  
  StoreLogger:
  - logging of message and throwable will result in two log methods in
  Slide logging
  
  TxFileContentStore:
  - adaptions to new system error handling in AbstractTxFileStoreService
  - streams get closed in finally blocks to assure all locks in
  FileResouceManager get freed
  - minor flaws
  
  TxXMLFileDescriptorsStore:
  - adaptions to new system error handling in AbstractTxFileStoreService
  
  XMLResourceDescriptor:
  - adaptions to new system error handling in AbstractTxFileStoreService
  - streams get closed in finally blocks to assure all locks in
  FileResouceManager get freed
  - made it thread safe
  - added a tiny hack (which is to be investigated further)
  
  FileResourceManager:
  - freeing locks and resource when tx is marked for rollback to avoid
  dangling locks when app misses to actually roll back the tx
  
  Revision  Changes    Path
  1.2       +75 -2     
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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AbstractTxFileStoreService.java   9 Oct 2003 09:31:33 -0000       1.1
  +++ AbstractTxFileStoreService.java   28 Oct 2003 08:41:42 -0000      1.2
  @@ -57,7 +57,11 @@
           new File(storeDir).mkdirs();
           new File(workDir).mkdirs();
   
  -        rm = new FileResourceManager(storeDir, workDir, new 
StoreLogger(getLogger(), FileResourceManager.class.getName()));
  +        rm =
  +            new FileResourceManager(
  +                storeDir,
  +                workDir,
  +                new StoreLogger(getLogger(), FileResourceManager.class.getName()));
   
           getLogger().log(
               "File Store configured to " + storeDir + ", working directory " + 
workDir,
  @@ -134,7 +138,7 @@
               LOG_CHANNEL,
               Logger.DEBUG);
           try {
  -            int status = rm.prepareTransaction(XidWrapper.wrap(xid));
  +            int status = rm.prepareTransaction(txId);
               switch (status) {
                   case ResourceManager.PREPARE_SUCCESS_READONLY :
                       return XA_RDONLY;
  @@ -263,6 +267,75 @@
                   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
                   break;
  +        }
  +    }
  +
  +    public synchronized void throwInternalError(String cause) throws 
ServiceAccessException {
  +        Object txId = getActiveTxId();
  +
  +        getLogger().log(
  +            "Thread "
  +                + Thread.currentThread()
  +                + " marked transaction branch "
  +                + txId
  +                + " for rollback. Cause: "
  +                + cause,
  +            LOG_CHANNEL,
  +            Logger.WARNING);
  +
  +        try {
  +            rm.markTransactionForRollback(txId);
  +        } catch (ResourceManagerException re) {
  +            throw new ServiceAccessException(this, re);
  +        }
  +
  +        throw new ServiceAccessException(this, cause);
  +
  +    }
  +
  +    // TODO if error is caused by lock that could not be acquired
  +    // we should try deadlock detection instead of simply rolling back
  +    // if no deadlock is detected, retrying for lock would be preferred method    
  +    public synchronized void throwInternalError(Throwable cause) throws 
ServiceAccessException {
  +        Object txId = getActiveTxId();
  +
  +        if ((cause instanceof ResourceManagerException)
  +            && ((ResourceManagerException) cause).getStatus() == 
ResourceManagerException.ERR_NO_LOCK) {
  +
  +            // XXX strictly speaking, this is incorrect, as we actually did not 
chck for deadlock,
  +            // but silently assume a deadlock must have been the cause for the 
failed lock
  +            try {
  +                rm.markTransactionForRollback(txId);
  +            } catch (ResourceManagerException re) {
  +                throw new ServiceAccessException(this, re);
  +            }
  +
  +            getLogger().log(
  +                "DEADLOCK VICTIM: Thread "
  +                    + Thread.currentThread()
  +                    + " marked transaction branch "
  +                    + txId
  +                    + " for rollback",
  +                LOG_CHANNEL,
  +                Logger.INFO);
  +
  +            throw new ServiceAccessException(this, "deadlock victim");
  +
  +        } else {
  +
  +            try {
  +                rm.markTransactionForRollback(txId);
  +            } catch (ResourceManagerException re) {
  +                throw new ServiceAccessException(this, re);
  +            }
  +
  +            getLogger().log(
  +                "Thread " + Thread.currentThread() + " marked transaction branch " 
+ txId + " for rollback",
  +                LOG_CHANNEL,
  +                Logger.WARNING);
  +
  +            throw new ServiceAccessException(this, cause);
  +
           }
       }
   
  
  
  
  1.2       +1 -2      
jakarta-slide/src/stores/org/apache/slide/store/txfile/StoreLogger.java
  
  Index: StoreLogger.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/store/txfile/StoreLogger.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- StoreLogger.java  9 Oct 2003 09:31:33 -0000       1.1
  +++ StoreLogger.java  28 Oct 2003 08:41:42 -0000      1.2
  @@ -37,9 +37,8 @@
   
       public void log(String message, int level, Throwable t) {
           if (logger != null) {
  -            if (t == null) {
                   logger.log(message, logChannel, level);
  -            } else {
  +            if (t != null) {
                   logger.log(t, logChannel, level);
               }
           }
  
  
  
  1.2       +26 -11    
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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TxFileContentStore.java   9 Oct 2003 09:31:33 -0000       1.1
  +++ TxFileContentStore.java   28 Oct 2003 08:41:42 -0000      1.2
  @@ -25,7 +25,7 @@
       public NodeRevisionContent retrieveRevisionContent(Uri uri, 
NodeRevisionDescriptor revisionDescriptor)
           throws ServiceAccessException, RevisionNotFoundException {
   
  -        String revisionUri = revisionUri = uri.toString() + "_" + 
revisionDescriptor.getRevisionNumber();
  +        String revisionUri = uri.toString() + "_" + 
revisionDescriptor.getRevisionNumber();
   
           try {
               Object txId = getActiveTxId();
  @@ -42,7 +42,8 @@
               if (e.getStatus() == ResourceManagerException.ERR_NO_SUCH_RESOURCE) {
                   throw new RevisionNotFoundException(uri.toString(), 
revisionDescriptor.getRevisionNumber());
               } else {
  -                throw new ServiceAccessException(this, e);
  +                throwInternalError(e);
  +                return null; // XXX fake (is never called)
               }
           }
       }
  @@ -59,12 +60,12 @@
               storeRevisionContent(uri, revisionDescriptor, revisionContent);
           } catch (RevisionNotFoundException e) {
               // Can not be, as we just created it. If it unexpectedly is, this is 
fatal 
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           } catch (ResourceManagerException e) {
               if (e.getStatus() == ResourceManagerException.ERR_RESOURCE_EXISTS) {
                   throw new RevisionAlreadyExistException(uri.toString(), 
revisionDescriptor.getRevisionNumber());
               } else {
  -                throw new ServiceAccessException(this, e);
  +                throwInternalError(e);
               }
           }
       }
  @@ -76,28 +77,42 @@
           throws ServiceAccessException, RevisionNotFoundException {
           String revisionUri = revisionUri = uri.toString() + "_" + 
revisionDescriptor.getRevisionNumber();
   
  +        OutputStream os = null;
  +        InputStream is = null;
           try {
  -            OutputStream os = rm.writeResource(getActiveTxId(), revisionUri);
  -            InputStream is = revisionContent.streamContent();
  +            os = rm.writeResource(getActiveTxId(), revisionUri);
  +            is = revisionContent.streamContent();
   
               if (is != null) {
                   long contentBytes = FileHelper.copy(is, os);
  -                os.close();
                   long contentLength = revisionDescriptor.getContentLength();
                   revisionDescriptor.setContentLength(contentBytes);
   
                   if (contentLength != -1 && contentBytes != contentLength) {
                       rm.deleteResource(getActiveTxId(), revisionUri);
  -                    throw new ServiceAccessException(this, "Content length does not 
match expected");
  +                    throwInternalError("Content length does not match expected");
                   }
               }
           } catch (IOException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           } catch (ResourceManagerException e) {
               if (e.getStatus() == ResourceManagerException.ERR_NO_SUCH_RESOURCE) {
                   throw new RevisionNotFoundException(uri.toString(), 
revisionDescriptor.getRevisionNumber());
               } else {
  -                throw new ServiceAccessException(this, e);
  +                throwInternalError(e);
  +            }
  +        } finally {
  +            try {
  +                if (os != null) {
  +                    os.close();
  +                }
  +            } catch (IOException e) {
  +            }
  +            try {
  +                if (is != null) {
  +                    is.close();
  +                }
  +            } catch (IOException e) {
               }
           }
       }
  @@ -108,7 +123,7 @@
           try {
               rm.deleteResource(getActiveTxId(), revisionUri);
           } catch (ResourceManagerException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  
  
  
  1.2       +16 -15    
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.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- TxXMLFileDescriptorsStore.java    9 Oct 2003 09:31:33 -0000       1.1
  +++ TxXMLFileDescriptorsStore.java    28 Oct 2003 08:41:42 -0000      1.2
  @@ -64,7 +64,7 @@
               xfd.storeObject(uri, object);
           } catch (ObjectNotFoundException e) {
               // should not happen, if it does, it is an error inside this store:
  -            throw new ServiceAccessException(this, "Newly created file vanished");
  +            throwInternalError("Newly created file vanished");
           }
       }
   
  @@ -84,7 +84,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.grantPermission(uri, permission);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -93,7 +93,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.revokePermission(uri, permission);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -102,7 +102,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.revokePermissions(uri);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -111,7 +111,8 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               return xfd.enumeratePermissions();
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
  +            return null; // XXX fake (is never called)
           }
       }
   
  @@ -126,7 +127,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.putLock(uri, lock);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -135,7 +136,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.renewLock(uri, lock);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -157,7 +158,8 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               return xfd.enumerateLocks();
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
  +            return null; // XXX fake (is never called)
           }
       }
   
  @@ -183,7 +185,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.createRevisionDescriptors(uri, revisionDescriptors);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -202,7 +204,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.removeRevisionDescriptors(uri);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -228,7 +230,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.createRevisionDescriptor(uri, revisionDescriptor);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -247,7 +249,7 @@
               XMLResourceDescriptor xfd = getFileDescriptor(uri);
               xfd.removeRevisionDescriptor(uri, number);
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(this, e);
  +            throwInternalError(e);
           }
       }
   
  @@ -260,10 +262,9 @@
       /**
        * Either returns a cached file descriptor or loads it from DB 
        */
  -    protected XMLResourceDescriptor getFileDescriptor(Uri uri)
  -        throws ServiceAccessException, ObjectNotFoundException {
  +    protected XMLResourceDescriptor getFileDescriptor(Uri uri) throws 
ServiceAccessException, ObjectNotFoundException {
           Object txId = getActiveTxId();
  -        XMLResourceDescriptor xfd = new XMLResourceDescriptor(uri, rm, txId, 
characterEncoding);
  +        XMLResourceDescriptor xfd = new XMLResourceDescriptor(uri, this, rm, txId, 
characterEncoding);
           return xfd;
       }
   }
  
  
  
  1.2       +58 -34    
jakarta-slide/src/stores/org/apache/slide/store/txfile/XMLResourceDescriptor.java
  
  Index: XMLResourceDescriptor.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/store/txfile/XMLResourceDescriptor.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XMLResourceDescriptor.java        9 Oct 2003 09:31:33 -0000       1.1
  +++ XMLResourceDescriptor.java        28 Oct 2003 08:41:42 -0000      1.2
  @@ -40,9 +40,10 @@
   
       protected static final String PATH_EXTENSION = ".def.xml";
       protected final FileResourceManager rm;
  +    protected final TxXMLFileDescriptorsStore store;
       protected final String characterEncoding;
  -    protected final Object txId;
  -    protected final Uri uri;
  +    protected volatile Object txId;
  +    protected volatile Uri uri;
       protected final String loadPath;
   
       protected StoreLogger logger;
  @@ -57,7 +58,12 @@
        * @throws ServiceAccessException if anything goes wrong at system level
        * @throws ObjectNotFoundException if <code>load</code> is set to 
<code>true</code> and the descriptor is not present in resource manager
        */
  -    public XMLResourceDescriptor(Uri uri, FileResourceManager rm, Object txId, 
String characterEncoding)
  +    public XMLResourceDescriptor(
  +        Uri uri,
  +        TxXMLFileDescriptorsStore store,
  +        FileResourceManager rm,
  +        Object txId,
  +        String characterEncoding)
           throws ServiceAccessException, ObjectNotFoundException {
           // XXX super class tries to create folders, no way to stop it:
           // at least let it create folders in a place where it can do no harm
  @@ -66,6 +72,7 @@
           logger = 
rm.getLogger().cloneWithNewLogChannel(XMLResourceDescriptor.class.getName());
   
           this.rm = rm;
  +        this.store = store;
           this.characterEncoding = characterEncoding;
           this.txId = txId;
           this.uri = uri;
  @@ -79,22 +86,28 @@
        * @throws ServiceAccessException if anything goes wrong at system level
        * @throws ObjectNotFoundException if the descriptor has not been created 
before 
        */
  -    public void save() throws ServiceAccessException, ObjectNotFoundException {
  +    public synchronized void save() throws ServiceAccessException, 
ObjectNotFoundException {
           if (txId == null) {
  -            throw new ServiceAccessException(null, "Not inside tx");
  +            store.throwInternalError("Not inside tx");
           }
           logger.logFine("Tx " + txId + " saves data for " + loadPath);
  +
  +        OutputStream os = null;
           try {
  -            OutputStream os = rm.writeResource(txId, loadPath);
  +            os = rm.writeResource(txId, loadPath);
               save(os);
  -            os.close();
  -        } catch (IOException e) {
  -            throw new ServiceAccessException(null, e);
           } catch (ResourceManagerException e) {
               if (e.getStatus() == ResourceManagerException.ERR_NO_SUCH_RESOURCE) {
                   throw new ObjectNotFoundException(uri);
               } else {
  -                throw new ServiceAccessException(null, e);
  +                store.throwInternalError(e);
  +            }
  +        } finally {
  +            try {
  +                if (os != null) {
  +                    os.close();
  +                }
  +            } catch (IOException e) {
               }
           }
       }
  @@ -105,10 +118,10 @@
        * @throws ServiceAccessException if anything goes wrong at system level
        * @throws ObjectAlreadyExistsException if the descriptor already exists 
        */
  -    public void create() throws ServiceAccessException, 
ObjectAlreadyExistsException {
  +    public synchronized void create() throws ServiceAccessException, 
ObjectAlreadyExistsException {
           logger.logFiner("Tx " + txId + " creates " + loadPath);
           if (txId == null) {
  -            throw new ServiceAccessException(null, "Not inside tx");
  +            store.throwInternalError("Not inside tx");
           }
           try {
               rm.createResource(txId, loadPath, false);
  @@ -117,7 +130,7 @@
               if (e.getStatus() == ResourceManagerException.ERR_RESOURCE_EXISTS) {
                   throw new ObjectAlreadyExistsException(uri.toString());
               } else {
  -                throw new ServiceAccessException(null, e);
  +                store.throwInternalError(e);
               }
           }
       }
  @@ -128,10 +141,10 @@
        * @throws ServiceAccessException if anything goes wrong at system level
        * @throws ObjectNotFoundException if the descriptor does not exist 
        */
  -    public void delete() throws ServiceAccessException, ObjectNotFoundException {
  +    public synchronized void delete() throws ServiceAccessException, 
ObjectNotFoundException {
           logger.logFiner("Tx " + txId + " deletes " + loadPath);
           if (txId == null) {
  -            throw new ServiceAccessException(null, "Not inside tx");
  +            store.throwInternalError("Not inside tx");
           }
           try {
               rm.deleteResource(txId, loadPath, false);
  @@ -140,7 +153,7 @@
               if (e.getStatus() == ResourceManagerException.ERR_NO_SUCH_RESOURCE) {
                   throw new ObjectNotFoundException(uri.toString());
               } else {
  -                throw new ServiceAccessException(null, e);
  +                store.throwInternalError(e);
               }
           }
       }
  @@ -151,34 +164,39 @@
        * @throws ServiceAccessException if anything goes wrong at system level
        * @throws ObjectNotFoundException if the descriptor does not exist 
        */
  -    public void load() throws ServiceAccessException, ObjectNotFoundException {
  +    public synchronized void load() throws ServiceAccessException, 
ObjectNotFoundException {
           logger.logFiner("Tx " + txId + " loads data for " + loadPath);
  +
  +        InputStream is = null;
           try {
               logger.logFinest("Faking read access from outside tx for " + loadPath);
               if (txId != null) {
                   if (rm.resourceExists(txId, loadPath)) {
  -                    InputStream is = rm.readResource(txId, loadPath);
  +                    is = rm.readResource(txId, loadPath);
                       load(is);
  -                    is.close();
                   } else {
                       init();
                   }
               } else {
                   if (rm.resourceExists(loadPath)) {
  -                    InputStream is = rm.readResource(loadPath);
  +                    is = rm.readResource(loadPath);
                       load(is);
  -                    is.close();
                   } else {
                       init();
                   }
               }
  -        } catch (IOException e) {
  -            throw new ServiceAccessException(null, e);
           } catch (ResourceManagerException e) {
               if (e.getStatus() == ResourceManagerException.ERR_NO_SUCH_RESOURCE) {
                   throw new ObjectNotFoundException(uri);
               } else {
  -                throw new ServiceAccessException(null, e);
  +                store.throwInternalError(e);
  +            }
  +        } finally {
  +            try {
  +                if (is != null) {
  +                    is.close();
  +                }
  +            } catch (IOException e) {
               }
           }
       }
  @@ -208,7 +226,7 @@
        * @param o object to compare this descriptor to
        * @return <code>true</code> if object is equal as described above 
        */
  -    public boolean equals(Object o) {
  +    public synchronized boolean equals(Object o) {
           return (
               this == o
                   || (o != null
  @@ -217,7 +235,7 @@
                       && ((XMLResourceDescriptor) o).txId.equals(txId)));
       }
   
  -    protected void save(OutputStream os) throws ServiceAccessException {
  +    protected synchronized void save(OutputStream os) throws ServiceAccessException 
{
           Element aRoot = encode();
           Document aDocument = new Document(aRoot);
   
  @@ -230,23 +248,23 @@
               aOutputter.output(aDocument, os);
               os.flush();
           } catch (IOException e) {
  -            throw new ServiceAccessException(null, e);
  +            store.throwInternalError(e);
           }
       }
   
  -    protected void load(InputStream is) throws ServiceAccessException {
  +    protected synchronized void load(InputStream is) throws ServiceAccessException {
           SAXBuilder aBuilder = new SAXBuilder();
           try {
               Document aDocument = aBuilder.build(is);
               decode(aDocument.getRootElement());
           } catch (JDOMException e) {
  -            throw new ServiceAccessException(null, e);
  +            store.throwInternalError(e);
           } catch (IOException e) {
  -            throw new ServiceAccessException(null, e);
  +            store.throwInternalError(e);
           }
       }
   
  -    protected void init() throws ServiceAccessException {
  +    protected synchronized void init() throws ServiceAccessException {
           object = null;
           permissions = new Vector();
           locks = new Vector();
  @@ -254,14 +272,20 @@
           descriptor = new Hashtable();
       }
   
  -    protected void save(Uri uri) throws ServiceAccessException {
  +    protected synchronized void save(Uri uri) throws ServiceAccessException {
           if (txId == null) {
  -            throw new ServiceAccessException(null, "Not inside tx");
  +            store.throwInternalError("Not inside tx");
           }
  +        // XXX this is a HACK, should throw exception, really 
  +        //      if (object == null) {
  +        //          store.throwInternalError("Resource '"+uri+"' not initialized");
  +        //      }
  +        if (object == null)
  +            return;
           try {
               save();
           } catch (ObjectNotFoundException e) {
  -            throw new ServiceAccessException(null, e);
  +            store.throwInternalError(e);
           }
       }
   
  
  
  
  1.2       +5 -0      
jakarta-slide/src/stores/org/apache/slide/store/txfile/rm/impl/FileResourceManager.java
  
  Index: FileResourceManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-slide/src/stores/org/apache/slide/store/txfile/rm/impl/FileResourceManager.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- FileResourceManager.java  9 Oct 2003 09:31:33 -0000       1.1
  +++ FileResourceManager.java  28 Oct 2003 08:41:42 -0000      1.2
  @@ -448,8 +448,13 @@
       public void markTransactionForRollback(Object txId) throws 
ResourceManagerException {
           assureRMReady();
           TransactionContext context = txInitialSaneCheckForWriting(txId);
  +        try {
           context.status = STATUS_MARKED_ROLLBACK;
           context.saveState();
  +        } finally {
  +            // be very sure to free locks and resources, as application might crash 
or otherwise forget to roll this tx back
  +            context.finalCleanUp();
  +        }
       }
   
       public int prepareTransaction(Object txId) throws ResourceManagerException {
  
  
  

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

Reply via email to