示例#1
0
  /** When an actual data segment was received; deals with request callbacks if necessary */
  private void handleReceivedData(String data) {
    // deal with any queued callbacks first

    QueuedRequest request = null;

    // then check for any requests
    // (should release lock as soon as possible)
    synchronized (_lock) {
      if (_activeRequest != null) {
        request = _activeRequest;
        _activeRequest = null;
      }
    }

    if (request != null && request.timeout > 0) {
      // make sure it hasn't been too long i.e. timeout
      if (request.isExpired()) {
        _logger.debug("Active request has expired");

        // fire the timeout handler
        _callbackHandler.handle(_timeoutCallback, _callbackErrorHandler);
      } else {
        // fire the response request's response handler
        request.setResponse(data);

        _callbackHandler.handle(request.responseHandler, data, _callbackErrorHandler);
      }
    }

    // ...then fire the 'received' callback next
    _callbackHandler.handle(_receivedCallback, data, _callbackErrorHandler);

    processQueue();
  }
示例#2
0
  /** The main thread. */
  private void begin() {
    while (!_shutdown) {
      // only need to set the thread state once here
      _threadStateHandler.handle();

      try {
        connectAndRead();

      } catch (Exception exc) {
        if (_shutdown) {
          // thread can gracefully exit
          return;
        }

        if (_recentlyConnected) _backoffTime = MIN_CONNETION_GAP;
        else {
          _backoffTime = Math.min(_backoffTime * 2, MAX_BACKOFF);
          _backoffTime = Math.max(MIN_CONNETION_GAP, _backoffTime);
        }

        long timeDiff = (System.nanoTime() - _lastSuccessfulConnection) / 1000000;
        if (timeDiff > _timeout) {
          // reset the timestamp
          _lastSuccessfulConnection = System.nanoTime();

          _callbackHandler.handle(_timeoutCallback, _callbackErrorHandler);
        }

        _recentlyConnected = false;
      }

      Threads.wait(_lock, _backoffTime);
    } // (while)
  }
示例#3
0
  /** Expires and initiates requests in the queue (assumes not synced) */
  private void processQueue() {
    // if any new requests are found
    QueuedRequest nextRequest = null;

    // if a timeout callback needs to be fired
    boolean callTimeout = false;

    synchronized (_lock) {
      // check if any active requests need expiring
      if (_activeRequest != null) {
        if (_activeRequest.responseHandler == null || _activeRequest.timeout <= 0) {
          // was a blind request or
          _activeRequest = null;

        } else if (_activeRequest.isExpired()) {
          _logger.debug("Active request has expired");

          // timeout callback must be fired
          callTimeout = true;

          // clear active request
          _activeRequest = null;

        } else if (_activeRequest.isLongTermExpired()) {
          _logger.debug("Active request has long term expired");

          callTimeout = true;

          _activeRequest = null;
        } else {
          // there is still an valid active request,
          // so just get out of here
          return;
        }
      }
    }

    // call the timeout callback, (there's an opportunity for request queue to be cleared by
    // callback handler)
    if (callTimeout) _callbackHandler.handle(_timeoutCallback, _callbackErrorHandler);

    // an active request might have come in
    synchronized (_lock) {
      if (_activeRequest != null) {
        // there's an active request, so leave it to play out
        return;
      }
      // record this for logging
      int longTermDropped = 0;

      try {
        for (; ; ) {
          // no active request, check for queued ones
          nextRequest = _requestQueue.poll();

          if (nextRequest == null) {
            // no more requests either, so nothing more to do
            _logger.debug("No new requests in queue.");

            return;
          }

          _queueLength--;

          if (!nextRequest.isLongTermExpired()) break;

          // otherwise, continue to expire the long term queued
          longTermDropped++;
        }
      } finally {
        if (longTermDropped > 0)
          _logger.debug("(dropped {} long term queued requests.)", longTermDropped);
      }

      // set active request and start timeout *before* sending
      _activeRequest = nextRequest;
      nextRequest.startTimeout();
    }

    // if the request has send data 'data' send now
    if (nextRequest.requestBuffer != null)
      sendBufferNow(nextRequest.requestBuffer, nextRequest.request, false);
  }
示例#4
0
  /** Establishes a socket and continually reads. */
  private void connectAndRead() throws Exception {
    Socket socket = null;
    OutputStream os = null;

    try {
      socket = new Socket();
      InetSocketAddress socketAddress = parseAndResolveDestination(_dest);
      socket.connect(socketAddress, CONNECT_TIMEOUT);

      _counterConnections.incr();

      socket.setSoTimeout(_timeout);

      // 'inject' countable stream
      os = new CountableOutputStream(socket.getOutputStream(), _counterSendOps, _counterSendRate);

      // update flag
      _lastSuccessfulConnection = System.nanoTime();

      synchronized (_lock) {
        if (_shutdown) return;

        _socket = socket;
        _outputStream = os;

        // connection has been successful so reset variables
        // related to exponential back-off

        _recentlyConnected = true;

        _backoffTime = MIN_CONNETION_GAP;
      }

      // fire the connected event
      _callbackHandler.handle(_connectedCallback, _callbackErrorHandler);

      // start reading
      if (_mode == Modes.LengthDelimitedRaw)
        readLengthDelimitedLoop(socket, _binaryStartFlag, _binaryStopFlag);
      else if (_mode == Modes.CharacterDelimitedText) readTextLoop(socket);
      else { // mode is 'UnboundedRaw'
        readUnboundedRawLoop(socket);
      }

      // (any non-timeout exceptions will be propagated to caller...)

    } catch (Exception exc) {
      // fire the disconnected handler if was previously connected
      if (os != null) Handler.tryHandle(_disconnectedCallback, _callbackErrorHandler);

      throw exc;

    } finally {
      // always gracefully close the socket and invalidate the socket fields

      synchronized (_lock) {
        _socket = null;
        _outputStream = null;
      }

      Stream.safeClose(socket);
    }
  }