bool KatranLb::modifyRealsForVip()

in katran/lib/KatranLb.cpp [1200:1279]


bool KatranLb::modifyRealsForVip(
    const ModifyAction action,
    const std::vector<NewReal>& reals,
    const VipKey& vip) {
  if (config_.disableForwarding) {
    LOG(ERROR) << "delRealForVip called on non-forwarding instance";
    return false;
  }

  UpdateReal ureal;
  std::vector<UpdateReal> ureals;
  ureal.action = action;

  auto vip_iter = vips_.find(vip);
  if (vip_iter == vips_.end()) {
    LOG(INFO) << folly::sformat(
        "trying to modify reals for non existing vip: {}", vip.address);
    return false;
  }
  auto cur_reals = vip_iter->second.getReals();
  for (const auto& real : reals) {
    if (validateAddress(real.address) == AddressType::INVALID) {
      LOG(ERROR) << "Invalid real's address: " << real.address;
      continue;
    }
    folly::IPAddress raddr(real.address);
    VLOG(4) << folly::format(
        "modifying real: {} with weight {} for vip {}:{}:{}",
        real.address,
        real.weight,
        vip.address,
        vip.port,
        vip.proto);

    if (action == ModifyAction::DEL) {
      auto real_iter = reals_.find(raddr);
      if (real_iter == reals_.end()) {
        LOG(INFO) << "trying to delete non-existing real";
        continue;
      }
      if (std::find(
              cur_reals.begin(), cur_reals.end(), real_iter->second.num) ==
          cur_reals.end()) {
        // this real doesn't belong to this vip
        LOG(INFO) << folly::sformat(
            "trying to delete non-existing real for the VIP: {}", vip.address);
        continue;
      }
      ureal.updatedReal.num = real_iter->second.num;
      decreaseRefCountForReal(raddr);
    } else {
      auto real_iter = reals_.find(raddr);
      if (real_iter != reals_.end()) {
        if (std::find(
                cur_reals.begin(), cur_reals.end(), real_iter->second.num) ==
            cur_reals.end()) {
          // increment ref count if it's a new real for this vip
          increaseRefCountForReal(raddr, real.flags);
          cur_reals.push_back(real_iter->second.num);
        }
        ureal.updatedReal.num = real_iter->second.num;
      } else {
        auto rnum = increaseRefCountForReal(raddr, real.flags);
        if (rnum == config_.maxReals) {
          LOG(INFO) << "exhausted real's space";
          continue;
        }
        ureal.updatedReal.num = rnum;
      }
      ureal.updatedReal.weight = real.weight;
      ureal.updatedReal.hash = raddr.hash();
    }
    ureals.push_back(ureal);
  }

  auto ch_positions = vip_iter->second.batchRealsUpdate(ureals);
  auto vip_num = vip_iter->second.getVipNum();
  programHashRing(ch_positions, vip_num);
  return true;
}