Menu

Async Listener Blocking

2012-07-25
2013-06-13
  • Daniel Fisher

    Daniel Fisher - 2012-07-25

    I noticed that search listeners block the response receive thread and I wasn't sure if this was intended behavior for async operations.

        SearchRequest req = new SearchRequest(
          new CancelListener(),
          "dc=blah,dc=blah",
          SearchScope.SUB,
          DereferencePolicy.NEVER,
          0,
          0,
          false,
          Filter.create("cn=blah"));
        AsyncRequestID id = conn.asyncSearch(req);
        return id.get();
      public class CancelListener implements AsyncSearchResultListener
      {
        public void searchEntryReturned(SearchResultEntry entry)
        {   
          try {
            conn.processExtendedOperation(
              new CancelExtendedRequest(entry.getMessageID()));
          } catch (LDAPException e) {
            e.printStackTrace();
          }
        }
        public void searchReferenceReturned(SearchResultReference ref) {}
        public void searchResultReceived(AsyncRequestID id, SearchResult result) {}
      }
    

    This code will block indefinitely as the search response is waiting on the cancel operation and the cancel operation response is blocking on the search response.
    I'm not certain listeners should support this behavior, but I thought it was worth a post to get some feedback.

     
  • Neil Wilson

    Neil Wilson - 2012-07-25

    I'm not sure I'd go as far as saying that it's the intended behavior, but it is the expected behavior.

    When you're using a connection in its default asynchronous mode, it has one thread dedicated to reading responses from the server.  For operations that don't use a response listener, the reader thread decodes the response and puts it on a queue that is read by the thread which initially requested the operation.  However, for operations that do register a response listener, the reader thread invokes the appropriate method in that listener, which means that during the course of that processing, the reader thread is tied up and won't be looking for responses.

    It really depends on what you want to achieve, but you may need to either invoke the desired secondary operation using the asynchronous API or using a separate thread.  But in either case, you'll need to return from the listener before it can look for additional responses to that operation.

    However, if the example you provided demonstrates what you actually want to do, then there are two options you may want to consider:

    - Set a size limit of one for the search operation.  That will cause the server to return at most one entry for the search so that there's no reason to cancel the operation after receiving an entry.  If there are still more results that match the filter, then the server will return a "size limit exceeded" result.

    - Send an abandon request rather than a cancel (using the LDAPConnection.abandon method).  An abandon request doesn't have a response, so the abandon request won't wait for one.

    Also note that in either the case of either the cancel extended request or the abandon request, there's no guarantee that the server will receive that request before sending more entries, so your listener still has the potential for dealing with multiple entries for the same search (and in your case, sending multiple cancel/abandon requests for the same search).

    Neil

     

Log in to post a comment.