@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; } }
/** * 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(); }
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(); }
@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(); } }
@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; } }
/** * 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); } }); }
@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(); } }