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); }
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; }
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); } } }
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; }