docs: public synchronized JsMessage get(short sessionId)
        throws SIResourceException, SIConnectionDroppedException, SIConnectionLostException
     {
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.entry(this, tc, "get", sessionId);
  
        JsMessage retValue = null;
  
        QueueData rhData = removeLastIfAvailable(sessionId);
        while (rhData != null) 
        {
                   
           retValue = (JsMessage) rhData.getMessage();
  
           // Now we need to decide whether the message has expired or not. We do this by comparing
           // the message arrival time + message TTL and the current time. If we find the message
           // has expired we need to unlock it at the server, and discard it from our queue without
           // giving it to the caller.
           // NOTE: We want to avoid the situation where we unlock an expired message but it gets to
           // the server at the exact time it did expire. As such, we give each message an extra
           // 500ms to live. This way we absolutely guarentee that when we unlock on the server the
           // message will not be redelivered.
           boolean messageHasExpired = false;
           long msgTTL = retValue.getRemainingTimeToLive();
  
           if (msgTTL != -1)
           {
              long currentTime = approxTimeThread.getApproxTime();
              long msgArrivalTime = rhData.getArrivalTime();
  
              // Compensate the TTL by 500 ms
              msgTTL += 500;
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Arrived: " + new Date(msgArrivalTime) +
                                                       ", Now: " + new Date(currentTime) +
                                                       ", Expires: " + new Date(msgArrivalTime + msgTTL));
  
              if (currentTime > (msgArrivalTime + msgTTL))
              {
                 if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Message has expired: " +
                                                      retValue.getMessageHandle());
                 messageHasExpired = true;
              }
           }
  
           // Now we need to update our counters and decide whether we request more messages.
           // We do this whether the message will expire or not - as either way the message is
           // coming of the queue.
           if (trackBytes)
           {
              bytesGivenToUserSinceLastRequestForMsgs += rhData.getMessageLength();
           }
  
           totalBytesGiven += bytesGivenToUserSinceLastRequestForMsgs;
           currentBytesOnQueue -= rhData.getMessageLength();
  
           if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled())
           {
              SibTr.debug(this, tc, "Current bytes on the queue", ""+currentBytesOnQueue);
              SibTr.debug(this, tc, "Bytes given since last request", ""+bytesGivenToUserSinceLastRequestForMsgs);
           }
  
           // Now check and see if we need more messags. If we have gone below the lower watermark
           // of bytes cached by us (rather - if we have given the user more than HIGH - LOW messages),
           // and if the server has stopped sending us messages (coz we have received more than the
           // high watermark) then request some more messages.
           if (trackBytes &&
               (bytesGivenToUserSinceLastRequestForMsgs >= (HIGH_QUEUE_BYTES - LOW_QUEUE_BYTES)))
           {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Need more messages: " +
                                                   bytesGivenToUserSinceLastRequestForMsgs + " >= " + (HIGH_QUEUE_BYTES - LOW_QUEUE_BYTES));
  
              // Are there new values waiting to be set? If so, set them now
              if (NEW_HIGH_QUEUE_BYTES != 0)
              {
                 HIGH_QUEUE_BYTES = NEW_HIGH_QUEUE_BYTES;
                 LOW_QUEUE_BYTES = NEW_LOW_QUEUE_BYTES;
              }
  
              convHelper.requestMoreMessages(bytesReceivedSinceLastRequestForMsgs, HIGH_QUEUE_BYTES);   // d172528
              bytesGivenToUserSinceLastRequestForMsgs = 0;
              bytesReceivedSinceLastRequestForMsgs = 0;
              totalRequests++;
  
              lastRequestForMessagesTime = System.currentTimeMillis();
  
  
              synchronized(queue)
              {
           	   if (queue.isEmpty()) goneEmptyCount++;
              }
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(this, tc, "Queue is now: ", this);
           }
  
           // If the message has not expired, break out of this loop and deliver the message
           if (!messageHasExpired)
           {
              break;
           }
  
           // Otherwise, unlock him if he was a recoverable message
           if (CommsUtils.isRecoverable(retValue, unrecoverableReliability))
           {
              try
              {
                 convHelper.unlockSet(new SIMessageHandle[] {retValue.getMessageHandle()});
              }
              catch (SIException e)
              {
                 FFDCFilter.processException(e, CLASS_NAME + ".get",
                                             CommsConstants.RHPQ_GET_01, this);
  
                 if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) SibTr.debug(tc, "Unable to unlock expired message", e);
  
                 // Not a lot else we can do that
              }
           }
  
           // And null out the message so we don't accidentally return him
           retValue = null;
           rhData = removeLastIfAvailable(sessionId);
        }
  
        if (TraceComponent.isAnyTracingEnabled() && tc.isEntryEnabled()) SibTr.exit(tc, "get", retValue);
        return retValue;
     }