void ConnectionManager::DrainHelper::drainConnections()

in wangle/acceptor/ConnectionManager.cpp [182:232]


void ConnectionManager::DrainHelper::drainConnections() {
  DestructorGuard g(&manager_);
  size_t numCleared = 0;
  size_t numKept = 0;

  auto it = manager_.drainIterator_;

  CHECK(
      shutdownState_ == ShutdownState::NOTIFY_PENDING_SHUTDOWN ||
      shutdownState_ == ShutdownState::CLOSE_WHEN_IDLE);
  while (it != manager_.conns_.end() && (numKept + numCleared) < 64) {
    ManagedConnection& conn = *it++;
    if (shutdownState_ == ShutdownState::NOTIFY_PENDING_SHUTDOWN) {
      conn.fireNotifyPendingShutdown();
      numKept++;
    } else { // CLOSE_WHEN_IDLE
      // Second time around: close idle sessions. If they aren't idle yet,
      // have them close when they are idle
      if (conn.isBusy()) {
        numKept++;
      } else {
        numCleared++;
      }
      conn.fireCloseWhenIdle(!manager_.notifyPendingShutdown_);
    }
  }

  if (shutdownState_ == ShutdownState::CLOSE_WHEN_IDLE) {
    VLOG(2) << "Idle connections cleared: " << numCleared
            << ", busy conns kept: " << numKept;
  } else {
    VLOG(3) << this << " notified n=" << numKept;
  }
  manager_.drainIterator_ = it;
  if (it != manager_.conns_.end()) {
    manager_.eventBase_->runInLoop(this);
  } else {
    if (shutdownState_ == ShutdownState::NOTIFY_PENDING_SHUTDOWN) {
      VLOG(3) << this << " finished notify_pending_shutdown";
      shutdownState_ = ShutdownState::NOTIFY_PENDING_SHUTDOWN_COMPLETE;
      if (!isScheduled()) {
        // The idle grace timer already fired, start over immediately
        shutdownState_ = ShutdownState::CLOSE_WHEN_IDLE;
        manager_.drainIterator_ = drainStartIterator();
        manager_.eventBase_->runInLoop(this);
      }
    } else {
      shutdownState_ = ShutdownState::CLOSE_WHEN_IDLE_COMPLETE;
    }
  }
}