bool CarbonRouterInstance::reconfigurePartially()

in mcrouter/CarbonRouterInstance-inl.h [508:592]


bool CarbonRouterInstance<RouterInfo>::reconfigurePartially() {
  auto partialUpdates = configApi_->releasePartialUpdatesLocked();
  VLOG(2) << "receive partial updates:" << partialUpdates.size();
  if (partialUpdates.empty()) {
    return false;
  }
  partialReconfigAttempt_.store(
      partialReconfigAttempt_.load(std::memory_order_relaxed) +
          partialUpdates.size(),
      std::memory_order_relaxed);

  // Use the first proxy's config, as it's same in all proxies.
  // Also there is no contention for holding the read lock as write lock is
  // only obtained by proxy_config_swap() from config thread (same thread
  // invoking this function)
  {
    auto proxyConfig = getProxy(0)->getConfigLocked();
    // Make sure partial config is allow for all updates
    for (const auto& update : partialUpdates) {
      if (!proxyConfig.second.allowPartialConfig(update.tierName)) {
        VLOG(1) << folly::sformat(
            "tier {} not allow partial reconfigure", update.tierName);
        return false;
      }
    }
  }

  auto& partialConfigs = getProxy(0)->getConfigUnsafe()->getPartialConfigs();
  for (size_t i = 0; i < opts_.num_proxies; i++) {
    for (const auto& update : partialUpdates) {
      auto& tierPartialConfigs = partialConfigs.at(update.tierName).second;
      if (i == 0) {
        VLOG(1) << folly::sformat(
            "partial update: tier={}, oldApString={}, newApString={}, oldFailureDomain={}, newFailureDomain={}",
            update.tierName,
            update.oldApString,
            update.newApString,
            update.oldFailureDomain,
            update.newFailureDomain);
      }
      for (const auto& [apAttr, poolList] : tierPartialConfigs) {
        auto oldAp = createAccessPoint(
            update.oldApString, update.oldFailureDomain, *this, *apAttr);
        auto newAp =
            std::const_pointer_cast<const AccessPoint>(createAccessPoint(
                update.newApString, update.newFailureDomain, *this, *apAttr));
        if (UNLIKELY(oldAp->getProtocol() != newAp->getProtocol())) {
          return false;
        }
        auto replacedAp = getProxy(i)->replaceAP(*oldAp, newAp);
        if (!replacedAp) {
          VLOG(2) << folly::sformat(
              "could not replace AP for tier={}, proxy={}, protocol={}",
              update.tierName,
              i,
              mc_protocol_to_string(oldAp->getProtocol()));
          return false;
        }
        auto proxyConfig = getProxy(i)->getConfigLocked();
        for (const auto& pool : poolList) {
          if (!proxyConfig.second.updateAccessPoints(pool, replacedAp, newAp)) {
            VLOG(2) << folly::sformat(
                "could not update AccessPoints for tier={}, pool={}, proxy={}, protocol={}",
                update.tierName,
                pool,
                i,
                mc_protocol_to_string(oldAp->getProtocol()));
            return false;
          }
        }
      }
    }
  }
  int numUpdates = partialUpdates.size();
  if (!configApi_->updatePartialConfigSource(std::move(partialUpdates))) {
    return false;
  }

  VLOG_IF(1, !opts_.constantly_reload_configs)
      << "Partially reconfigured " << opts_.num_proxies << " proxies";
  partialReconfigSuccess_.store(
      partialReconfigSuccess_.load(std::memory_order_relaxed) + numUpdates,
      std::memory_order_relaxed);
  return true;
}