Return-Path: Delivered-To: apmail-jakarta-commons-dev-archive@www.apache.org Received: (qmail 36594 invoked from network); 14 Jul 2007 01:10:12 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 14 Jul 2007 01:10:12 -0000 Received: (qmail 99012 invoked by uid 500); 14 Jul 2007 01:10:12 -0000 Delivered-To: apmail-jakarta-commons-dev-archive@jakarta.apache.org Received: (qmail 98935 invoked by uid 500); 14 Jul 2007 01:10:12 -0000 Mailing-List: contact commons-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Help: List-Post: List-Id: "Jakarta Commons Developers List" Reply-To: "Jakarta Commons Developers List" Delivered-To: mailing list commons-dev@jakarta.apache.org Received: (qmail 98924 invoked by uid 500); 14 Jul 2007 01:10:12 -0000 Received: (qmail 98921 invoked by uid 99); 14 Jul 2007 01:10:12 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Jul 2007 18:10:12 -0700 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Jul 2007 18:10:06 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id 610A11A981A; Fri, 13 Jul 2007 18:09:46 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r556197 - in /jakarta/commons/proper/transaction/branches/TRANSACTION_2: ./ src/java/org/apache/commons/transaction/ src/java/org/apache/commons/transaction/file/ src/java/org/apache/commons/transaction/locking/ src/java/org/apache/commons/... Date: Sat, 14 Jul 2007 01:09:45 -0000 To: commons-cvs@jakarta.apache.org From: ozeigermann@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070714010946.610A11A981A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: ozeigermann Date: Fri Jul 13 18:09:44 2007 New Revision: 556197 URL: http://svn.apache.org/viewvc?view=rev&rev=556197 Log: I kept on throwing away everything not really needed. Next big step is to make rudimentary TxFileResourceManager work again. Need to implement interfaces. Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/ReadWriteLockManager.java Removed: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTxContext.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/Status.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TxContext.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/BlockingReadWriteLockPolicy.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/LockPolicy.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/AbstractTransactionalResource.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/TransactionalResource.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/XidWrapper.java Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/TODO.txt jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResource.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResource.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/DefaultPathManager.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/AbstractXAResource.java Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/TODO.txt URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/TODO.txt?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/TODO.txt (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/TODO.txt Fri Jul 13 18:09:44 2007 @@ -8,12 +8,4 @@ - Optimally, only a single Wrapper remains - All implementations shall be based on AbstractTxContext -- Maybe get rid of lock policy. Could well be integrated into AbstractTxContext - - Question: Is there a need for a different kind of locking? - -- Merge - - org.apache.commons.transaction.TransactionalResource with - - org.apache.commons.transaction.xa.TransactionalResource - - same with the abstract impementations - -- We do not need suspend/resume/etc. in AbstractTransactionManager, we can leave this to the xa transaction manager \ No newline at end of file +- Port JCA implementation for Map from 1.x \ No newline at end of file Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResource.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResource.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResource.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/AbstractTransactionalResource.java Fri Jul 13 18:09:44 2007 @@ -18,8 +18,13 @@ import java.util.HashSet; import java.util.Set; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReadWriteLock; -import org.apache.commons.transaction.locking.LockPolicy; +import org.apache.commons.transaction.locking.LockException; +import org.apache.commons.transaction.locking.LockManager; +import org.apache.commons.transaction.locking.ReadWriteLockManager; +import org.apache.commons.transaction.locking.LockException.Code; /** * Not thread-safe. FIXME: Should it be? @@ -28,7 +33,7 @@ * * @param */ -public abstract class AbstractTransactionalResource implements TransactionalResource { +public abstract class AbstractTransactionalResource implements TransactionalResource { protected ThreadLocal activeTx = new ThreadLocal(); protected Set activeTransactions = new HashSet(); @@ -38,39 +43,15 @@ protected abstract T createContext(); @Override - public boolean isReadOnly() { - TxContext txContext = getActiveTx(); - - if (txContext == null) { - throw new IllegalStateException("Active thread " + Thread.currentThread() - + " not associated with a transaction!"); - } - - return txContext.isReadOnly(); - } - - @Override public boolean isTransactionMarkedForRollback() { - TxContext txContext = getActiveTx(); - - if (txContext == null) { - throw new IllegalStateException("Active thread " + Thread.currentThread() - + " not associated with a transaction!"); - } - - return (txContext.getStatus() == Status.MARKED_ROLLBACK); - } - - @Override - public void markTransactionForRollback() { - TxContext txContext = getActiveTx(); + T txContext = getActiveTx(); if (txContext == null) { throw new IllegalStateException("Active thread " + Thread.currentThread() + " not associated with a transaction!"); } - txContext.setStatus(Status.MARKED_ROLLBACK); + return (txContext.isMarkedForRollback()); } /** @@ -91,7 +72,7 @@ * * @see #resumeTransaction(TxContext) */ - public TxContext suspendTransaction() { + public T suspendTransaction() { T txContext = getActiveTx(); if (txContext == null) { @@ -135,16 +116,6 @@ } @Override - public Status getTransactionState() { - TxContext txContext = getActiveTx(); - - if (txContext == null) { - return Status.NO_TRANSACTION; - } - return txContext.getStatus(); - } - - @Override public void startTransaction() { if (getActiveTx() != null) { throw new IllegalStateException("Active thread " + Thread.currentThread() @@ -158,7 +129,7 @@ @Override public void rollbackTransaction() { - TxContext txContext = getActiveTx(); + T txContext = getActiveTx(); if (txContext == null) { throw new IllegalStateException("Active thread " + Thread.currentThread() @@ -172,14 +143,14 @@ @Override public void commitTransaction() { - TxContext txContext = getActiveTx(); + T txContext = getActiveTx(); if (txContext == null) { throw new IllegalStateException("Active thread " + Thread.currentThread() + " not associated with a transaction!"); } - if (txContext.getStatus() == Status.MARKED_ROLLBACK) { + if (txContext.isMarkedForRollback()) { throw new IllegalStateException("Active thread " + Thread.currentThread() + " is marked for rollback!"); } @@ -191,7 +162,7 @@ @Override public boolean prepareTransaction() { - TxContext txContext = getActiveTx(); + T txContext = getActiveTx(); if (txContext == null) { throw new IllegalStateException("Active thread " + Thread.currentThread() @@ -202,7 +173,7 @@ @Override public void setTransactionTimeout(long mSecs) { - TxContext txContext = getActiveTx(); + T txContext = getActiveTx(); if (txContext == null) { throw new IllegalStateException("Active thread " + Thread.currentThread() @@ -218,6 +189,127 @@ protected void setActiveTx(T txContext) { activeTx.set(txContext); + } + + public boolean isTransactionPrepared() { + // TODO Auto-generated method stub + return false; + } + + public boolean isReadOnlyTransaction() { + // TODO Auto-generated method stub + return false; + } + + public void markTransactionForRollback() { + // TODO Auto-generated method stub + + } + + public abstract class AbstractTxContext { + private long timeout = -1L; + + private long startTime = -1L; + + private boolean readOnly = true; + + private boolean prepared = false; + private boolean markedForRollback = false; + + private ReadWriteLockManager lm = new ReadWriteLockManager(); + + public AbstractTxContext() { + startTime = System.currentTimeMillis(); + } + + protected long getRemainingTimeout() { + long now = System.currentTimeMillis(); + return (getStartTime()- now + timeout); + } + + public void dispose() { + Iterable locks = getLm().getAllForCurrentThread(); + + for (ReadWriteLock lock : locks) { + lock.readLock().unlock(); + lock.writeLock().unlock(); + } + } + + public boolean isReadOnly() { + return readOnly; + } + + public boolean prepare() { + prepared = true; + return true; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTimeMSecs) { + this.startTime = startTimeMSecs; + } + + public long getTimeout() { + return timeout; + } + + public void setTimeout(long timeoutMSecs) { + this.timeout = timeoutMSecs; + } + + public void setReadOnly(boolean readOnly) { + this.readOnly = readOnly; + } + + public ReadWriteLockManager getLm() { + return lm; + } + + protected ReadWriteLock initLock(Object id) { + return getLm().putIfAbsent(id, getLm().create()); + } + + public void readLock(Object id) throws LockException { + try { + boolean locked = initLock(id).readLock().tryLock(getRemainingTimeout(), TimeUnit.MILLISECONDS); + if (!locked) { + throw new LockException(Code.TIMED_OUT, id); + } + } catch (InterruptedException e) { + throw new LockException(Code.INTERRUPTED, id); + } + } + + public void writeLock(Object id)throws LockException { + try { + boolean locked = initLock(id).writeLock().tryLock(getRemainingTimeout(), TimeUnit.MILLISECONDS); + if (!locked) { + throw new LockException(Code.TIMED_OUT, id); + } + } catch (InterruptedException e) { + throw new LockException(Code.INTERRUPTED, id); + } + } + + public boolean isMarkedForRollback() { + return markedForRollback; + } + + public boolean isPrepared() { + return prepared; + } + + public void markForRollback() { + markedForRollback = true; + } + + public void commit() { + + } } } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResource.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResource.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResource.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/TransactionalResource.java Fri Jul 13 18:09:44 2007 @@ -16,6 +16,13 @@ */ package org.apache.commons.transaction; +import javax.transaction.xa.XAException; + +/** + * Interface for something that makes up a transactional resource. + * + * @version $Id: TransactionalResource.java 493628 2007-01-07 01:42:48Z joerg $ + */ public interface TransactionalResource { /** * TODO @@ -25,9 +32,8 @@ public void setTransactionTimeout(long mSecs); /** - * TODO - * - * @return + * Prepares the changes done inside this transaction reasource. + * */ public boolean prepareTransaction(); @@ -86,21 +92,8 @@ */ public void commitTransaction(); - /** - * Returns the state of the current transaction. - * - * @return state of the current transaction as decribed in the - * {@link Status} interface. - */ - public Status getTransactionState(); + boolean isReadOnlyTransaction(); + boolean isTransactionPrepared(); - /** - * Checks if any write operations have been performed inside this - * transaction. - * - * @return true if no write opertation has been performed - * inside the current transaction, false otherwise - */ - public boolean isReadOnly(); } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/DefaultPathManager.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/DefaultPathManager.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/DefaultPathManager.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/DefaultPathManager.java Fri Jul 13 18:09:44 2007 @@ -26,7 +26,7 @@ import org.apache.commons.transaction.util.FileHelper; public class DefaultPathManager implements PathManager { - + private Log logger = LogFactory.getLog(getClass()); protected String workChangeDir = "change"; @@ -37,8 +37,6 @@ protected String storeDir; - - public String getStoreDir() { return storeDir; } @@ -80,11 +78,11 @@ } return path; } - + public String assureLeadingSlash(String pathObject) { String path = ""; if (pathObject != null) { - path = getPathForId(pathObject); + path = getPathForId(pathObject); if (path.length() > 0 && path.charAt(0) != '/' && path.charAt(0) != '\\') { path = "/" + path; } @@ -134,7 +132,7 @@ return txChangePath; } catch (IOException e) { throw new Error("Can not write to resource at '" + path); - + } } @@ -189,6 +187,5 @@ public String getDeleteBaseDir() { return getTransactionBaseDir() + getWorkDeleteDir(); } - } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/FileResourceManager.java Fri Jul 13 18:09:44 2007 @@ -19,24 +19,91 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.Collection; import org.apache.commons.transaction.locking.LockException; public interface FileResourceManager { - public InputStream read(String id) throws IOException, LockException; + + /** + * Checks if there is an object at the position specified by + * path. + * + * @param path + * path of the object to check + * @return true if the object at path exists + */ + boolean exists(String path) throws IOException, LockException; + + /** + * Checks if there is an object at the position specified by + * path and if so if it is a folder. + * + * @param path + * path of the object to check + * @return true if the object at path exists + * and is a folder + */ + boolean isFolder(String path) throws IOException, LockException; + + /** + * Checks if there is an object at the position specified by + * path and if so if it is a content resource. + * + * @param path + * path of the object to check + * @return true if the object at path exists + * and is a file resource + */ + boolean isFile(String path) throws IOException, LockException; + + /** + * Creates a folder at the position specified by folderpath. + * + * @param folderpath + * path of the folder + */ + void createFolder(String folderpath) throws IOException, LockException; + + /** + * Creates a content resource at the position specified by + * path. + * + * @param path + * path of the content resource + */ + void createFile(String path) throws IOException, LockException; + + /** + * Gets the names of the children of the folder specified by + * path. + * + * @param path + * URI of the folder + * @return collection containing names of the children + */ + Collection getChildrenNames(String path) throws IOException, LockException; + + /** + * Gets the content of the file specified by path. + * + * @param path + * path of the content resource + * @return input stream you can read the content of the resource from + */ + public InputStream read(String path) throws IOException, LockException; + + public OutputStream write(String path) throws IOException, LockException; + + /** + * Removes the object specified by uri. + * + * @param uri + * URI of the object, i.e. content resource or folder + */ + public boolean remove(String path) throws IOException, LockException; - public OutputStream write(String id) throws IOException, LockException; - - public boolean remove(String id) throws IOException, LockException; - - public boolean create(String id) throws IOException, LockException; - - public boolean move(String sourceId, String destinationId) throws IOException, LockException; - - public boolean copy(String sourceId, String destinationId) throws IOException, LockException; - - public boolean createDir(String id) throws IOException, LockException; - - public boolean removeDir(String id) throws IOException, LockException; + public boolean move(String sourcepath, String destinationpath) throws IOException, LockException; + public boolean copy(String sourcepath, String destinationpath) throws IOException, LockException; } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/file/TxFileResourceManager.java Fri Jul 13 18:09:44 2007 @@ -16,41 +16,38 @@ */ package org.apache.commons.transaction.file; -import java.io.BufferedReader; -import java.io.BufferedWriter; +import java.io.Closeable; import java.io.File; import java.io.FileInputStream; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.util.ArrayList; -import java.util.List; +import java.util.Collection; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.commons.transaction.AbstractTxContext; -import org.apache.commons.transaction.Status; +import org.apache.commons.transaction.AbstractTransactionalResource; import org.apache.commons.transaction.TransactionalResource; -import org.apache.commons.transaction.TxContext; +import org.apache.commons.transaction.AbstractTransactionalResource.AbstractTxContext; import org.apache.commons.transaction.locking.LockException; -import org.apache.commons.transaction.locking.LockPolicy; import org.apache.commons.transaction.util.FileHelper; -public class TxFileResourceManager implements FileResourceManager { +public class TxFileResourceManager extends + AbstractTransactionalResource implements + FileResourceManager { private Log logger = LogFactory.getLog(getClass()); protected String contextFileName = "transaction.log"; protected PathManager idMapper; - + protected TransactionalResource tm; - public static void applyDeletes(File removeDir, File targetDir, File rootDir) throws IOException { + public static void applyDeletes(File removeDir, File targetDir, File rootDir) + throws IOException { if (removeDir.isDirectory() && targetDir.isDirectory()) { File[] files = removeDir.listFiles(); for (int i = 0; i < files.length; i++) { @@ -65,7 +62,7 @@ } else if (!targetFile.isFile()) { // this is likely a dangling link targetFile.delete(); - } + } // indicate, this has been done removeFile.delete(); } else { @@ -79,8 +76,6 @@ } } - - public String getContextFileName() { return contextFileName; } @@ -89,30 +84,6 @@ this.contextFileName = contextFile; } - public InputStream read(String id) throws IOException { - getLockPolicy().readLock(id, null); - String path = getIdMapper().getPathForRead(id); - return new FileInputStream(new File(path)); - } - - public OutputStream write(String id) throws IOException { - getLockPolicy().writeLock(id, null); - String path = getIdMapper().getPathForRead(id); - return new FileOutputStream(new File(path)); - } - - public boolean remove(String id) throws IOException { - getLockPolicy().writeLock(id, null); - String path = getIdMapper().getPathForDelete(id); - return new File(path).delete(); - } - - public boolean create(String id) throws IOException { - getLockPolicy().writeLock(id, null); - String path = getIdMapper().getPathForDelete(id); - return new File(path).createNewFile(); - } - public PathManager getIdMapper() { return idMapper; } @@ -121,31 +92,17 @@ this.idMapper = idMapper; } - public boolean copy(String sourceId, String destinationId) throws IOException { - // TODO Auto-generated method stub - return false; + @Override + protected FileTxContext createContext() { + return new FileTxContext(); } - public boolean createDir(String id) throws IOException { - // TODO Auto-generated method stub - return false; - } + // TODO resource manager needs to forward requests to this context, locking + // will happen here + public class FileTxContext extends AbstractTxContext implements FileResourceManager { - public boolean move(String sourceId, String destinationId) throws IOException { - // TODO Auto-generated method stub - return false; - } - - public boolean removeDir(String id) throws IOException { - // TODO Auto-generated method stub - return false; - } - - // TODO resource manager needs to forward requests to this context, locking will happen here - public class FileTxContext extends AbstractTxContext implements TxContext, FileResourceManager { - // list of streams participating in this tx - private List openResources = new ArrayList(); + private Collection openStreams = new ArrayList(); public FileTxContext() { super(); @@ -154,11 +111,8 @@ new File(changeDir).mkdirs(); new File(deleteDir).mkdirs(); - - saveState(); } - public void commit() { super.commit(); String changeDir = getIdMapper().getChangeBaseDir(); @@ -178,74 +132,58 @@ FileHelper.removeRec(new File(baseDir)); } - public void saveState() { - String statePath = getIdMapper().getTransactionBaseDir() + "/" + getContextFileName(); - File file = new File(statePath); - BufferedWriter writer = null; - try { - OutputStream os = new FileOutputStream(file); - writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8")); - writer.write(toString()); - } catch (FileNotFoundException e) { - String msg = "Saving status information to '" + statePath + "' failed! Could not create file"; - logger.fatal(msg, e); - throw new Error(msg, e); - } catch (IOException e) { - String msg = "Saving status information to '" + statePath + "' failed"; - logger.fatal(msg, e); - throw new Error(msg, e); - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException e) { - } + public boolean copy(String sourceId, String destinationId) throws IOException, + LockException { + // TODO Auto-generated method stub + return false; + } - } - } + public boolean createDir(String id) throws IOException, LockException { + // TODO Auto-generated method stub + return false; } - public void recoverState() { - String statePath = getIdMapper().getTransactionBaseDir() + "/" + getContextFileName(); - File file = new File(statePath); - BufferedReader reader = null; - try { - InputStream is = new FileInputStream(file); + public boolean move(String sourceId, String destinationId) throws IOException, + LockException { + // TODO Auto-generated method stub + return false; + } - reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - setStatus(Status.valueOf(reader.readLine())); - setTimeout(Long.parseLong(reader.readLine())); - setStartTime(Long.parseLong(reader.readLine())); - } catch (FileNotFoundException e) { - String msg = "Recovering status information from '" + statePath + "' failed! Could not find file"; - logger.fatal(msg, e); - throw new Error(msg, e); - } catch (IOException e) { - String msg = "Recovering status information from '" + statePath + "' failed"; - logger.fatal(msg, e); - throw new Error(msg, e); - } catch (Throwable t) { - String msg = "Recovering status information from '" + statePath + "' failed"; - logger.fatal(msg, t); - throw new Error(msg, t); - } finally { - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - } + public InputStream read(String id) throws IOException, LockException { + readLock(id); + String path = getIdMapper().getPathForRead(id); + InputStream is = new FileInputStream(new File(path)); + registerStream(is); + return is; + } - } - } + public OutputStream write(String id) throws IOException { + writeLock(id); + String path = getIdMapper().getPathForRead(id); + return new FileOutputStream(new File(path)); } - public String toString() { - StringBuffer buf = new StringBuffer(); - buf.append(getStatus().name()).append('\n'); - buf.append(Long.toString(getTimeout())).append('\n'); - buf.append(Long.toString(getStartTime())).append('\n'); - return buf.toString(); + public boolean remove(String id) throws IOException { + writeLock(id); + String path = getIdMapper().getPathForDelete(id); + return new File(path).delete(); + } + + public boolean create(String id) throws IOException { + writeLock(id); + String path = getIdMapper().getPathForDelete(id); + return new File(path).createNewFile(); + } + + public boolean removeDir(String id) throws IOException, LockException { + // TODO Auto-generated method stub + return false; + } + + protected void registerStream(Closeable stream) { + openStreams.add(stream); } } + } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/GenericLockManager.java Fri Jul 13 18:09:44 2007 @@ -34,6 +34,7 @@ return globalLocks.values(); } + // FIXME public Set getAllForCurrentThread() { // TODO Auto-generated method stub return null; Added: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/ReadWriteLockManager.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/ReadWriteLockManager.java?view=auto&rev=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/ReadWriteLockManager.java (added) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/locking/ReadWriteLockManager.java Fri Jul 13 18:09:44 2007 @@ -0,0 +1,13 @@ +package org.apache.commons.transaction.locking; + +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + + +public class ReadWriteLockManager extends GenericLockManager implements LockManager { + + public ReadWriteLock create() { + return new ReentrantReadWriteLock(); + } + +} Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/OptimisticMapWrapper.java Fri Jul 13 18:09:44 2007 @@ -16,33 +16,37 @@ */ package org.apache.commons.transaction.memory; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; -import org.apache.commons.transaction.Status; -import org.apache.commons.transaction.TxContext; -import org.apache.commons.transaction.locking.BlockingReadWritegetLockPolicy(); import org.apache.commons.transaction.locking.LockException; /** - * Wrapper that adds transactional control to all kinds of maps that implement the {@link Map} interface. By using - * a naive optimistic transaction control this wrapper has better isolation than {@link TransactionalMapWrapper}, but - * may also fail to commit. - * - *
- * Start a transaction by calling {@link #startTransaction()}. Then perform the normal actions on the map and - * finally either call {@link #commitTransaction()} to make your changes permanent or {@link #rollbackTransaction()} to - * undo them. - *
- * Caution: Do not modify values retrieved by {@link #get(Object)} as this will circumvent the transactional mechanism. - * Rather clone the value or copy it in a way you see fit and store it back using {@link #put(Object, Object)}. - *
- * Note: This wrapper guarantees isolation level SERIALIZABLE. + * Wrapper that adds transactional control to all kinds of maps that implement + * the {@link Map} interface. By using a naive optimistic transaction control + * this wrapper has better isolation than {@link TransactionalMapWrapper}, but + * may also fail to commit. + * *
- * Caution: This implementation might be slow when large amounts of data is changed in a transaction as much references will need to be copied around. + * Start a transaction by calling {@link #startTransaction()}. Then perform the + * normal actions on the map and finally either call + * {@link #commitTransaction()} to make your changes permanent or + * {@link #rollbackTransaction()} to undo them.
+ * Caution: Do not modify values retrieved by {@link #get(Object)} as + * this will circumvent the transactional mechanism. Rather clone the value or + * copy it in a way you see fit and store it back using + * {@link #put(Object, Object)}.
+ * Note: This wrapper guarantees isolation level + * SERIALIZABLE.
+ * Caution: This implementation might be slow when large amounts of + * data is changed in a transaction as much references will need to be copied + * around. * * @version $Id: OptimisticMapWrapper.java 493628 2007-01-07 01:42:48Z joerg $ * @see TransactionalMapWrapper @@ -50,23 +54,27 @@ */ public class OptimisticMapWrapper extends TransactionalMapWrapper { - protected static final int COMMIT_TIMEOUT = 1000 * 60; // 1 minute - protected static final int ACCESS_TIMEOUT = 1000 * 30; // 30 seconds + private ReadWriteLock commitLock; + + private long commitTimeout = 1000 * 60; // 1 minute - protected static final Object COMMIT_LOCK = "COMMIT"; + private long accessTimeout = 1000 * 30; // 30 seconds /** - * Creates a new optimistic transactional map wrapper. Temporary maps and sets to store transactional - * data will be instances of {@link java.util.HashMap} and {@link java.util.HashSet}. + * Creates a new optimistic transactional map wrapper. Temporary maps and + * sets to store transactional data will be instances of + * {@link java.util.HashMap} and {@link java.util.HashSet}. * - * @param wrapped map to be wrapped + * @param wrapped + * map to be wrapped */ public OptimisticMapWrapper(Map wrapped) { super(wrapped); + commitLock = new ReentrantReadWriteLock(); } public void rollbackTransaction() { - TxContext txContext = getActiveTx(); + MapTxContext txContext = getActiveTx(); super.rollbackTransaction(); activeTransactions.remove(txContext); } @@ -76,21 +84,22 @@ } public void commitTransaction(boolean force) throws LockException { - TxContext txContext = getActiveTx(); + MapTxContext txContext = getActiveTx(); if (txContext == null) { throw new IllegalStateException( "Active thread " + Thread.currentThread() + " not associated with a transaction!"); } - if (txContext.getStatus() == Status.MARKED_ROLLBACK) { + if (txContext.isMarkedForRollback()) { throw new IllegalStateException("Active thread " + Thread.currentThread() + " is marked for rollback!"); } try { - // in this final commit phase we need to be the only one access the map + // in this final commit phase we need to be the only one access the + // map // to make sure no one adds an entry after we checked for conflicts - getLockPolicy().acquireWrite(txContext, COMMIT_TIMEOUT); + commitLock.writeLock().tryLock(getCommitTimeout(), TimeUnit.MILLISECONDS); if (!force) { Object conflictKey = checkForConflicts(); @@ -106,7 +115,7 @@ } catch (InterruptedException e) { throw new LockException(e); } finally { - getLockPolicy().release(txContext); + commitLock.writeLock().unlock(); } } @@ -133,12 +142,14 @@ for (Iterator it = activeTransactions.iterator(); it.hasNext();) { CopyingTxContext otherTxContext = (CopyingTxContext) it.next(); - // no need to copy data if the other transaction does not access global map anyway + // no need to copy data if the other transaction does not access + // global map anyway if (otherTxContext.cleared) continue; if (thisTxContext.cleared) { - // we will clear everything, so we have to copy everything before + // we will clear everything, so we have to copy everything + // before otherTxContext.externalChanges.putAll(wrapped); } else // no need to check if we have already copied everthing { @@ -164,17 +175,24 @@ } } } + + @Override + protected CopyingTxContext createContext() { + return new CopyingTxContext(); + } public class CopyingTxContext extends MapTxContext { protected Map externalChanges; + protected Map externalAdds; + protected Set externalDeletes; protected CopyingTxContext() { super(); - externalChanges = mapFactory.createMap(); - externalDeletes = setFactory.createSet(); - externalAdds = mapFactory.createMap(); + externalChanges = new HashMap(); + externalDeletes = new HashSet(); + externalAdds = new HashMap(); } protected Set externalChangedKeys() { @@ -195,7 +213,7 @@ protected Set keys() { try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); + commitLock.readLock().tryLock(getAccessTimeout(), TimeUnit.MILLISECONDS); Set keySet = super.keys(); keySet.removeAll(externalDeletes); keySet.addAll(externalAdds.keySet()); @@ -203,135 +221,131 @@ } catch (InterruptedException e) { return null; } finally { - getLockPolicy().release(this); + commitLock.readLock().unlock(); } } protected Object get(Object key) { try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); + commitLock.readLock().tryLock(getAccessTimeout(), TimeUnit.MILLISECONDS); if (deletes.contains(key)) { - // reflects that entry has been deleted in this tx + // reflects that entry has been deleted in this tx return null; } - + Object changed = changes.get(key); if (changed != null) { return changed; } - + Object added = adds.get(key); if (added != null) { return added; } - + if (cleared) { return null; } else { if (externalDeletes.contains(key)) { - // reflects that entry has been deleted in this tx + // reflects that entry has been deleted in this tx return null; } - + changed = externalChanges.get(key); if (changed != null) { return changed; } - + added = externalAdds.get(key); if (added != null) { return added; } - + // not modified in this tx return wrapped.get(key); } } catch (InterruptedException e) { return null; } finally { - getLockPolicy().release(this); + commitLock.readLock().unlock(); } } protected void put(Object key, Object value) { try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); + commitLock.readLock().tryLock(getAccessTimeout(), TimeUnit.MILLISECONDS); super.put(key, value); } catch (InterruptedException e) { } finally { - getLockPolicy().release(this); + commitLock.readLock().unlock(); } } protected void remove(Object key) { try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); + commitLock.readLock().tryLock(getAccessTimeout(), TimeUnit.MILLISECONDS); super.remove(key); } catch (InterruptedException e) { } finally { - getLockPolicy().release(this); + commitLock.readLock().unlock(); } } protected int size() { try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); + commitLock.readLock().tryLock(getAccessTimeout(), TimeUnit.MILLISECONDS); int size = super.size(); - + size -= externalDeletes.size(); size += externalAdds.size(); - + return size; } catch (InterruptedException e) { return -1; } finally { - getLockPolicy().release(this); + commitLock.readLock().unlock(); } } protected void clear() { try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); + commitLock.readLock().tryLock(getAccessTimeout(), TimeUnit.MILLISECONDS); super.clear(); externalDeletes.clear(); externalChanges.clear(); externalAdds.clear(); } catch (InterruptedException e) { } finally { - getLockPolicy().release(this); + commitLock.readLock().unlock(); } } - protected void merge() { + public void commit() { try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); - super.merge(); + commitLock.readLock().tryLock(getAccessTimeout(), TimeUnit.MILLISECONDS); + super.commit(); } catch (InterruptedException e) { } finally { - getLockPolicy().release(this); + commitLock.readLock().unlock(); } } - protected void dispose() { - try { - getLockPolicy().acquireRead(this, ACCESS_TIMEOUT); - super.dispose(); - setFactory.disposeSet(externalDeletes); - externalDeletes = null; - mapFactory.disposeMap(externalChanges); - externalChanges = null; - mapFactory.disposeMap(externalAdds); - externalAdds = null; - } catch (InterruptedException e) { - } finally { - getLockPolicy().release(this); - } - } + } - protected void finalize() throws Throwable { - activeTransactions.remove(this); - super.finalize(); - } + public long getAccessTimeout() { + return accessTimeout; + } + + public void setAccessTimeout(long accessTimeout) { + this.accessTimeout = accessTimeout; + } + + public long getCommitTimeout() { + return commitTimeout; + } + + public void setCommitTimeout(long commitTimeout) { + this.commitTimeout = commitTimeout; } } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/PessimisticMapWrapper.java Fri Jul 13 18:09:44 2007 @@ -22,18 +22,21 @@ import java.util.Set; /** - * Wrapper that adds transactional control to all kinds of maps that implement the {@link Map} interface. By using - * pessimistic transaction control (blocking locks) this wrapper has better isolation than {@link TransactionalMapWrapper}, but - * also has less possible concurrency and may even deadlock. A commit, however, will never fail. - *
- * Start a transaction by calling {@link #startTransaction()}. Then perform the normal actions on the map and - * finally either call {@link #commitTransaction()} to make your changes permanent or {@link #rollbackTransaction()} to - * undo them. - *
- * Caution: Do not modify values retrieved by {@link #get(Object)} as this will circumvent the transactional mechanism. - * Rather clone the value or copy it in a way you see fit and store it back using {@link #put(Object, Object)}. - *
- * Note: This wrapper guarantees isolation level SERIALIZABLE. + * Wrapper that adds transactional control to all kinds of maps that implement + * the {@link Map} interface. By using pessimistic transaction control (blocking + * locks) this wrapper has better isolation than {@link TransactionalMapWrapper}, + * but also has less possible concurrency and may even deadlock. A commit, + * however, will never fail.
+ * Start a transaction by calling {@link #startTransaction()}. Then perform the + * normal actions on the map and finally either call + * {@link #commitTransaction()} to make your changes permanent or + * {@link #rollbackTransaction()} to undo them.
+ * Caution: Do not modify values retrieved by {@link #get(Object)} as + * this will circumvent the transactional mechanism. Rather clone the value or + * copy it in a way you see fit and store it back using + * {@link #put(Object, Object)}.
+ * Note: This wrapper guarantees isolation level + * SERIALIZABLE. * * @version $Id: PessimisticMapWrapper.java 493628 2007-01-07 01:42:48Z joerg $ * @see TransactionalMapWrapper @@ -43,13 +46,13 @@ protected static final Object GLOBAL_LOCK = "GLOBAL"; - protected long readTimeOut = 60000; /* FIXME: pass in ctor */ - /** - * Creates a new pessimistic transactional map wrapper. Temporary maps and sets to store transactional - * data will be instances of {@link java.util.HashMap} and {@link java.util.HashSet}. + * Creates a new pessimistic transactional map wrapper. Temporary maps and + * sets to store transactional data will be instances of + * {@link java.util.HashMap} and {@link java.util.HashSet}. * - * @param wrapped map to be wrapped + * @param wrapped + * map to be wrapped */ public PessimisticMapWrapper(Map wrapped) { super(wrapped); @@ -71,14 +74,16 @@ } public Object remove(Object key) { - // assure we get a write lock before super can get a read lock to avoid lots + // assure we get a write lock before super can get a read lock to avoid + // lots // of deadlocks assureWriteLock(key); return super.remove(key); } public Object put(Object key, Object value) { - // assure we get a write lock before super can get a read lock to avoid lots + // assure we get a write lock before super can get a read lock to avoid + // lots // of deadlocks assureWriteLock(key); return super.put(key, value); @@ -89,22 +94,27 @@ if (txContext != null) { txContext.writeLock(key); // XXX fake intention lock (prohibits global WRITE) - txContext.readLock(GLOBAL_LOCK); + txContext.readLock(GLOBAL_LOCK); } } - + protected void assureGlobalReadLock() { LockingTxContext txContext = (LockingTxContext) getActiveTx(); if (txContext != null) { // XXX fake intention lock (prohibits global WRITE) - txContext.readLock(GLOBAL_LOCK); + txContext.readLock(GLOBAL_LOCK); } } - + + @Override + protected LockingTxContext createContext() { + return new LockingTxContext(); + } + public class LockingTxContext extends MapTxContext { protected Set keys() { - readLock(GLOBAL_LOCK); + readLock(GLOBAL_LOCK); return super.keys(); } @@ -130,7 +140,8 @@ } protected int size() { - // XXX this is bad luck, we need a global read lock just for the size :( :( :( + // XXX this is bad luck, we need a global read lock just for the + // size :( :( :( readLock(GLOBAL_LOCK); return super.size(); } @@ -140,10 +151,6 @@ super.clear(); } - protected void finalize() throws Throwable { - dispose(); - super.finalize(); - } } } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/memory/TransactionalMapWrapper.java Fri Jul 13 18:09:44 2007 @@ -26,40 +26,44 @@ import java.util.Set; import org.apache.commons.transaction.AbstractTransactionalResource; -import org.apache.commons.transaction.AbstractTxContext; -import org.apache.commons.transaction.Status; import org.apache.commons.transaction.TransactionalResource; -import org.apache.commons.transaction.TxContext; +import org.apache.commons.transaction.AbstractTransactionalResource.AbstractTxContext; /** - * Wrapper that adds transactional control to all kinds of maps that implement the {@link Map} interface. - * This wrapper has rather weak isolation, but is simply, neven blocks and commits will never fail for logical - * reasons. - *
- * Start a transaction by calling {@link #startTransaction()}. Then perform the normal actions on the map and - * finally either call {@link #commitTransaction()} to make your changes permanent or {@link #rollbackTransaction()} to - * undo them. - *
- * Caution: Do not modify values retrieved by {@link #get(Object)} as this will circumvent the transactional mechanism. - * Rather clone the value or copy it in a way you see fit and store it back using {@link #put(Object, Object)}. - *
- * Note: This wrapper guarantees isolation level READ COMMITTED only. I.e. as soon a value - * is committed in one transaction it will be immediately visible in all other concurrent transactions. + * Wrapper that adds transactional control to all kinds of maps that implement + * the {@link Map} interface. This wrapper has rather weak isolation, but is + * simply, neven blocks and commits will never fail for logical reasons.
+ * Start a transaction by calling {@link #startTransaction()}. Then perform the + * normal actions on the map and finally either call + * {@link #commitTransaction()} to make your changes permanent or + * {@link #rollbackTransaction()} to undo them.
+ * Caution: Do not modify values retrieved by {@link #get(Object)} as + * this will circumvent the transactional mechanism. Rather clone the value or + * copy it in a way you see fit and store it back using + * {@link #put(Object, Object)}.
+ * Note: This wrapper guarantees isolation level + * READ COMMITTED only. I.e. as soon a value is committed in one + * transaction it will be immediately visible in all other concurrent + * transactions. * * @version $Id: TransactionalMapWrapper.java 493628 2007-01-07 01:42:48Z joerg $ * @see OptimisticMapWrapper * @see PessimisticMapWrapper */ -public class TransactionalMapWrapper extends AbstractTransactionalResource implements Map, TransactionalResource { +public class TransactionalMapWrapper extends + AbstractTransactionalResource implements Map, + TransactionalResource { /** The map wrapped. */ protected Map wrapped; /** - * Creates a new transactional map wrapper. Temporary maps and sets to store transactional - * data will be instances of {@link java.util.HashMap} and {@link java.util.HashSet}. + * Creates a new transactional map wrapper. Temporary maps and sets to store + * transactional data will be instances of {@link java.util.HashMap} and + * {@link java.util.HashSet}. * - * @param wrapped map to be wrapped + * @param wrapped + * map to be wrapped */ public TransactionalMapWrapper(Map wrapped) { this.wrapped = Collections.synchronizedMap(wrapped); @@ -68,14 +72,13 @@ // can be used by sub classes protected TransactionalMapWrapper() { } - // // Map methods // /** - * @see Map#clear() + * @see Map#clear() */ public void clear() { MapTxContext txContext = getActiveTx(); @@ -87,7 +90,7 @@ } /** - * @see Map#size() + * @see Map#size() */ public int size() { MapTxContext txContext = getActiveTx(); @@ -99,7 +102,7 @@ } /** - * @see Map#isEmpty() + * @see Map#isEmpty() */ public boolean isEmpty() { MapTxContext txContext = getActiveTx(); @@ -111,17 +114,17 @@ } /** - * @see Map#containsKey(java.lang.Object) + * @see Map#containsKey(java.lang.Object) */ public boolean containsKey(Object key) { - return keySet().contains(key); + return keySet().contains(key); } /** - * @see Map#containsValue(java.lang.Object) + * @see Map#containsValue(java.lang.Object) */ public boolean containsValue(Object value) { - TxContext txContext = getActiveTx(); + MapTxContext txContext = getActiveTx(); if (txContext == null) { return wrapped.containsValue(value); @@ -131,11 +134,11 @@ } /** - * @see Map#values() + * @see Map#values() */ public Collection values() { - TxContext txContext = getActiveTx(); + MapTxContext txContext = getActiveTx(); if (txContext == null) { return wrapped.values(); @@ -145,7 +148,8 @@ for (Iterator it = keySet().iterator(); it.hasNext();) { Object key = it.next(); Object value = get(key); - // XXX we have no isolation, so get entry might have been deleted in the meantime + // XXX we have no isolation, so get entry might have been + // deleted in the meantime if (value != null) { values.add(value); } @@ -155,7 +159,7 @@ } /** - * @see Map#putAll(java.util.Map) + * @see Map#putAll(java.util.Map) */ public void putAll(Map map) { MapTxContext txContext = getActiveTx(); @@ -171,10 +175,10 @@ } /** - * @see Map#entrySet() + * @see Map#entrySet() */ public Set entrySet() { - TxContext txContext = getActiveTx(); + MapTxContext txContext = getActiveTx(); if (txContext == null) { return wrapped.entrySet(); } else { @@ -183,7 +187,8 @@ for (Iterator it = keySet().iterator(); it.hasNext();) { Object key = it.next(); Object value = get(key); - // XXX we have no isolation, so get entry might have been deleted in the meantime + // XXX we have no isolation, so get entry might have been + // deleted in the meantime if (value != null) { entrySet.add(new HashEntry(key, value)); } @@ -193,7 +198,7 @@ } /** - * @see Map#keySet() + * @see Map#keySet() */ public Set keySet() { MapTxContext txContext = getActiveTx(); @@ -206,7 +211,7 @@ } /** - * @see Map#get(java.lang.Object) + * @see Map#get(java.lang.Object) */ public Object get(Object key) { MapTxContext txContext = getActiveTx(); @@ -219,7 +224,7 @@ } /** - * @see Map#remove(java.lang.Object) + * @see Map#remove(java.lang.Object) */ public Object remove(Object key) { MapTxContext txContext = getActiveTx(); @@ -249,10 +254,21 @@ } + @Override + protected MapTxContext createContext() { + return new MapTxContext(); + } + + @Override + protected MapTxContext getActiveTx() { + return activeTx.get(); + } + // mostly copied from org.apache.commons.collections.map.AbstractHashedMap protected static class HashEntry implements Map.Entry { /** The key */ protected Object key; + /** The value */ protected Object value; @@ -284,11 +300,13 @@ } Map.Entry other = (Map.Entry) obj; return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) - && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue())); + && (getValue() == null ? other.getValue() == null : getValue().equals( + other.getValue())); } public int hashCode() { - return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); + return (getKey() == null ? 0 : getKey().hashCode()) + ^ (getValue() == null ? 0 : getValue().hashCode()); } public String toString() { @@ -296,10 +314,13 @@ } } - public class MapTxContext extends AbstractTxContext implements TxContext { + public class MapTxContext extends AbstractTxContext { protected Set deletes; + protected Map changes; + protected Map adds; + protected boolean cleared; protected MapTxContext() { @@ -322,15 +343,15 @@ protected Object get(Object key) { if (deletes.contains(key)) { - // reflects that entry has been deleted in this tx + // reflects that entry has been deleted in this tx return null; } - if(changes.containsKey(key)){ + if (changes.containsKey(key)) { return changes.get(key); } - if(adds.containsKey(key)){ + if (adds.containsKey(key)) { return adds.get(key); } @@ -352,10 +373,10 @@ adds.put(key, value); } } catch (RuntimeException e) { - setStatus(Status.MARKED_ROLLBACK); + markForRollback(); throw e; } catch (Error e) { - setStatus(Status.MARKED_ROLLBACK); + markForRollback(); throw e; } } @@ -370,10 +391,10 @@ deletes.add(key); } } catch (RuntimeException e) { - setStatus(Status.MARKED_ROLLBACK); + markForRollback(); throw e; } catch (Error e) { - setStatus(Status.MARKED_ROLLBACK); + markForRollback(); throw e; } } @@ -396,7 +417,7 @@ } protected boolean isEmpty() { - return (size() == 0); + return (size() == 0); } public void commit() { @@ -416,15 +437,6 @@ } } - public void setTimeout(long timeoutMSecs) { - // TODO Auto-generated method stub - - } - } - @Override - protected MapTxContext createContext() { - return new MapTxContext(); - } } Modified: jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/AbstractXAResource.java URL: http://svn.apache.org/viewvc/jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/AbstractXAResource.java?view=diff&rev=556197&r1=556196&r2=556197 ============================================================================== --- jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/AbstractXAResource.java (original) +++ jakarta/commons/proper/transaction/branches/TRANSACTION_2/src/java/org/apache/commons/transaction/xa/AbstractXAResource.java Fri Jul 13 18:09:44 2007 @@ -29,9 +29,11 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.transaction.TransactionalResource; /** - * Abstract XAResource doing all the tedious tasks shared by many XAResouce implementations. + * Abstract XAResource doing all the tedious tasks shared by many XAResouce + * implementations. * * @version $Id: AbstractXAResource.java 493628 2007-01-07 01:42:48Z joerg $ */ @@ -43,14 +45,13 @@ private ThreadLocal activeTransactionBranch = new ThreadLocal(); private Map suspendedContexts = Collections.synchronizedMap(new HashMap()); + private Map activeContexts = Collections.synchronizedMap(new HashMap()); public abstract boolean isSameRM(XAResource xares) throws XAException; public abstract Xid[] recover(int flag) throws XAException; - protected abstract boolean includeBranchInXid(); - public void forget(Xid xid) throws XAException { if (logger.isDebugEnabled()) { logger.debug("Forgetting transaction branch " + xid); @@ -74,18 +75,18 @@ logger.debug("Committing transaction branch " + ts); } - if (ts.getStatus() == STATUS_MARKED_ROLLBACK) { + if (ts.isTransactionMarkedForRollback()) { throw new XAException(XAException.XA_RBROLLBACK); } - if (ts.getStatus() != STATUS_PREPARED) { + if (ts.isTransactionPrepared()) { if (onePhase) { - ts.prepare(); + ts.prepareTransaction(); } else { throw new XAException(XAException.XAER_PROTO); } } - ts.commit(); + ts.commitTransaction(); setCurrentlyActiveTransactionalResource(null); removeActiveTransactionalResource(xid); removeSuspendedTransactionalResource(xid); @@ -101,7 +102,7 @@ logger.debug("Rolling back transaction branch " + ts); } - ts.rollback(); + ts.rollbackTransaction(); setCurrentlyActiveTransactionalResource(null); removeActiveTransactionalResource(xid); removeSuspendedTransactionalResource(xid); @@ -117,17 +118,26 @@ logger.debug("Preparing transaction branch " + ts); } - if (ts.getStatus() == STATUS_MARKED_ROLLBACK) { + if (ts.isTransactionMarkedForRollback()) { throw new XAException(XAException.XA_RBROLLBACK); } - - int result = ts.prepare(); - ts.setStatus(STATUS_PREPARED); - + + int result; + boolean prepared = ts.prepareTransaction(); + if (prepared) { + if (ts.isReadOnlyTransaction()) { + result = XA_RDONLY; + } else { + result = XA_OK; + } + } else { + throw new XAException(XAException.XA_RBROLLBACK); + } + if (result == XA_RDONLY) { commit(xid, false); } - + return result; } @@ -140,24 +150,26 @@ throw new XAException(XAException.XAER_INVAL); } if (logger.isDebugEnabled()) { - logger.debug(new StringBuffer(128) - .append("Thread ").append(Thread.currentThread()) - .append(flags == TMSUSPEND ? " suspends" : flags == TMFAIL ? " fails" : " ends") - .append(" work on behalf of transaction branch ") - .append(ts).toString()); + logger + .debug(new StringBuffer(128).append("Thread ").append(Thread.currentThread()) + .append( + flags == TMSUSPEND ? " suspends" : flags == TMFAIL ? " fails" + : " ends").append( + " work on behalf of transaction branch ").append(ts).toString()); } switch (flags) { - case TMSUSPEND : - ts.suspend(); - addSuspendedTransactionalResource(xid, ts); - removeActiveTransactionalResource(xid); - break; - case TMFAIL : - ts.setStatus(STATUS_MARKED_ROLLBACK); - break; - case TMSUCCESS : - break; + case TMSUSPEND: + // FIXME: This would require action on the transactional resource, + // but we just can't do that + addSuspendedTransactionalResource(xid, ts); + removeActiveTransactionalResource(xid); + break; + case TMFAIL: + ts.markTransactionForRollback(); + break; + case TMSUCCESS: + break; } setCurrentlyActiveTransactionalResource(null); } @@ -167,35 +179,36 @@ throw new XAException(XAException.XAER_INVAL); } if (logger.isDebugEnabled()) { - logger.debug(new StringBuffer(128) - .append("Thread ").append(Thread.currentThread()) - .append(flags == TMNOFLAGS ? " starts" : flags == TMJOIN ? " joins" : " resumes") - .append(" work on behalf of transaction branch ") + logger.debug(new StringBuffer(128).append("Thread ").append(Thread.currentThread()) + .append( + flags == TMNOFLAGS ? " starts" : flags == TMJOIN ? " joins" + : " resumes").append(" work on behalf of transaction branch ") .append(xid).toString()); } - + TransactionalResource ts; switch (flags) { - // a new transaction - case TMNOFLAGS : - case TMJOIN : - default : - try { - ts = createTransactionResource(xid); - ts.begin(); - } catch (Exception e) { - logger.error("Could not create new transactional resource", e); - throw new XAException(e.getMessage()); - } - break; - case TMRESUME : - ts = getSuspendedTransactionalResource(xid); - if (ts == null) { - throw new XAException(XAException.XAER_NOTA); - } - ts.resume(); - removeSuspendedTransactionalResource(xid); - break; + // a new transaction + case TMNOFLAGS: + case TMJOIN: + default: + try { + ts = createTransactionResource(xid); + ts.startTransaction(); + } catch (Exception e) { + logger.error("Could not create new transactional resource", e); + throw new XAException(e.getMessage()); + } + break; + case TMRESUME: + ts = getSuspendedTransactionalResource(xid); + if (ts == null) { + throw new XAException(XAException.XAER_NOTA); + } + // FIXME: This would require action on the transactional resource, + // but we just can't do that + removeSuspendedTransactionalResource(xid); + break; } setCurrentlyActiveTransactionalResource(ts); addAcitveTransactionalResource(xid, ts); @@ -213,38 +226,35 @@ } protected TransactionalResource getTransactionalResource(Xid xid) { - TransactionalResource ts = getActiveTransactionalResource(xid); - if (ts != null) return ts; - else return getSuspendedTransactionalResource(xid); + TransactionalResource ts = getActiveTransactionalResource(xid); + if (ts != null) + return ts; + else + return getSuspendedTransactionalResource(xid); } + protected TransactionalResource getActiveTransactionalResource(Xid xid) { - Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); - return (TransactionalResource) activeContexts.get(wxid); + return (TransactionalResource) activeContexts.get(xid); } protected TransactionalResource getSuspendedTransactionalResource(Xid xid) { - Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); - return (TransactionalResource) suspendedContexts.get(wxid); + return (TransactionalResource) suspendedContexts.get(xid); } protected void addAcitveTransactionalResource(Xid xid, TransactionalResource txContext) { - Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); - activeContexts.put(wxid, txContext); + activeContexts.put(xid, txContext); } protected void addSuspendedTransactionalResource(Xid xid, TransactionalResource txContext) { - Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); - suspendedContexts.put(wxid, txContext); + suspendedContexts.put(xid, txContext); } protected void removeActiveTransactionalResource(Xid xid) { - Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); - activeContexts.remove(wxid); + activeContexts.remove(xid); } protected void removeSuspendedTransactionalResource(Xid xid) { - Xid wxid = XidWrapper.wrap(xid, includeBranchInXid()); - suspendedContexts.remove(wxid); + suspendedContexts.remove(xid); } } --------------------------------------------------------------------- To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: commons-dev-help@jakarta.apache.org