Uploaded image for project: 'MINA'
  1. MINA
  2. DIRMINA-777

IoSessionConfig.setUseReadOperation(true) doesn't seem to work

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Blocker
    • Resolution: Fixed
    • Affects Version/s: 2.0.0-RC1
    • Fix Version/s: 2.0.8
    • Component/s: Core
    • Environment:
      Mac OS X 10.6.2, Java 1.6, Android SDK

      Description

      I'm attempting to perform a synchronous write/read in a demux-based client application with MINA 2.0 RC1, but it seems to get stuck. Here is my code:

      public boolean login(final String username, final String password) {
          // block inbound messages
          session.getConfig().setUseReadOperation(true);
      
          // send the login request
          final LoginRequest loginRequest = new LoginRequest(username, password);
          final WriteFuture writeFuture = session.write(loginRequest);
          writeFuture.awaitUninterruptibly();
      
          if (writeFuture.getException() != null) {
              session.getConfig().setUseReadOperation(false);
              return false;
          }
      
          // retrieve the login response
          final ReadFuture readFuture = session.read();
          readFuture.awaitUninterruptibly();
      
          if (readFuture.getException() != null) {
              session.getConfig().setUseReadOperation(false);
              return false;
          }
      
          // stop blocking inbound messages
          session.getConfig().setUseReadOperation(false);
      
          // determine if the login info provided was valid
          final LoginResponse loginResponse = (LoginResponse)readFuture.getMessage();
          return loginResponse.getSuccess();
      }
      

      I can see on the server side that the LoginRequest object is retrieved, and a LoginResponse message is sent. On the client side, the DemuxingProtocolCodecFactory receives the response, but after throwing in some logging, I can see that the client gets stuck on the call to `readFuture.awaitUninterruptibly() `.

      I can't for the life of me figure out why it is stuck here based upon my own code. I properly set the read operation to true on the session config, meaning that messages should be blocked. However, it seems as if the message no longer exists by time I try to read response messages synchronously.

        Activity

        Hide
        elecharny Emmanuel Lecharny added a comment -

        Jeff added a unit test proving that the method works correctly. Closing the issue.

        Show
        elecharny Emmanuel Lecharny added a comment - Jeff added a unit test proving that the method works correctly. Closing the issue.
        Hide
        jeffmaury Jeff MAURY added a comment -

        I added a JUnit test to validate the readFuture and it is working correctly (at least on a small message). Can you check if the codec is not the cause.
        For the Junit test, see https://github.com/apache/mina/blob/2.0/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DIRMINA777Test.java

        Show
        jeffmaury Jeff MAURY added a comment - I added a JUnit test to validate the readFuture and it is working correctly (at least on a small message). Can you check if the codec is not the cause. For the Junit test, see https://github.com/apache/mina/blob/2.0/mina-core/src/test/java/org/apache/mina/transport/socket/nio/DIRMINA777Test.java
        Hide
        elecharny Emmanuel Lecharny added a comment -

        Not sure the readFuture mechanism is working at all. first, we create the ReadFuture queue on the fly, with no synchonization :

            private ReadFuture newReadFuture() {
                Queue<ReadFuture> readyReadFutures = getReadyReadFutures();
                ...
        
            private Queue<ReadFuture> getReadyReadFutures() {
                Queue<ReadFuture> readyReadFutures = (Queue<ReadFuture>) getAttribute(READY_READ_FUTURES_KEY);
                if (readyReadFutures == null) {
                    readyReadFutures = new ConcurrentLinkedQueue<ReadFuture>();
        
                    Queue<ReadFuture> oldReadyReadFutures = (Queue<ReadFuture>) setAttributeIfAbsent(READY_READ_FUTURES_KEY,
                            readyReadFutures);
                    if (oldReadyReadFutures != null) {
                        readyReadFutures = oldReadyReadFutures;
                    }
                }
                return readyReadFutures;
            }
        

        and second, I don't even see what it could be used for. We generate ReadFuture containing either the received message, or an exception or a close event. All those elements will be received by the Handler anyway.

        I think it puts a lot of burden on the shoulder of an implementer for a little benefit.

        At the very minimum, I would suggest we rethink the whole mechanism in MINA 3, and avoid trying to fix that in MINA 2.

        Show
        elecharny Emmanuel Lecharny added a comment - Not sure the readFuture mechanism is working at all. first, we create the ReadFuture queue on the fly, with no synchonization : private ReadFuture newReadFuture() { Queue<ReadFuture> readyReadFutures = getReadyReadFutures(); ... private Queue<ReadFuture> getReadyReadFutures() { Queue<ReadFuture> readyReadFutures = (Queue<ReadFuture>) getAttribute(READY_READ_FUTURES_KEY); if (readyReadFutures == null ) { readyReadFutures = new ConcurrentLinkedQueue<ReadFuture>(); Queue<ReadFuture> oldReadyReadFutures = (Queue<ReadFuture>) setAttributeIfAbsent(READY_READ_FUTURES_KEY, readyReadFutures); if (oldReadyReadFutures != null ) { readyReadFutures = oldReadyReadFutures; } } return readyReadFutures; } and second, I don't even see what it could be used for. We generate ReadFuture containing either the received message, or an exception or a close event. All those elements will be received by the Handler anyway. I think it puts a lot of burden on the shoulder of an implementer for a little benefit. At the very minimum, I would suggest we rethink the whole mechanism in MINA 3, and avoid trying to fix that in MINA 2.
        Hide
        elecharny Emmanuel Lecharny added a comment -

        Would it be possible to have a small sample that expose the issue, so that I can trace what's going on in the MINA code ?

        Thanks !

        Show
        elecharny Emmanuel Lecharny added a comment - Would it be possible to have a small sample that expose the issue, so that I can trace what's going on in the MINA code ? Thanks !
        Hide
        elecharny Emmanuel Lecharny added a comment -

        Please, do not add comments in a foreign language... (even if those are related to the problem, google translate is not that good in chinese...)

        Show
        elecharny Emmanuel Lecharny added a comment - Please, do not add comments in a foreign language... (even if those are related to the problem, google translate is not that good in chinese...)
        Hide
        elecharny Emmanuel Lecharny added a comment -

        I'm pretty sure it's more a problem with the place where the flag is set. It should be set before writing any data in the session, otherwise you might have a race condition where the message is received before the flag can be set.

        Can you test the same code with the flag set before the write ?

        Show
        elecharny Emmanuel Lecharny added a comment - I'm pretty sure it's more a problem with the place where the flag is set. It should be set before writing any data in the session, otherwise you might have a race condition where the message is received before the flag can be set. Can you test the same code with the flag set before the write ?
        Hide
        scholers liqingfeng added a comment -

        But ,i use other client.This bug is not Fixed.
        you can use an PC device to test the issue;
        i use one server to set the read operation to true ( session.getConfig().setUseReadOperation(false); ) , one pc is server A,one pc is server B,
        A send message to B,this issue show, i can't try to read response messages synchronously.

        Show
        scholers liqingfeng added a comment - But ,i use other client.This bug is not Fixed. you can use an PC device to test the issue; i use one server to set the read operation to true ( session.getConfig().setUseReadOperation(false); ) , one pc is server A,one pc is server B, A send message to B,this issue show, i can't try to read response messages synchronously.
        Hide
        elecharny Emmanuel Lecharny added a comment -

        It will be closed if we consider that it's a real issue, or if we consider this is not. Still to be evaluated, as I don't have an Android device to test the issue, and as I don't have the full code of the client and server to reproduce it.

        Show
        elecharny Emmanuel Lecharny added a comment - It will be closed if we consider that it's a real issue, or if we consider this is not. Still to be evaluated, as I don't have an Android device to test the issue, and as I don't have the full code of the client and server to reproduce it.
        Hide
        scholers liqingfeng added a comment -

        when it is colosed?

        Show
        scholers liqingfeng added a comment - when it is colosed?
        Hide
        elecharny Emmanuel Lecharny added a comment -

        Postponed to 2.0.1

        Show
        elecharny Emmanuel Lecharny added a comment - Postponed to 2.0.1

          People

          • Assignee:
            Unassigned
            Reporter:
            mhuggins Matt Huggins
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development