示例#1
0
  @Override
  public void flush() throws IOException {
    while (true) {
      switch (_state.get()) {
        case OPEN:
          if (BufferUtil.hasContent(_aggregate)) _channel.write(_aggregate, false);
          else _channel.write(BufferUtil.EMPTY_BUFFER, false);
          return;

        case ASYNC:
          throw new IllegalStateException("isReady() not called");

        case READY:
          if (!_state.compareAndSet(State.READY, State.PENDING)) continue;
          new AsyncFlush().process();
          return;

        case PENDING:
        case UNREADY:
          throw new WritePendingException();

        case CLOSED:
          return;
      }
      break;
    }
  }
示例#2
0
 /**
  * Blocking send of content.
  *
  * @param content The content to send.
  * @throws IOException
  */
 public void sendContent(ByteBuffer content) throws IOException {
   final BlockingCallback callback = _channel.getWriteBlockingCallback();
   if (content.hasArray() && content.limit() < content.capacity())
     content = content.asReadOnlyBuffer();
   _channel.write(content, true, callback);
   callback.block();
 }
示例#3
0
  public void write(ByteBuffer buffer) throws IOException {
    _written += buffer.remaining();
    boolean complete = _channel.getResponse().isAllContentWritten(_written);

    // Async or Blocking ?
    while (true) {
      switch (_state.get()) {
        case OPEN:
          // process blocking below
          break;

        case ASYNC:
          throw new IllegalStateException("isReady() not called");

        case READY:
          if (!_state.compareAndSet(State.READY, State.PENDING)) continue;

          // Do the asynchronous writing from the callback
          new AsyncWrite(buffer, complete).process();
          return;

        case PENDING:
        case UNREADY:
          throw new WritePendingException();

        case CLOSED:
          throw new EofException("Closed");
      }
      break;
    }

    // handle blocking write
    int len = BufferUtil.length(buffer);

    // flush any content from the aggregate
    if (BufferUtil.hasContent(_aggregate)) _channel.write(_aggregate, complete && len == 0);

    // write any remaining content in the buffer directly
    if (len > 0) _channel.write(buffer, complete);
    else if (complete) _channel.write(BufferUtil.EMPTY_BUFFER, complete);

    if (complete) closed();
  }
示例#4
0
 @Override
 public void close() {
   State state = _state.get();
   while (state != State.CLOSED) {
     if (_state.compareAndSet(state, State.CLOSED)) {
       try {
         if (BufferUtil.hasContent(_aggregate))
           _channel.write(_aggregate, !_channel.getResponse().isIncluding());
         else _channel.write(BufferUtil.EMPTY_BUFFER, !_channel.getResponse().isIncluding());
       } catch (IOException e) {
         LOG.debug(e);
         _channel.failed();
       }
       releaseBuffer();
       return;
     }
     state = _state.get();
   }
 }
示例#5
0
  @Override
  public void write(int b) throws IOException {
    _written += 1;
    boolean complete = _channel.getResponse().isAllContentWritten(_written);

    // Async or Blocking ?
    while (true) {
      switch (_state.get()) {
        case OPEN:
          if (_aggregate == null)
            _aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), false);
          BufferUtil.append(_aggregate, (byte) b);

          // Check if all written or full
          if (complete || BufferUtil.isFull(_aggregate)) {
            BlockingCallback callback = _channel.getWriteBlockingCallback();
            _channel.write(_aggregate, complete, callback);
            callback.block();
            if (complete) closed();
          }
          break;

        case ASYNC:
          throw new IllegalStateException("isReady() not called");

        case READY:
          if (!_state.compareAndSet(State.READY, State.PENDING)) continue;

          if (_aggregate == null)
            _aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), false);
          BufferUtil.append(_aggregate, (byte) b);

          // Check if all written or full
          if (!complete && !BufferUtil.isFull(_aggregate)) {
            if (!_state.compareAndSet(State.PENDING, State.ASYNC))
              throw new IllegalStateException();
            return;
          }

          // Do the asynchronous writing from the callback
          new AsyncFlush().process();
          return;

        case PENDING:
        case UNREADY:
          throw new WritePendingException();

        case CLOSED:
          throw new EofException("Closed");
      }
      break;
    }
  }
示例#6
0
  /**
   * Asynchronous send of content.
   *
   * @param content The content to send
   * @param callback The callback to use to notify success or failure
   */
  public void sendContent(ByteBuffer content, final Callback callback) {
    if (content.hasArray() && content.limit() < content.capacity())
      content = content.asReadOnlyBuffer();
    _channel.write(
        content,
        true,
        new Callback() {
          @Override
          public void succeeded() {
            closed();
            callback.succeeded();
          }

          @Override
          public void failed(Throwable x) {
            callback.failed(x);
          }
        });
  }
示例#7
0
  @Override
  public void write(byte[] b, int off, int len) throws IOException {
    _written += len;
    boolean complete = _channel.getResponse().isAllContentWritten(_written);

    // Async or Blocking ?
    while (true) {
      switch (_state.get()) {
        case OPEN:
          // process blocking below
          break;

        case ASYNC:
          throw new IllegalStateException("isReady() not called");

        case READY:
          if (!_state.compareAndSet(State.READY, State.PENDING)) continue;

          // Should we aggregate?
          int capacity = getBufferSize();
          if (!complete && len <= _commitSize) {
            if (_aggregate == null)
              _aggregate = _channel.getByteBufferPool().acquire(capacity, false);

            // YES - fill the aggregate with content from the buffer
            int filled = BufferUtil.fill(_aggregate, b, off, len);

            // return if we are not complete, not full and filled all the content
            if (filled == len && !BufferUtil.isFull(_aggregate)) {
              if (!_state.compareAndSet(State.PENDING, State.ASYNC))
                throw new IllegalStateException();
              return;
            }

            // adjust offset/length
            off += filled;
            len -= filled;
          }

          // Do the asynchronous writing from the callback
          new AsyncWrite(b, off, len, complete).process();
          return;

        case PENDING:
        case UNREADY:
          throw new WritePendingException();

        case CLOSED:
          throw new EofException("Closed");
      }
      break;
    }

    // handle blocking write

    // Should we aggregate?
    int capacity = getBufferSize();
    if (!complete && len <= _commitSize) {
      if (_aggregate == null) _aggregate = _channel.getByteBufferPool().acquire(capacity, false);

      // YES - fill the aggregate with content from the buffer
      int filled = BufferUtil.fill(_aggregate, b, off, len);

      // return if we are not complete, not full and filled all the content
      if (filled == len && !BufferUtil.isFull(_aggregate)) return;

      // adjust offset/length
      off += filled;
      len -= filled;
    }

    // flush any content from the aggregate
    if (BufferUtil.hasContent(_aggregate)) {
      _channel.write(_aggregate, complete && len == 0);

      // should we fill aggregate again from the buffer?
      if (len > 0 && !complete && len <= _commitSize) {
        BufferUtil.append(_aggregate, b, off, len);
        return;
      }
    }

    // write any remaining content in the buffer directly
    if (len > 0)
      // pass as readonly to avoid space stealing optimisation in HttpConnection
      _channel.write(ByteBuffer.wrap(b, off, len).asReadOnlyBuffer(), complete);
    else if (complete) _channel.write(BufferUtil.EMPTY_BUFFER, complete);

    if (complete) {
      closed();
    }
  }