/** * Called to signal async read isReady() has returned false. This indicates that there is no * content available to be consumed and that once the channel enteres the ASYNC_WAIT state it will * register for read interest by calling {@link HttpChannel#asyncReadFillInterested()} either from * this method or from a subsequent call to {@link #unhandle()}. */ public void onReadUnready() { boolean interested = false; try (Locker.Lock lock = _locker.lock()) { if (DEBUG) LOG.debug("onReadUnready {}", toStringLocked()); // We were already unready, this is not a state change, so do nothing if (!_asyncReadUnready) { _asyncReadUnready = true; _asyncReadPossible = false; // Assumes this has been checked in isReady() with lock held if (_state == State.ASYNC_WAIT) interested = true; } } if (interested) _channel.asyncReadFillInterested(); }
/** * Signal that the HttpConnection has finished handling the request. For blocking connectors,this * call may block if the request has been suspended (startAsync called). * * @return next actions be handled again (eg because of a resume that happened before unhandle was * called) */ protected Action unhandle() { Action action; AsyncContextEvent schedule_event = null; boolean read_interested = false; try (Locker.Lock lock = _locker.lock()) { if (DEBUG) LOG.debug("unhandle {}", toStringLocked()); switch (_state) { case COMPLETING: case COMPLETED: return Action.TERMINATED; case THROWN: _state = State.DISPATCHED; return Action.ERROR_DISPATCH; case DISPATCHED: case ASYNC_IO: break; default: throw new IllegalStateException(this.getStatusStringLocked()); } if (_async != null) { _initial = false; switch (_async) { case COMPLETE: _state = State.COMPLETING; _async = null; action = Action.COMPLETE; break; case DISPATCH: _state = State.DISPATCHED; _async = null; action = Action.ASYNC_DISPATCH; break; case STARTED: if (_asyncReadUnready && _asyncReadPossible) { _state = State.ASYNC_IO; _asyncReadUnready = false; action = Action.READ_CALLBACK; } else if (_asyncWrite) // TODO refactor same as read { _asyncWrite = false; _state = State.ASYNC_IO; action = Action.WRITE_CALLBACK; } else { schedule_event = _event; read_interested = _asyncReadUnready; _state = State.ASYNC_WAIT; action = Action.WAIT; } break; case EXPIRING: // onTimeout callbacks still being called, so just WAIT _state = State.ASYNC_WAIT; action = Action.WAIT; break; case EXPIRED: // onTimeout handling is complete, but did not dispatch as // we were handling. So do the error dispatch here _state = State.DISPATCHED; _async = null; action = Action.ERROR_DISPATCH; break; case ERRORED: _state = State.DISPATCHED; _async = null; action = Action.ERROR_DISPATCH; break; default: throw new IllegalStateException(this.getStatusStringLocked()); } } else { _state = State.COMPLETING; action = Action.COMPLETE; } } if (schedule_event != null) scheduleTimeout(schedule_event); if (read_interested) _channel.asyncReadFillInterested(); return action; }