in mcrouter/routes/CarbonLookasideRoute.h [412:525]
typename RouterInfo::RouteHandlePtr createCarbonLookasideRoute(
RouteHandleFactory<typename RouterInfo::RouteHandleIf>& factory,
const folly::dynamic& json) {
checkLogic(json.isObject(), "CarbonLookasideRoute is not an object");
auto jChild = json.get_ptr("child");
checkLogic(
jChild != nullptr, "CarbonLookasideRoute: 'child' property is missing");
auto child = factory.create(*jChild);
checkLogic(
child != nullptr,
"CarbonLookasideRoute: cannot create route handle from 'child'");
bool subSecTTL = false;
if (auto jTtlUnit = json.get_ptr("ttl_unit_ms")) {
checkLogic(
jTtlUnit->isBool(),
"CarbonLookasideRoute: 'ttl_unit_ms' is not a bool");
if (jTtlUnit->getBool()) {
subSecTTL = true;
}
}
auto jTtl = json.get_ptr("ttl");
checkLogic(
jTtl != nullptr, "CarbonLookasideRoute: 'ttl' property is missing");
checkLogic(jTtl->isInt(), "CarbonLookasideRoute: 'ttl' is not an integer");
int32_t ttl = jTtl->getInt();
if (subSecTTL) {
checkLogic(
ttl >= 10 && ttl < 1000 && (1000 % ttl == 0),
"CarbonLookasideRoute: for sub-second ttl, you must use a number "
"that is >= 10, < 1000, and 1000 must be a multiple of ttl.");
}
std::string prefix = ""; // Defaults to no prefix.
if (auto jPrefix = json.get_ptr("prefix")) {
checkLogic(
jPrefix->isString(), "CarbonLookasideRoute: 'prefix' is not a string");
prefix = jPrefix->getString();
}
std::string flavor = "web"; // Defaults to web flavor.
if (auto jFlavor = json.get_ptr("flavor")) {
checkLogic(
jFlavor->isString(), "CarbonLookasideRoute: 'flavor' is not a string");
flavor = jFlavor->getString();
}
std::unordered_map<std::string, std::string> flavorOverrides;
if (json.get_ptr("flavor_overrides")) {
checkLogic(
parse_json_options(json, "flavor_overrides", flavorOverrides),
"CarbonLookasideRoute: error parsing 'flavor_overrides'");
}
size_t keySplitSize = 1;
if (auto jKeySplitSize = json.get_ptr("key_split_size")) {
checkLogic(
jKeySplitSize->isInt() && jKeySplitSize->getInt() > 0,
"CarbonLookasideRoute: 'key_split_size' must be a positive integer");
keySplitSize = jKeySplitSize->getInt();
}
LeaseSettings leaseSettings = parseLeaseSettings(json);
auto helperConfig = json.get_ptr("helper_config");
if (helperConfig) {
checkLogic(
helperConfig->isObject(),
"CarbonLookasideRoute: 'helper_config' is not an object");
}
CarbonLookasideHelper helper(helperConfig);
// Creates a McRouter client to communicate with memcache using the
// specified flavor information. The route handle owns the router resource
// via a shared_ptr. The router will survive reconfigurations given that
// at least one route handle will maintain a reference to it at any one time.
// It will be cleaned up automatically whenever the last route handle using it
// is removed.
auto persistenceId = folly::to<std::string>("CarbonLookasideClient:", flavor);
auto router =
createCarbonLookasideRouter(persistenceId, flavor, flavorOverrides);
if (!router) {
LOG(ERROR) << "Failed to create router from flavor '" << flavor
<< "' for CarbonLookasideRouter.";
return child;
}
CarbonRouterClient<MemcacheRouterInfo>::Pointer client{nullptr};
try {
client = router->createClient(0 /* max_outstanding_requests */);
} catch (const std::runtime_error& e) {
LOG(ERROR)
<< "Failed to create client for CarbonLookasideRouter. Exception: "
<< e.what();
return child;
}
return makeRouteHandleWithInfo<
RouterInfo,
CarbonLookasideRoute,
CarbonLookasideHelper>(
std::move(child),
std::move(router),
std::move(client),
std::move(prefix),
keySplitSize,
ttl,
subSecTTL,
std::move(helper),
std::move(leaseSettings));
}