McrouterRouteHandlePtr makeFailoverWithExptimeRoute(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json) {
  checkLogic(json.isObject(), "FailoverWithExptimeRoute is not an object");
  auto jnormal = json.get_ptr("normal");
  checkLogic(jnormal, "FailoverWithExptimeRoute: normal not found");
  auto normal = factory.create(*jnormal);

  int32_t failoverExptime = 60;
  if (auto jexptime = json.get_ptr("failover_exptime")) {
    checkLogic(jexptime->isInt(), "FailoverWithExptimeRoute: "
                                  "failover_exptime is not an integer");
    failoverExptime = jexptime->getInt();
  }

  std::vector<McrouterRouteHandlePtr> failover;
  if (auto jfailover = json.get_ptr("failover")) {
    failover = factory.createList(*jfailover);
  }

  auto children = getFailoverChildren(std::move(normal),
                                      std::move(failover),
                                      failoverExptime);
  return makeFailoverRoute(json, std::move(children));
}
FailoverWithExptimeRoute::FailoverWithExptimeRoute(
  RouteHandleFactory<McrouterRouteHandleIf>& factory,
  const folly::dynamic& json)
    : failoverExptime_(60) {

  checkLogic(json.isObject(), "FailoverWithExptimeRoute is not object");

  std::vector<McrouterRouteHandlePtr> failoverTargets;

  if (json.count("failover")) {
    failoverTargets = factory.createList(json["failover"]);
  }

  failover_ = FailoverRoute<McrouterRouteHandleIf>(std::move(failoverTargets));

  if (json.count("normal")) {
    normal_ = factory.create(json["normal"]);
  }

  if (json.count("failover_exptime")) {
    checkLogic(json["failover_exptime"].isInt(),
               "failover_exptime is not integer");
    failoverExptime_ = json["failover_exptime"].asInt();
  }

  if (json.count("settings")) {
    settings_ = FailoverWithExptimeSettings(json["settings"]);
  }
}
McrouterRouteHandlePtr makeFailoverWithExptimeRoute(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json) {
  checkLogic(json.isObject(), "FailoverWithExptimeRoute is not an object");

  McrouterRouteHandlePtr normal;
  if (auto jnormal = json.get_ptr("normal")) {
    normal = factory.create(*jnormal);
  }

  std::vector<McrouterRouteHandlePtr> failoverTargets;
  if (auto jfailover = json.get_ptr("failover")) {
    failoverTargets = factory.createList(*jfailover);
  }

  int32_t failoverExptime = 60;
  if (auto jexptime = json.get_ptr("failover_exptime")) {
    checkLogic(jexptime->isInt(), "FailoverWithExptimeRoute: "
                                  "failover_exptime is not an integer");
    failoverExptime = jexptime->getInt();
  }

  // Check if only one format is being used
  checkLogic(!(json.count("settings") && // old
        (json.count("failover_errors") || json.count("failover_tag"))), // new
      "Use either 'settings' (old format) or 'failover_errors' / 'failover_tag'"
    );

  // new format
  FailoverErrorsSettings failoverErrors;
  bool failoverTagging = false;
  if (auto jfailoverTag = json.get_ptr("failover_tag")) {
    checkLogic(jfailoverTag->isBool(),
               "FailoverWithExptime: failover_tag is not bool");
    failoverTagging = jfailoverTag->getBool();
  }
  if (auto jfailoverErrors = json.get_ptr("failover_errors")) {
    failoverErrors = FailoverErrorsSettings(*jfailoverErrors);
  }

  // old format
  if (auto jsettings = json.get_ptr("settings")) {
    VLOG(1) << "FailoverWithExptime: This config format is deprecated. "
               "Use 'failover_errors' instead of 'settings'.";
    auto oldSettings = FailoverWithExptimeSettings(*jsettings);
    failoverTagging = oldSettings.failoverTagging;
    failoverErrors = oldSettings.getFailoverErrors();
  }

  return makeFailoverWithExptimeRoute(
    std::move(normal),
    std::move(failoverTargets),
    failoverExptime,
    std::move(failoverErrors),
    failoverTagging);
}
Beispiel #4
0
McrouterRouteHandlePtr makeLatestRoute(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json) {
  std::vector<McrouterRouteHandlePtr> children;
  if (json.isObject()) {
    if (auto jchildren = json.get_ptr("children")) {
      children = factory.createList(*jchildren);
    }
  } else {
    children = factory.createList(json);
  }
  return makeLatestRoute(json, std::move(children));
}
McrouterRouteHandlePtr makeRateLimitRoute(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json) {
  checkLogic(json.isObject(), "RateLimitRoute is not an object");
  auto jtarget = json.get_ptr("target");
  checkLogic(jtarget, "RateLimitRoute: target not found");
  auto target = factory.create(*jtarget);
  auto jrates = json.get_ptr("rates");
  checkLogic(jrates, "RateLimitRoute: rates not found");
  return makeRateLimitRoute(std::move(target), RateLimiter(*jrates));
}
/**
 * @return target and asynclogName
 *         Caller may call makeAsynclogRoute afterwards.
 */
std::pair<McrouterRouteHandlePtr, std::string> parseAsynclogRoute(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json) {
  std::string asynclogName;
  McrouterRouteHandlePtr target;
  checkLogic(json.isObject() || json.isString(),
             "AsynclogRoute should be object or string");
  if (json.isString()) {
    asynclogName = json.stringPiece().str();
    target = factory.create(json);
  } else { // object
    auto jname = json.get_ptr("name");
    checkLogic(jname && jname->isString(),
               "AsynclogRoute: required string name");
    auto jtarget = json.get_ptr("target");
    checkLogic(jtarget, "AsynclogRoute: target not found");
    asynclogName = jname->stringPiece().str();
    target = factory.create(*jtarget);
  }
  return { std::move(target), std::move(asynclogName) };
}
McrouterRouteHandlePtr makeOperationSelectorRoute(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json) {
  if (!json.isObject()) {
    return factory.create(json);
  }

  McrouterRouteHandlePtr defaultPolicy;
  if (json.count("default_policy")) {
    defaultPolicy = factory.create(json["default_policy"]);
  }

  std::vector<McrouterRouteHandlePtr> operationPolicies{mc_nops};
  if (auto jOpPolicies = json.get_ptr("operation_policies")) {
    checkLogic(jOpPolicies->isObject(),
               "OperationSelectorRoute: operation_policies is not an object");

    std::map<std::string, const folly::dynamic*> orderedPolicies;
    for (auto& it : jOpPolicies->items()) {
      checkLogic(it.first.isString(),
                 "OperationSelectorRoute: operation_policies' "
                 "key is not a string");
      auto key = it.first.stringPiece().str();
      orderedPolicies.emplace(std::move(key), &it.second);
    }

    // order is important here: named handles may not be resolved if we parse
    // policies in random order
    for (const auto& it : orderedPolicies) {
      auto opId = mc_op_from_string(it.first.data());
      checkLogic(opId != mc_op_unknown, "Unknown mc operation: {}", it.first);
      operationPolicies[opId] = factory.create(*it.second);
    }

    return makeOperationSelectorRoute(std::move(operationPolicies),
                                      std::move(defaultPolicy));
  }

  return defaultPolicy;
}
Beispiel #8
0
std::vector<McrouterRouteHandlePtr> makeShadowRoutes(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json,
    proxy_t& proxy,
    ExtraRouteHandleProviderIf& extraProvider) {
  checkLogic(json.isObject(), "ShadowRoute should be an object");
  const auto jchildren = json.get_ptr("children");
  checkLogic(jchildren, "ShadowRoute: children not found");
  auto children = factory.createList(*jchildren);
  if (json.count("shadows")) {
    children = makeShadowRoutes(
        factory, json, std::move(children), proxy, extraProvider);
  }
  return children;
}
OperationSelectorRoute::OperationSelectorRoute(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json) {
  if (!json.isObject()) {
    defaultPolicy_ = factory.create(json);
    return;
  }

  if (json.count("default_policy")) {
    defaultPolicy_ = factory.create(json["default_policy"]);
  }

  operationPolicies_.resize(mc_nops);
  if (json.count("operation_policies")) {
    const auto& policies = json["operation_policies"];
    checkLogic(policies.isObject(),
               "OperationSelectorRoute: operation_policies is not object");

    std::map<std::string, folly::dynamic> orderedPolicies;
    for (const auto& it : policies.items()) {
      checkLogic(it.first.isString(),
                 "OperationSelectorRoute: operation_policies "
                 "key is not a string");
      auto key = it.first.asString().toStdString();
      orderedPolicies.insert({ key, it.second });
    }

    // order is important here: named handles may not be resolved if we parse
    // policies in random order
    for (const auto& it : orderedPolicies) {
      auto opId = mc_op_from_string(it.first.data());
      checkLogic(opId != mc_op_unknown, "Unknown mc operation: {}", it.first);
      operationPolicies_[opId] = factory.create(it.second);
    }
  }
}
Beispiel #10
0
std::vector<McrouterRouteHandlePtr> makeShadowRoutes(
    RouteHandleFactory<McrouterRouteHandleIf>& factory,
    const folly::dynamic& json,
    std::vector<McrouterRouteHandlePtr> children,
    proxy_t& proxy,
    ExtraRouteHandleProviderIf& extraProvider) {
  folly::StringPiece shadowPolicy = "default";
  if (auto jshadow_policy = json.get_ptr("shadow_policy")) {
    checkLogic(jshadow_policy->isString(),
               "ShadowRoute: shadow_policy is not a string");
    shadowPolicy = jshadow_policy->stringPiece();
  }

  auto jshadows = json.get_ptr("shadows");
  checkLogic(jshadows, "ShadowRoute: route doesn't contain shadows field");

  if (!jshadows->isArray()) {
    MC_LOG_FAILURE(proxy.router().opts(),
                   failure::Category::kInvalidConfig,
                   "ShadowRoute: shadows specified in route is not an array");
    return children;
  }

  McrouterShadowData data;
  for (auto& shadow : *jshadows) {
    if (!shadow.isObject()) {
      MC_LOG_FAILURE(proxy.router().opts(),
                     failure::Category::kInvalidConfig,
                     "ShadowRoute: shadow is not an object");
      continue;
    }
    auto jtarget = shadow.get_ptr("target");
    if (!jtarget) {
      MC_LOG_FAILURE(proxy.router().opts(),
                     failure::Category::kInvalidConfig,
                     "ShadowRoute shadows: no target for shadow");
      continue;
    }
    try {
      auto s = ShadowSettings::create(shadow, proxy.router());
      if (s) {
        data.emplace_back(factory.create(*jtarget), std::move(s));
      }
    } catch (const std::exception& e) {
      MC_LOG_FAILURE(proxy.router().opts(),
                     failure::Category::kInvalidConfig,
                     "Can not create shadow for ShadowRoute: {}",
                     e.what());
    }
  }
  for (size_t i = 0; i < children.size(); ++i) {
    McrouterShadowData childrenShadows;
    for (const auto& shadowData : data) {
      if (shadowData.second->startIndex() <= i &&
          i < shadowData.second->endIndex()) {
        childrenShadows.push_back(shadowData);
      }
    }
    if (!childrenShadows.empty()) {
      childrenShadows.shrink_to_fit();
      children[i] = extraProvider.makeShadow(proxy,
                                                  std::move(children[i]),
                                                  std::move(childrenShadows),
                                                  shadowPolicy);
    }
  }
  return children;
}