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)); }
McrouterRouteHandlePtr McRouteHandleProvider::makePoolRoute( McRouteHandleFactory& factory, const folly::dynamic& json) { checkLogic(json.isObject() || json.isString(), "PoolRoute should be object or string"); const folly::dynamic* jpool; if (json.isObject()) { jpool = json.get_ptr("pool"); checkLogic(jpool, "PoolRoute: pool not found"); } else { jpool = &json; } auto p = makePool(*jpool); auto pool = std::move(p.first); auto destinations = std::move(p.second); if (json.isObject()) { if (auto maxOutstandingPtr = json.get_ptr("max_outstanding")) { checkLogic(maxOutstandingPtr->isInt(), "PoolRoute {}: max_outstanding is not int", pool->getName()); auto maxOutstanding = maxOutstandingPtr->asInt(); if (maxOutstanding) { for (auto& destination: destinations) { destination = makeOutstandingLimitRoute(std::move(destination), maxOutstanding); } } } } if (json.isObject() && json.count("shadows")) { folly::StringPiece shadowPolicy = "default"; if (auto jshadow_policy = json.get_ptr("shadow_policy")) { checkLogic(jshadow_policy->isString(), "PoolRoute: shadow_policy is not a string"); shadowPolicy = jshadow_policy->stringPiece(); } McrouterShadowData data; for (auto& shadow : json["shadows"]) { checkLogic(shadow.count("target"), "PoolRoute {} shadows: no target for shadow", pool->getName()); auto s = ShadowSettings::create(shadow, proxy_->router()); if (s) { data.emplace_back(factory.create(shadow["target"]), std::move(s)); } } for (size_t i = 0; i < destinations.size(); ++i) { McrouterShadowData destinationShadows; for (const auto& shadowData : data) { if (shadowData.second->startIndex() <= i && i < shadowData.second->endIndex()) { destinationShadows.push_back(shadowData); } } if (!destinationShadows.empty()) { destinationShadows.shrink_to_fit(); destinations[i] = extraProvider_->makeShadow( proxy_, std::move(destinations[i]), std::move(destinationShadows), shadowPolicy); } } } // add weights and override whatever we have in PoolRoute::hash folly::dynamic jhashWithWeights = folly::dynamic::object(); if (pool->getWeights()) { jhashWithWeights = folly::dynamic::object ("hash_func", WeightedCh3HashFunc::type()) ("weights", *pool->getWeights()); } if (json.isObject()) { if (auto jhash = json.get_ptr("hash")) { checkLogic(jhash->isObject() || jhash->isString(), "PoolRoute {}: hash is not object/string", pool->getName()); if (jhash->isString()) { jhashWithWeights["hash_func"] = *jhash; } else { // object for (const auto& it : jhash->items()) { jhashWithWeights[it.first] = it.second; } } } } auto route = makeHashRoute(jhashWithWeights, std::move(destinations)); if (json.isObject()) { if (proxy_->router().opts().destination_rate_limiting) { if (auto jrates = json.get_ptr("rates")) { route = makeRateLimitRoute(std::move(route), RateLimiter(*jrates)); } } if (auto jsplits = json.get_ptr("shard_splits")) { route = makeShardSplitRoute(std::move(route), ShardSplitter(*jsplits)); } } auto asynclogName = pool->getName(); bool needAsynclog = true; if (json.isObject()) { if (auto jasynclog = json.get_ptr("asynclog")) { checkLogic(jasynclog->isBool(), "PoolRoute: asynclog is not bool"); needAsynclog = jasynclog->getBool(); } if (auto jname = json.get_ptr("name")) { checkLogic(jname->isString(), "PoolRoute: name is not a string"); asynclogName = jname->stringPiece().str(); } } if (needAsynclog) { route = createAsynclogRoute(std::move(route), asynclogName); } return route; }