On Thu, 2007-02-08 at 09:20 +0000, Marnie McCormack wrote: > Hi Carl & Kim, > > Are there any applicable JIRAs I can look at for pointers ? > > Thanks, > Marnie > > > On 2/6/07, Carl Trieloff <[EMAIL PROTECTED]> wrote: > > > > > > Quite a few issues where found in this area on the 0-9 branch. I might > > be good to sync up with Kim on the > > issues resolved on the 0-9 branch that have not been merged back to > > trunk yet. > > > > Carl. > > > > > > Marnie McCormack (JIRA) wrote: > > > Message loss after rollback > > > --------------------------- > > > > > > Key: QPID-346 > > > URL: https://issues.apache.org/jira/browse/QPID-346 > > > Project: Qpid > > > Issue Type: Bug > > > Components: Java Client > > > Affects Versions: M1 > > > Reporter: Marnie McCormack > > > > > > > > > Rolling back a transaction after a message consume alwasy results in the > > loss of a message > > > > > > I am not certain whether this is directly related to your problem, but here are the details:
I have found that there is a problem with rollback() on the trunk (mirrored in the 0-9 branch, but solved there), and the following patch to TransactedTest reveals the problem. Part of the changes in the patch move the creation of messages A,B,C into the two (original) tests that use them, as the later addition of the testResendsMsgsAfterSessionClose() method does not use these, and leaves them around for later tests to stumble across. If you patch the test, and run mvn -Dtest=TransactedTest test then you will see the following: Running org.apache.qpid.test.unit.transacted.TransactedTest Tests run: 5, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 8.639 sec <<< FAILURE! testEmpty2(org.apache.qpid.test.unit.transacted.TransactedTest) Time elapsed: 1.064 sec <<< FAILURE! junit.framework.AssertionFailedError at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.assertTrue(Assert.java:20) at junit.framework.Assert.assertTrue(Assert.java:27) at org.apache.qpid.test.unit.transacted.TransactedTest.testEmpty2(TransactedTest.java:181) which indicates that the messages X,Y,Z are still around after the rollback test completed. If the commit() method on line 158 (post-patch) is uncommented, then the failure changes to: Running org.apache.qpid.test.unit.transacted.TransactedTest Tests run: 5, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 8.689 sec <<< FAILURE! testRollback(org.apache.qpid.test.unit.transacted.TransactedTest) Time elapsed: 1.09 sec <<< FAILURE! junit.framework.AssertionFailedError at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.assertTrue(Assert.java:20) at junit.framework.Assert.assertTrue(Assert.java:27) at org.apache.qpid.test.unit.transacted.TransactedTest.testRollback(TransactedTest.java:167) which shows that inspite the rollback, X,Y,Z were still downloaded. Take a look at r501577 for how this was solved on the 0-9 branch. Note that the changes to the definition of queue Q1 on line 61 made earlier on the trunk may mask certain problems related to this... If this line is changed back to queue1 = new AMQQueue("Q1", false); then if there are still messages left over from the test, they tend to interfere with one of the later tests (RecoverTest, I think) when the entire test suite is run together. For this reason I added the empty checks after each test which consume any left-over messages in the process of reporting the error. Ideally, tests should clean up after themselves, and not leave stray messages around. Making the queue temporary, as this change did, may have masked the underlying problem. I plan to check this change to TransactedTest into Subversion at some point, if you find that it is appropriate, you can do so for me... I hope this helps, Kim
Index: java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java =================================================================== --- java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java (revision 504866) +++ java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java (working copy) @@ -74,23 +74,11 @@ prepSession = prepCon.createSession(false, AMQSession.NO_ACKNOWLEDGE); prepProducer1 = prepSession.createProducer(queue1); prepCon.start(); - - - //add some messages - prepProducer1.send(prepSession.createTextMessage("A")); - prepProducer1.send(prepSession.createTextMessage("B")); - prepProducer1.send(prepSession.createTextMessage("C")); - - testCon = new AMQConnection("vm://:1", "guest", "guest", "TestConnection", "test"); - testSession = testCon.createSession(false, AMQSession.NO_ACKNOWLEDGE); - testConsumer2 = testSession.createConsumer(queue2); - } protected void tearDown() throws Exception { con.close(); - testCon.close(); prepCon.close(); TransportConnection.killAllVMBrokers(); super.tearDown(); @@ -98,6 +86,11 @@ public void testCommit() throws Exception { + //add some messages + prepProducer1.send(prepSession.createTextMessage("A")); + prepProducer1.send(prepSession.createTextMessage("B")); + prepProducer1.send(prepSession.createTextMessage("C")); + //send and receive some messages producer2.send(session.createTextMessage("X")); producer2.send(session.createTextMessage("Y")); @@ -108,19 +101,44 @@ //commit session.commit(); + + //ensure sent messages can be received and received messages are gone + testCon = new AMQConnection("vm://:1", "guest", "guest", "TestConnection", "test"); + testSession = testCon.createSession(false, AMQSession.NO_ACKNOWLEDGE); + testConsumer1 = testSession.createConsumer(queue1); + testConsumer2 = testSession.createConsumer(queue2); testCon.start(); - //ensure sent messages can be received and received messages are gone + expect("X", testConsumer2.receive(1000)); expect("Y", testConsumer2.receive(1000)); expect("Z", testConsumer2.receive(1000)); + assertTrue(null == testConsumer1.receive(1000)); + assertTrue(null == testConsumer2.receive(1000)); + testCon.close(); + } + + // This checks that queues Q1 & Q2 are in fact empty and do not have any stray + // messages left over from the last test (which can affect later tests)... + public void testEmpty1() throws Exception + { + testCon = new AMQConnection("vm://:1", "guest", "guest", "TestConnection", "test"); + testSession = testCon.createSession(false, AMQSession.NO_ACKNOWLEDGE); testConsumer1 = testSession.createConsumer(queue1); + testConsumer2 = testSession.createConsumer(queue2); + testCon.start(); assertTrue(null == testConsumer1.receive(1000)); assertTrue(null == testConsumer2.receive(1000)); + testCon.close(); } public void testRollback() throws Exception { + //add some messages + prepProducer1.send(prepSession.createTextMessage("A")); + prepProducer1.send(prepSession.createTextMessage("B")); + prepProducer1.send(prepSession.createTextMessage("C")); + producer2.send(session.createTextMessage("X")); producer2.send(session.createTextMessage("Y")); producer2.send(session.createTextMessage("Z")); @@ -135,10 +153,33 @@ expect("A", consumer1.receive(1000)); expect("B", consumer1.receive(1000)); expect("C", consumer1.receive(1000)); + + //commit + //session.commit(); + + testCon = new AMQConnection("vm://:1", "guest", "guest", "TestConnection", "test"); + testSession = testCon.createSession(false, AMQSession.NO_ACKNOWLEDGE); + testConsumer1 = testSession.createConsumer(queue1); + testConsumer2 = testSession.createConsumer(queue2); testCon.start(); + + assertTrue(null == testConsumer1.receive(1000)); + assertTrue(null == testConsumer2.receive(1000)); + testCon.close(); + } + + // This checks that queues Q1 & Q2 are in fact empty and do not have any stray + // messages left over from the last test (which can affect later tests)... + public void testEmpty2() throws Exception + { + testCon = new AMQConnection("vm://:1", "guest", "guest", "TestConnection", "test"); + testSession = testCon.createSession(false, AMQSession.NO_ACKNOWLEDGE); testConsumer1 = testSession.createConsumer(queue1); + testConsumer2 = testSession.createConsumer(queue2); + testCon.start(); assertTrue(null == testConsumer1.receive(1000)); assertTrue(null == testConsumer2.receive(1000)); + testCon.close(); } public void testResendsMsgsAfterSessionClose() throws Exception