Author: kwall
Date: Fri Dec 14 14:25:09 2012
New Revision: 1421884

URL: http://svn.apache.org/viewvc?rev=1421884&view=rev
Log:
QPID-4503: Producer transaction timeout detection feature may produce suprious 
open/idle alerts and close client connections/sessions without good cause

Race conditon existed between the initial check that determined transaction 
timeout detection was required and the subsequent re-observeration
required to perform the open and idle calculation.  In the unlucky timing, the 
state of the transaction changed between these two points.  (To produce
the time-since-epoch type the transaction needs to be committed between these 
two points).

Changed checkTransactionStatus so that transactionStartTime and 
transactionUpdateTime are observed once only.

There still exists the possibility that the transaction status change change 
between the reading of transactionStartTime and transactionUpdateTime
times, but I do not see how this could produce a suprious report (or close).  
The alternative (to take a locks to ensure consistent observations
are made) seems unjustifiably costly.

Modified:
    
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
    
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
    
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java

Modified: 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java?rev=1421884&r1=1421883&r2=1421884&view=diff
==============================================================================
--- 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
 (original)
+++ 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
 Fri Dec 14 14:25:09 2012
@@ -70,7 +70,6 @@ import org.apache.qpid.server.message.Me
 import org.apache.qpid.server.message.ServerMessage;
 import org.apache.qpid.server.output.ProtocolOutputConverter;
 import org.apache.qpid.server.protocol.AMQConnectionModel;
-import org.apache.qpid.server.protocol.AMQProtocolEngine;
 import org.apache.qpid.server.protocol.AMQProtocolSession;
 import org.apache.qpid.server.protocol.AMQSessionModel;
 import org.apache.qpid.server.queue.AMQQueue;
@@ -113,7 +112,7 @@ public class AMQChannel implements AMQSe
      */
     private long _deliveryTag = 0;
 
-    /** A channel has a default queue (the last declared) that is used when no 
queue name is explictily set */
+    /** A channel has a default queue (the last declared) that is used when no 
queue name is explicitly set */
     private AMQQueue _defaultQueue;
 
     /** This tag is unique per subscription to a queue. The server returns 
this in response to a basic.consume request. */
@@ -209,10 +208,6 @@ public class AMQChannel implements AMQSe
     }
 
 
-    public boolean inTransaction()
-    {
-        return isTransactional() && _txnUpdateTime.get() > 0 && 
_transaction.getTransactionStartTime() > 0;
-    }
 
     private void incrementOutstandingTxnsIfNecessary()
     {
@@ -1487,11 +1482,13 @@ public class AMQChannel implements AMQSe
 
     public void checkTransactionStatus(long openWarn, long openClose, long 
idleWarn, long idleClose) throws AMQException
     {
-        if (inTransaction())
+        final long transactionStartTime = 
_transaction.getTransactionStartTime();
+        final long transactionUpdateTime = _txnUpdateTime.get();
+        if (isTransactional() && transactionUpdateTime > 0 && 
transactionStartTime > 0)
         {
             long currentTime = System.currentTimeMillis();
-            long openTime = currentTime - 
_transaction.getTransactionStartTime();
-            long idleTime = currentTime - _txnUpdateTime.get();
+            long openTime = currentTime - transactionStartTime;
+            long idleTime = currentTime - transactionUpdateTime;
 
             _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, 
ChannelMessages.IDLE_TXN(idleTime),
                                                      
TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT);

Modified: 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java?rev=1421884&r1=1421883&r2=1421884&view=diff
==============================================================================
--- 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
 (original)
+++ 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java
 Fri Dec 14 14:25:09 2012
@@ -42,7 +42,6 @@ import javax.security.auth.Subject;
 import org.apache.qpid.AMQException;
 import org.apache.qpid.AMQStoreException;
 import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.protocol.ProtocolEngine;
 import org.apache.qpid.server.TransactionTimeoutHelper;
 import org.apache.qpid.server.logging.LogActor;
 import org.apache.qpid.server.logging.LogSubject;
@@ -449,11 +448,6 @@ public class ServerSession extends Sessi
         return _transaction.isTransactional();
     }
 
-    public boolean inTransaction()
-    {
-        return isTransactional() && _txnUpdateTime.get() > 0 && 
_transaction.getTransactionStartTime() > 0;
-    }
-
     public void selectTx()
     {
         _transaction = new LocalTransaction(this.getMessageStore());
@@ -591,7 +585,7 @@ public class ServerSession extends Sessi
     /**
      * Update last transaction activity timestamp
      */
-    public void updateTransactionalActivity()
+    private void updateTransactionalActivity()
     {
         if (isTransactional())
         {
@@ -709,11 +703,13 @@ public class ServerSession extends Sessi
 
     public void checkTransactionStatus(long openWarn, long openClose, long 
idleWarn, long idleClose) throws AMQException
     {
-        if (inTransaction())
+        final long transactionStartTime = 
_transaction.getTransactionStartTime();
+        final long transactionUpdateTime = _txnUpdateTime.get();
+        if (isTransactional() && transactionUpdateTime > 0 && 
transactionStartTime > 0)
         {
             long currentTime = System.currentTimeMillis();
-            long openTime = currentTime - 
_transaction.getTransactionStartTime();
-            long idleTime = currentTime - _txnUpdateTime.get();
+            long openTime = currentTime - transactionStartTime;
+            long idleTime = currentTime - transactionUpdateTime;
 
             _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, 
ChannelMessages.IDLE_TXN(idleTime),
                                                      
TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT);

Modified: 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java?rev=1421884&r1=1421883&r2=1421884&view=diff
==============================================================================
--- 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
 (original)
+++ 
qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java
 Fri Dec 14 14:25:09 2012
@@ -50,7 +50,7 @@ public class LocalTransaction implements
 
     private volatile Transaction _transaction;
     private MessageStore _transactionLog;
-    private long _txnStartTime = 0L;
+    private volatile long _txnStartTime = 0L;
     private StoreFuture _asyncTran;
 
     public LocalTransaction(MessageStore transactionLog)



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to