Merged V2.1 to HEAD

6338: Some WCM-435.
   6344: Fix for AWC-1452 (dialog close navigation issue)
   6345: Fix for AR-1611 and other related CIFS and NFS fixes
   6346: Minor javadoc fix for ReplicatingContentStore
   6347: Handle exceptions arising from UserTransaction.begin().
   6348: Many WCM fixes in one
            Conflicts resolved on faces-config-beans.xml


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@6722 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-09-10 13:21:08 +00:00
parent e3e2711e29
commit cd78bd51ba
7 changed files with 146 additions and 44 deletions

View File

@@ -27,7 +27,6 @@ package org.alfresco.filesys.server;
import java.net.InetAddress; import java.net.InetAddress;
import javax.transaction.Status; import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction; import javax.transaction.UserTransaction;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
@@ -36,7 +35,11 @@ import org.alfresco.filesys.server.auth.ClientInfo;
import org.alfresco.filesys.server.core.SharedDevice; import org.alfresco.filesys.server.core.SharedDevice;
import org.alfresco.filesys.server.core.SharedDeviceList; import org.alfresco.filesys.server.core.SharedDeviceList;
import org.alfresco.filesys.server.filesys.FilesysTransaction; import org.alfresco.filesys.server.filesys.FilesysTransaction;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.service.transaction.TransactionService; import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.transaction.SpringAwareUserTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/** /**
* Server Session Base Class * Server Session Base Class
@@ -45,6 +48,9 @@ import org.alfresco.service.transaction.TransactionService;
*/ */
public abstract class SrvSession public abstract class SrvSession
{ {
// Logging
private static final Log logger = LogFactory.getLog(SrvSession.class);
// Network server this session is associated with // Network server this session is associated with
@@ -102,9 +108,6 @@ public abstract class SrvSession
private ThreadLocal<FilesysTransaction> m_tx = new ThreadLocal<FilesysTransaction>(); private ThreadLocal<FilesysTransaction> m_tx = new ThreadLocal<FilesysTransaction>();
// UserTransaction m_transaction;
// private boolean m_readOnlyTrans;
// Request and transaction counts // Request and transaction counts
protected int m_reqCount; protected int m_reqCount;
@@ -505,6 +508,11 @@ public abstract class SrvSession
private final boolean beginTransaction(TransactionService transService, boolean readOnly) private final boolean beginTransaction(TransactionService transService, boolean readOnly)
throws AlfrescoRuntimeException throws AlfrescoRuntimeException
{ {
// DEBUG
if ( logger.isDebugEnabled())
logger.debug( "Begin transaction readOnly=" + readOnly);
boolean created = false; boolean created = false;
// Get the filesystem transaction // Get the filesystem transaction
@@ -514,6 +522,11 @@ public abstract class SrvSession
{ {
filesysTx = new FilesysTransaction(); filesysTx = new FilesysTransaction();
m_tx.set( filesysTx); m_tx.set( filesysTx);
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Created FilesysTransaction");
} }
// If there is an active transaction check that it is the required type // If there is an active transaction check that it is the required type
@@ -535,6 +548,11 @@ public abstract class SrvSession
// Rollback the current transaction // Rollback the current transaction
tx.rollback(); tx.rollback();
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Rolled back existing transaction");
} }
} }
catch ( Exception ex) catch ( Exception ex)
@@ -552,15 +570,21 @@ public abstract class SrvSession
tx.commit(); tx.commit();
m_transConvCount++; m_transConvCount++;
} }
catch ( Exception ex) catch ( Throwable ex)
{ {
throw new AlfrescoRuntimeException("Failed to commit read-only transaction, " + ex.getMessage()); ex.printStackTrace();
// throw new AlfrescoRuntimeException("Failed to commit read-only transaction, " + ex.getMessage());
} }
finally finally
{ {
// Clear the active transaction // Clear the active transaction
filesysTx.clearTransaction(); filesysTx.clearTransaction();
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Cleared existing transaction (read/write)");
} }
} }
} }
@@ -571,15 +595,46 @@ public abstract class SrvSession
{ {
try try
{ {
UserTransaction userTrans = transService.getUserTransaction(readOnly); // Create the transaction
userTrans.begin();
UserTransaction userTrans = null;
if ( AlfrescoTransactionSupport.getTransactionId() != null) {
// Create a non-propagating transaction as there is an active transaction
userTrans = transService.getNonPropagatingUserTransaction(readOnly);
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("%%%%% Transaction active id=" + AlfrescoTransactionSupport.getTransactionId() + ", started=" + AlfrescoTransactionSupport.getTransactionStartTime());
}
else {
// Create a normal transaction
userTrans = transService.getUserTransaction(readOnly);
}
// Start the transaction
userTrans.begin();
created = true; created = true;
// Store the transaction // Store the transaction
filesysTx.setTransaction( userTrans, readOnly); filesysTx.setTransaction( userTrans, readOnly);
m_transCount++; m_transCount++;
// DEBUG
if ( logger.isDebugEnabled()) {
logger.debug("Created transaction readOnly=" + readOnly + ", tx=" + userTrans + ", txSts=" + userTrans.getStatus());
SpringAwareUserTransaction springTx = (SpringAwareUserTransaction) userTrans;
logger.debug(" Tx details readOnly=" + springTx.isReadOnly() + ", txStatus=" + springTx.getStatus() + ",id=" + AlfrescoTransactionSupport.getTransactionId());
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -614,7 +669,9 @@ public abstract class SrvSession
{ {
// Commit or rollback the transaction // Commit or rollback the transaction
if ( tx.getStatus() == Status.STATUS_MARKED_ROLLBACK) if ( tx.getStatus() == Status.STATUS_MARKED_ROLLBACK ||
tx.getStatus() == Status.STATUS_ROLLEDBACK ||
tx.getStatus() == Status.STATUS_ROLLING_BACK)
{ {
// Transaction is marked for rollback // Transaction is marked for rollback
@@ -629,13 +686,19 @@ public abstract class SrvSession
} }
catch ( Exception ex) catch ( Exception ex)
{ {
throw new AlfrescoRuntimeException("Failed to end transaction", ex); ex.printStackTrace();
// throw new AlfrescoRuntimeException("Failed to end transaction", ex);
} }
finally finally
{ {
// Clear the current transaction // Clear the current transaction
filesysTx.clearTransaction(); filesysTx.clearTransaction();
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Cleared existing transaction (end)");
} }
} }

View File

@@ -261,6 +261,11 @@ public class AlfrescoRpcAuthenticator implements RpcAuthenticator {
// Clear the authentication, null user should not be allowed to do any service calls // Clear the authentication, null user should not be allowed to do any service calls
m_authComponent.clearCurrentSecurityContext(); m_authComponent.clearCurrentSecurityContext();
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Clear security context, client=" + client);
} }
else if ( client.isGuest() == false) else if ( client.isGuest() == false)
{ {
@@ -272,12 +277,22 @@ public class AlfrescoRpcAuthenticator implements RpcAuthenticator {
m_authComponent.setCurrentUser( client.getUserName()); m_authComponent.setCurrentUser( client.getUserName());
client.setAuthenticationToken( m_authComponent.getCurrentAuthentication()); client.setAuthenticationToken( m_authComponent.getCurrentAuthentication());
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Set user name=" + client.getUserName() + ", token=" + client.getAuthenticationToken());
} }
else else
{ {
// Set the authentication context for the request // Set the authentication context for the request
m_authComponent.setCurrentAuthentication( client.getAuthenticationToken()); m_authComponent.setCurrentAuthentication( client.getAuthenticationToken());
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Set user using auth token, token=" + client.getAuthenticationToken());
} }
} }
else else
@@ -285,7 +300,16 @@ public class AlfrescoRpcAuthenticator implements RpcAuthenticator {
// Enable guest access for the request // Enable guest access for the request
m_authComponent.setGuestUserAsCurrentUser(); m_authComponent.setGuestUserAsCurrentUser();
// DEBUG
if ( logger.isDebugEnabled())
logger.debug("Set guest user");
} }
// Commit the authentication transaction
sess.endTransaction();
} }
/** /**

View File

@@ -1666,8 +1666,7 @@ public class NFSServer extends RpcNetworkServer implements RpcProcessor {
// Write to the network file // Write to the network file
disk.writeFile(sess, conn, netFile, rpc.getBuffer(), rpc disk.writeFile(sess, conn, netFile, rpc.getBuffer(), rpc.getPosition(), count, offset);
.getPosition(), count, offset);
} }
// Get file information for the path and pack the response // Get file information for the path and pack the response
@@ -1707,8 +1706,7 @@ public class NFSServer extends RpcNetworkServer implements RpcProcessor {
// DEBUG // DEBUG
if (logger.isDebugEnabled() && hasDebugFlag(DBG_ERROR)) { if (logger.isDebugEnabled() && hasDebugFlag(DBG_ERROR)) {
logger.debug("Write Exception: netFile=" + netFile + ", cache=" + sess.getFileCache().numberOfEntries()); logger.debug("Write Exception: netFile=" + netFile + ", cache=" + sess.getFileCache().numberOfEntries(), ex);
logger.debug(ex);
} }
} }
@@ -1902,6 +1900,9 @@ public class NFSServer extends RpcNetworkServer implements RpcProcessor {
} }
catch (AccessDeniedException ex) { catch (AccessDeniedException ex) {
errorSts = NFS.StsAccess; errorSts = NFS.StsAccess;
if ( logger.isDebugEnabled())
logger.debug("Create error:", ex);
} }
catch (Exception ex) { catch (Exception ex) {
errorSts = NFS.StsServerFault; errorSts = NFS.StsServerFault;
@@ -1909,7 +1910,7 @@ public class NFSServer extends RpcNetworkServer implements RpcProcessor {
// DEBUG // DEBUG
if (logger.isDebugEnabled() && hasDebugFlag(DBG_ERROR)) if (logger.isDebugEnabled() && hasDebugFlag(DBG_ERROR))
logger.debug("Create Exception: " + ex.toString()); logger.debug("Create Exception: " + ex.toString(), ex);
} }
// Check for a failure status // Check for a failure status
@@ -3241,8 +3242,7 @@ public class NFSServer extends RpcNetworkServer implements RpcProcessor {
// DEBUG // DEBUG
if (logger.isDebugEnabled() && hasDebugFlag(DBG_SEARCH)) if (logger.isDebugEnabled() && hasDebugFlag(DBG_SEARCH))
logger.debug("ReadDir return entries=" + entCnt + ", eof=" logger.debug("ReadDir return entries=" + (entCnt - 1) + ", eof=" + search.hasMoreFiles());
+ search.hasMoreFiles());
} }
catch (BadHandleException ex) { catch (BadHandleException ex) {
errorSts = NFS.StsBadHandle; errorSts = NFS.StsBadHandle;
@@ -3612,7 +3612,7 @@ public class NFSServer extends RpcNetworkServer implements RpcProcessor {
// DEBUG // DEBUG
if (logger.isDebugEnabled() && hasDebugFlag(DBG_SEARCH)) if (logger.isDebugEnabled() && hasDebugFlag(DBG_SEARCH))
logger.debug("ReadDirPlus return entries=" + entCnt + ", eof=" + (search.hasMoreFiles() ? false : true)); logger.debug("ReadDirPlus return entries=" + (entCnt - 1) + ", eof=" + (search.hasMoreFiles() ? false : true));
} }
catch (BadHandleException ex) { catch (BadHandleException ex) {
errorSts = NFS.StsBadHandle; errorSts = NFS.StsBadHandle;

View File

@@ -277,6 +277,12 @@ public class NetworkFileCache {
// Close the file via the disk interface // Close the file via the disk interface
try { try {
// DEBUG
if ( logger.isDebugEnabled())
logger.debug( "NFSFileExpiry: Closing file " + fentry.getFile().getFullName());
// Set the current user using the session that last accessed the file // Set the current user using the session that last accessed the file

View File

@@ -567,6 +567,10 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
*/ */
public FileInfo getFileInformation(SrvSession session, TreeConnection tree, String path) throws IOException public FileInfo getFileInformation(SrvSession session, TreeConnection tree, String path) throws IOException
{ {
// Start a transaction
session.beginReadTransaction(transactionService);
// Get the device root // Get the device root
ContentContext ctx = (ContentContext) tree.getContext(); ContentContext ctx = (ContentContext) tree.getContext();
@@ -598,7 +602,6 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
{ {
// Get the file information for the node // Get the file information for the node
session.beginReadTransaction(transactionService);
finfo = cifsHelper.getFileInformation(nodeRef); finfo = cifsHelper.getFileInformation(nodeRef);
} }
@@ -624,10 +627,6 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
if ( fstate.hasNodeRef() == false) if ( fstate.hasNodeRef() == false)
{ {
// Create the transaction
session.beginReadTransaction(transactionService);
// Get the node for the folder path // Get the node for the folder path
fstate.setNodeRef( getNodeForPath( tree, paths[0])); fstate.setNodeRef( getNodeForPath( tree, paths[0]));
@@ -674,7 +673,6 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
{ {
// Get the file information for the node // Get the file information for the node
session.beginReadTransaction(transactionService);
finfo = cifsHelper.getFileInformation(nodeRef); finfo = cifsHelper.getFileInformation(nodeRef);
// DEBUG // DEBUG
@@ -688,10 +686,6 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
if ( finfo == null) if ( finfo == null)
{ {
// Start a transaction
session.beginReadTransaction(transactionService);
String[] paths = FileName.splitPath( path); String[] paths = FileName.splitPath( path);
if ( paths[0] != null && paths[0].length() > 1) if ( paths[0] != null && paths[0].length() > 1)
@@ -737,6 +731,13 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
} }
catch (FileNotFoundException e) catch (FileNotFoundException e)
{ {
// Check if there is a transaction active
if ( session.hasUserTransaction() == false) {
System.out.println("***** getFileInformation() - no transaction active");
e.printStackTrace();
}
// a valid use case // a valid use case
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Getting file information - File not found: \n" + logger.debug("Getting file information - File not found: \n" +
@@ -1458,7 +1459,7 @@ public class ContentDiskDriver extends AlfrescoDiskDriver implements DiskInterfa
// DEBUG // DEBUG
if ( logger.isDebugEnabled()) if ( logger.isDebugEnabled())
logger.debug("Creaste file, state=" + fstate); logger.debug("Create file, state=" + fstate);
} }
} }

View File

@@ -88,7 +88,7 @@ import org.apache.commons.logging.LogFactory;
* *
* <h2><u>No Replication</u></h2> * <h2><u>No Replication</u></h2>
* <p> * <p>
* Content is not written to the primary store only. The other stores are * Content is written to the primary store only. The other stores are
* only used to retrieve content and the primary store is not updated with * only used to retrieve content and the primary store is not updated with
* the content. * the content.
* *

View File

@@ -51,7 +51,7 @@ import org.springframework.dao.DeadlockLoserDataAccessException;
public class RetryingTransactionHelper public class RetryingTransactionHelper
{ {
private static final String MSG_READ_ONLY = "permissions.err_read_only"; private static final String MSG_READ_ONLY = "permissions.err_read_only";
private static Logger fgLogger = Logger.getLogger(RetryingTransactionHelper.class); private static Logger logger = Logger.getLogger(RetryingTransactionHelper.class);
/** /**
* Exceptions that trigger retries. * Exceptions that trigger retries.
@@ -71,12 +71,12 @@ public class RetryingTransactionHelper
/** /**
* Reference to the TransactionService instance. * Reference to the TransactionService instance.
*/ */
private TransactionService fTxnService; private TransactionService txnService;
/** /**
* The maximum number of retries. -1 for infinity. * The maximum number of retries. -1 for infinity.
*/ */
private int fMaxRetries; private int maxRetries;
/** /**
* Whether the the transactions may only be reads * Whether the the transactions may only be reads
@@ -86,7 +86,7 @@ public class RetryingTransactionHelper
/** /**
* Random number generator for retry delays. * Random number generator for retry delays.
*/ */
private Random fRandom; private Random random;
/** /**
* Callback interface * Callback interface
@@ -108,7 +108,7 @@ public class RetryingTransactionHelper
*/ */
public RetryingTransactionHelper() public RetryingTransactionHelper()
{ {
fRandom = new Random(System.currentTimeMillis()); this.random = new Random(System.currentTimeMillis());
} }
// Setters. // Setters.
@@ -117,7 +117,7 @@ public class RetryingTransactionHelper
*/ */
public void setTransactionService(TransactionService service) public void setTransactionService(TransactionService service)
{ {
fTxnService = service; this.txnService = service;
} }
/** /**
@@ -125,7 +125,7 @@ public class RetryingTransactionHelper
*/ */
public void setMaxRetries(int maxRetries) public void setMaxRetries(int maxRetries)
{ {
fMaxRetries = maxRetries; this.maxRetries = maxRetries;
} }
/** /**
@@ -199,7 +199,7 @@ public class RetryingTransactionHelper
// Track the last exception caught, so that we // Track the last exception caught, so that we
// can throw it if we run out of retries. // can throw it if we run out of retries.
RuntimeException lastException = null; RuntimeException lastException = null;
for (int count = 0; fMaxRetries < 0 || count < fMaxRetries; ++count) for (int count = 0; maxRetries < 0 || count < maxRetries; ++count)
{ {
UserTransaction txn = null; UserTransaction txn = null;
boolean isNew = false; boolean isNew = false;
@@ -207,11 +207,11 @@ public class RetryingTransactionHelper
{ {
if (requiresNew) if (requiresNew)
{ {
txn = fTxnService.getNonPropagatingUserTransaction(); txn = txnService.getNonPropagatingUserTransaction();
} }
else else
{ {
txn = fTxnService.getUserTransaction(readOnly); txn = txnService.getUserTransaction(readOnly);
} }
// Only start a transaction if required. This check isn't necessary as the transactional // Only start a transaction if required. This check isn't necessary as the transactional
// behaviour ensures that the appropriate propogation is performed. It is a useful and // behaviour ensures that the appropriate propogation is performed. It is a useful and
@@ -239,11 +239,11 @@ public class RetryingTransactionHelper
txn.commit(); txn.commit();
} }
} }
if (fgLogger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
if (count != 0) if (count != 0)
{ {
fgLogger.debug( logger.debug(
"Transaction succeeded after " + count + "Transaction succeeded after " + count +
" retries on thread " + Thread.currentThread().getName()); " retries on thread " + Thread.currentThread().getName());
} }
@@ -271,21 +271,29 @@ public class RetryingTransactionHelper
{ {
try try
{ {
if (txn.getStatus() != Status.STATUS_ROLLEDBACK) int txnStatus = txn.getStatus();
// We can only rollback if a transaction was started (NOT NO_TRANSACTION) and
// if that transaction has not been rolled back (NOT ROLLEDBACK).
// If an exception occurs while the transaction is being created (e.g. no database connection)
// then the status will be NO_TRANSACTION.
if (txnStatus != Status.STATUS_NO_TRANSACTION && txnStatus != Status.STATUS_ROLLEDBACK)
{ {
txn.rollback(); txn.rollback();
} }
} }
catch (IllegalStateException e1) catch (IllegalStateException e1)
{ {
logger.error(e);
throw new AlfrescoRuntimeException("Failure during rollback: " + cb, e1); throw new AlfrescoRuntimeException("Failure during rollback: " + cb, e1);
} }
catch (SecurityException e1) catch (SecurityException e1)
{ {
logger.error(e);
throw new AlfrescoRuntimeException("Failure during rollback: " + cb, e1); throw new AlfrescoRuntimeException("Failure during rollback: " + cb, e1);
} }
catch (SystemException e1) catch (SystemException e1)
{ {
logger.error(e);
throw new AlfrescoRuntimeException("Failure during rollback: " + cb, e1); throw new AlfrescoRuntimeException("Failure during rollback: " + cb, e1);
} }
} }
@@ -299,7 +307,7 @@ public class RetryingTransactionHelper
// The sleep interval increases with the number of retries. // The sleep interval increases with the number of retries.
try try
{ {
Thread.sleep(fRandom.nextInt(500 * count + 500)); Thread.sleep(random.nextInt(500 * count + 500));
} }
catch (InterruptedException ie) catch (InterruptedException ie)
{ {