-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
https://reviews.apache.org/r/5794/#review9055
-----------------------------------------------------------


Hi Rajith,

The suggested code changes looks reasonable for me.
I could not find any issue with the suggested solution.

The only thing I would like to ask is to add some tests to cover the changes.
For example, I used the following tests to test your changes with Java Broker

public class ExceptionHandlingTest extends QpidBrokerTestCase implements 
ExceptionListener
{

    private AMQConnection _connection;
    private AMQSession_0_10 _exceptionSession;
    private AMQSession_0_10 _session;
    private JMSException _exception;

    public void setUp() throws Exception
    {
        super.setUp();
        _connection = (AMQConnection) getConnection();
        _connection.setExceptionListener(this);
        _session = (AMQSession_0_10) _connection.createSession(false, 
Session.AUTO_ACKNOWLEDGE);
        _exceptionSession = (AMQSession_0_10) _connection.createSession(false, 
Session.AUTO_ACKNOWLEDGE);
        _exception = null;
    }

    public void testDeclareStandardEchange() throws Exception
    {
        Exception caughtException = null;
        try
        {
            _exceptionSession.declareExchange(new 
AMQShortString("qpid.management"), new AMQShortString("direct"), false);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            caughtException = e;
        }
        assertState();
        assertTrue("Unexpected exception", caughtException == null || 
caughtException instanceof AMQException);
    }

    public void testDeclareQueuePassiveForNonExistingQueue() throws Exception
    {
        Exception caughtException = null;
        try
        {
            _exceptionSession.send0_10QueueDeclare((AMQDestination) 
getTestQueue(), _connection.getProtocolHandler(), false,
                    false, true);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            caughtException = e;
        }
        assertState();
        assertTrue("Unexpected exception", caughtException == null || 
caughtException instanceof AMQException);
    }

    @Override
    public void onException(JMSException exception)
    {
        _exception = exception;
    }

    private void assertState() throws Exception
    {
        assertFalse("Connection has been closed unexpectedly", 
_connection.isClosed());
        assertFalse("Not affected session has been closed unexpectedly", 
_session.isClosed());
        assertNotNull("Exception is not received", _exception);
        assertTrue("Exception session has not been closed", 
_exceptionSession.isClosed());

        // assert that JMS operations are performed OK on non-affected session
        Destination queue = _session.createQueue(getTestQueueName());
        MessageConsumer consumer = _session.createConsumer(queue);
        MessageProducer producer = _session.createProducer(queue);
        producer.send(_session.createTextMessage("Test"));
        _connection.start();
        Message m = consumer.receive(1000l);
        assertNotNull("Test message has not been received", m);
        consumer.close();
        producer.close();
    }
}

I did not try to run these tests with CPP broker.

The failing test SelectorTest#testRuntimeSelectorError can be fixed by 
replacing the assert checking if connection is closed 
assertTrue("Connection should be closed", _connection.isClosed());
with assert checking if session is closed
assertTrue("Session should be closed", (AMQSession<?,?)session.isClosed());


Apart from adding the tests, I do not have any other commentaries about the 
suggested changes.

- Oleksandr Rudyy


On July 6, 2012, 12:39 a.m., rajith attapattu wrote:
> 
> -----------------------------------------------------------
> This is an automatically generated e-mail. To reply, visit:
> https://reviews.apache.org/r/5794/
> -----------------------------------------------------------
> 
> (Updated July 6, 2012, 12:39 a.m.)
> 
> 
> Review request for qpid, Robbie Gemmell, Keith Wall, and Rob Godfrey.
> 
> 
> Description
> -------
> 
> When a session exception is received, we notify the connection via the 
> exceptionReceived method. The connection will close all sessions for this 
> connection, but does not close the underlying Protocol connection.
> Further calls (from application code) to close the connection, does not close 
> the underlying protocol-connection as it skips this part, due to the 
> connection already being marked as closed.
> This results in leaked connections.
> 
> The proposed patch does the following.
> 1. When a session exception is received, it closes the Session (and the 
> consumers/producers associated with it) to prevent further use of this 
> session.
> 2. It also notifies the connection, however the exception being passed, is 
> marked as a soft error, thereby preventing the connection from being marked 
> as closed.
>    It also prevents the rest of the sessions being closed.
> 3. The exception will however be notified via the exception listener. This is 
> important in certain cases, as it might be the only case where an exception 
> can be notified.
> 
> What is the impact to applications.
> ------------------------------------
> 1. If an application closes the connection when it receives an exception, and 
> then recreates the connection and it's associated objects 
> (sessions/consumers/producers) then this change will have no impact.
> 
> 2. If an application just recreates everything from scratch, without 
> resorting to closing the connection (assuming that all exceptions received 
> via the listener will automatically close the connection), there will be tcp 
> connection leaks. 
> However the objects associated with the connection will eventualy be garbage 
> collected. We should probably close the underlying TCP connection in the 
> finalizer for the Connection object as a safety measure.
> 
> With this change, the recommended approach would be, for application to check 
> the connection status in deciding what it should do.
> For example, 
> 
> if (conn.isClosed())
> {
>    // re-create connection.
> }
> else
> {
>   // session exception
>   // this means the rest of the sessions and the connection is still open.
> }
> 
> 
> This addresses bug QPID-3575.
>     https://issues.apache.org/jira/browse/QPID-3575
> 
> 
> Diffs
> -----
> 
>   
> http://svn.apache.org/repos/asf/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
>  1357981 
>   
> http://svn.apache.org/repos/asf/qpid/trunk/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java
>  1357981 
>   
> http://svn.apache.org/repos/asf/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java
>  1357981 
> 
> Diff: https://reviews.apache.org/r/5794/diff/
> 
> 
> Testing
> -------
> 
> Tested with the default java profile and the cpp test profile.
> 
> SelectorTest#testRuntimeSelectorError is failing as it expects the connection 
> to be closed.
> I need to investigate further to determine if the test needs to be changed or 
> not.
> 
> 
> Thanks,
> 
> rajith attapattu
> 
>

Reply via email to