HTTPSession::onWriteSuccess(uint64_t bytesWritten) {
  DestructorGuard dg(this);
  bytesWritten_ += bytesWritten;
  transportInfo_.totalBytes += bytesWritten;
  CHECK(writeTimeout_.isScheduled());
  if (pendingWrites_.empty()) {
    VLOG(10) << "Cancel write timer on last successful write";
    writeTimeout_.cancelTimeout();
  } else {
    VLOG(10) << "Refresh write timer on writeSuccess";
    timeout_.scheduleTimeout(&writeTimeout_);
  }

  if (infoCallback_) {
    infoCallback_->onWrite(*this, bytesWritten);
  }

  VLOG(5) << "total bytesWritten_: " << bytesWritten_;

  // processByteEvents will return true if it has been replaced with another
  // tracker in the middle and needs to be re-run.  Should happen at most
  // once.  while with no body is intentional
  while (byteEventTracker_ &&
         byteEventTracker_->processByteEvents(
           byteEventTracker_, bytesWritten_)) {} // pass

  if ((!codec_->isReusable() || readsShutdown()) && (transactions_.empty())) {
    if (!codec_->isReusable()) {
      // Shouldn't happen unless there is a bug. This can only happen when
      // someone calls shutdownTransport, but did not specify a reason before.
      setCloseReason(ConnectionCloseReason::UNKNOWN);
    }
    VLOG(4) << *this << " shutdown from onWriteSuccess";
    shutdownTransport(true, true);
  }
  numActiveWrites_--;
  if (!inLoopCallback_) {
    updateWriteCount();
    // safe to resume here:
    updateWriteBufSize(-folly::to<int64_t>(bytesWritten));
    // PRIO_FIXME: this is done because of the corking business...
    //             in the future we may want to have a pull model
    //             whereby the socket asks us for a given amount of
    //             data to send...
    if (numActiveWrites_ == 0 && hasMoreWrites()) {
      runLoopCallback();
    }
  }
  onWriteCompleted();

  if (egressBytesLimit_ > 0 && bytesWritten_ >= egressBytesLimit_) {
    VLOG(4) << "Egress limit reached, shutting down "
      "session (egressed " << bytesWritten_ << ", limit set to "
      << egressBytesLimit_ << ")";
    shutdownTransport(true, true);
  }
}
HTTPSession::onWriteSuccess(uint64_t bytesWritten) {
  DestructorGuard dg(this);
  bytesWritten_ += bytesWritten;
  transportInfo_.totalBytes += bytesWritten;
  CHECK(writeTimeout_.isScheduled());
  if (pendingWrites_.empty()) {
    VLOG(10) << "Cancel write timer on last successful write";
    writeTimeout_.cancelTimeout();
  } else {
    VLOG(10) << "Refresh write timer on writeSuccess";
    timeout_.scheduleTimeout(&writeTimeout_);
  }

  if (infoCallback_) {
    infoCallback_->onWrite(*this, bytesWritten);
  }

  VLOG(5) << "total bytesWritten_: " << bytesWritten_;

   
   
   
  while (byteEventTracker_ &&
         byteEventTracker_->processByteEvents(
           byteEventTracker_, bytesWritten_)) {}  

  if ((!codec_->isReusable() || readsShutdown()) && (transactions_.empty())) {
    if (!codec_->isReusable()) {
       
       
      setCloseReason(ConnectionCloseReason::UNKNOWN);
    }
    VLOG(4) << *this << " shutdown from onWriteSuccess";
    shutdownTransport(true, true);
  }
  numActiveWrites_--;
  if (!inLoopCallback_) {
    updateWriteCount();
     
    updateWriteBufSize(-folly::to<int64_t>(bytesWritten));
     
     
     
     
    if (numActiveWrites_ == 0 && hasMoreWrites()) {
      runLoopCallback();
    }
  }
  onWriteCompleted();

  if (egressBytesLimit_ > 0 && bytesWritten_ >= egressBytesLimit_) {
    VLOG(4) << "Egress limit reached, shutting down "
      "session (egressed " << bytesWritten_ << ", limit set to "
      << egressBytesLimit_ << ")";
    shutdownTransport(true, true);
  }
}