PhpFunc::PhpFunc(const folly::dynamic& d, const fbstring& className) : m_name(d["name"].asString()), m_className(className), m_func(d), m_desc(getFollyDynamicDefaultString(d, "desc", "")), m_returnRef(d.getDefault("ref", "false") == "true"), m_returnKindOf(KindOfNull), m_returnCppType("void"), m_returnPhpType("void"), m_minNumParams(0), m_numTypeChecks(0) { auto returnIt = d.find("return"); if (returnIt != d.items().end()) { auto retNode = returnIt->second; auto typeIt = retNode.find("type"); if (typeIt != retNode.items().end()) { auto type = typeIt->second; if ((type.isString()) && (type != "void") && (type != "null")) { m_returnKindOf = m_returnRef ? KindOfRef : kindOfFromDynamic(type); m_returnCppType = typeString(type, true); m_returnPhpType = phpTypeFromDataType(m_returnKindOf); } } m_returnDesc = getFollyDynamicDefaultString(retNode, "desc", ""); } auto args = d.find("args"); if (args == d.items().end() || !args->second.isArray()) { throw std::logic_error( folly::format("'{0}' must have an array field 'args'", name()).str() ); } auto ret = d.find("return"); if (ret == d.items().end() || !ret->second.isObject() || ret->second.find("type") == ret->second.items().end()) { throw std::logic_error( folly::format("'{0}' must have an array field 'return', which must have " "a string field 'type'", name()).str() ); } bool magic = isMagicMethod(); for (auto &p : args->second) { PhpParam param(p, magic); m_params.push_back(param); if (!param.hasDefault()) { ++m_minNumParams; } if (param.isCheckedType()) { ++m_numTypeChecks; } } m_flags = parseFlags(m_func["flags"]); }
JSValueRef Value::fromDynamicInner(JSContextRef ctx, const folly::dynamic& obj) { switch (obj.type()) { // For primitive types (and strings), just create and return an equivalent JSValue case folly::dynamic::Type::NULLT: return JSC_JSValueMakeNull(ctx); case folly::dynamic::Type::BOOL: return JSC_JSValueMakeBoolean(ctx, obj.getBool()); case folly::dynamic::Type::DOUBLE: return JSC_JSValueMakeNumber(ctx, obj.getDouble()); case folly::dynamic::Type::INT64: return JSC_JSValueMakeNumber(ctx, obj.asDouble()); case folly::dynamic::Type::STRING: return JSC_JSValueMakeString(ctx, String(ctx, obj.getString().c_str())); case folly::dynamic::Type::ARRAY: { // Collect JSValue for every element in the array JSValueRef vals[obj.size()]; for (size_t i = 0; i < obj.size(); ++i) { vals[i] = fromDynamicInner(ctx, obj[i]); } // Create a JSArray with the values JSValueRef arr = JSC_JSObjectMakeArray(ctx, obj.size(), vals, nullptr); return arr; } case folly::dynamic::Type::OBJECT: { // Create an empty object JSObjectRef jsObj = JSC_JSObjectMake(ctx, nullptr, nullptr); // Create a JSValue for each of the object's children and set them in the object for (auto it = obj.items().begin(); it != obj.items().end(); ++it) { JSC_JSObjectSetProperty( ctx, jsObj, String(ctx, it->first.asString().c_str()), fromDynamicInner(ctx, it->second), kJSPropertyAttributeNone, nullptr); } return jsObj; } default: // Assert not reached LOG(FATAL) << "Trying to convert a folly object of unsupported type."; return JSC_JSValueMakeNull(ctx); } }
ShardSplitter::ShardSplitter(const folly::dynamic& json) { if (!json.isObject()) { return; } for (const auto& it : json.items()) { if (!it.second.isInt()) { LOG(ERROR) << "ShardSplitter: shard_splits value is not an int for " << it.first.asString(); continue; } auto splitCnt = it.second.asInt(); if (splitCnt <= 0) { LOG(ERROR) << "ShardSplitter: shard_splits value <= 0 '" << it.first.asString() << "': " << splitCnt; } else if (static_cast<size_t>(splitCnt) > kMaxSplits) { LOG(ERROR) << "ShardSplitter: shard_splits value > " << kMaxSplits << " '" << it.first.asString() << "': " << splitCnt; shardSplits_.emplace(it.first.c_str(), kMaxSplits); } else { shardSplits_.emplace(it.first.c_str(), splitCnt); } } }
void HyperlinkViewManager::UpdateProperties(ShadowNodeBase* nodeToUpdate, const folly::dynamic& reactDiffMap) { auto button = nodeToUpdate->GetView().as<winrt::HyperlinkButton>(); if (button == nullptr) return; for (const auto& pair : reactDiffMap.items()) { const std::string& propertyName = pair.first.getString(); const folly::dynamic& propertyValue = pair.second; if (propertyName == "disabled") { if (propertyValue.isBool()) button.IsEnabled(!propertyValue.asBool()); } else if (propertyName == "tooltip") { if (propertyValue.isString()) { winrt::TextBlock tooltip = winrt::TextBlock(); tooltip.Text(asHstring(propertyValue)); winrt::ToolTipService::SetToolTip(button, tooltip); } } else if (propertyName == "url") { winrt::Uri myUri(asHstring(propertyValue)); button.NavigateUri(myUri); } } Super::UpdateProperties(nodeToUpdate, reactDiffMap); }
void Scheduler::startSurface( SurfaceId surfaceId, const std::string &moduleName, const folly::dynamic &initialProps, const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) { std::lock_guard<std::mutex> lock(mutex_); auto shadowTree = std::make_unique<ShadowTree>(surfaceId, layoutConstraints, layoutContext); shadowTree->setDelegate(this); shadowTreeRegistry_.emplace(surfaceId, std::move(shadowTree)); #ifndef ANDROID // TODO: Is this an ok place to do this? auto serializedCommands = initialProps.find("serializedCommands"); if (serializedCommands != initialProps.items().end()) { auto tree = TemplateRenderer::buildShadowTree(serializedCommands->second.asString(), surfaceId, folly::dynamic::object(), *componentDescriptorRegistry_); uiManagerDidFinishTransactionWithoutLock(surfaceId, std::make_shared<SharedShadowNodeList>(SharedShadowNodeList {tree})); // TODO: hydrate rather than replace uiManager_->startSurface(surfaceId, moduleName, initialProps); } else { uiManager_->startSurface(surfaceId, moduleName, initialProps); } #endif }
void SwitchViewManager::UpdateProperties(ShadowNodeBase* nodeToUpdate, const folly::dynamic& reactDiffMap) { auto toggleSwitch = nodeToUpdate->GetView().as<winrt::ToggleSwitch>(); if (toggleSwitch == nullptr) return; for (const auto& pair : reactDiffMap.items()) { const std::string& propertyName = pair.first.getString(); const folly::dynamic& propertyValue = pair.second; if (propertyName == "disabled") { if (propertyValue.isBool()) toggleSwitch.IsEnabled(!propertyValue.asBool()); else if (pair.second.isNull()) toggleSwitch.ClearValue(winrt::Control::IsEnabledProperty()); } else if (propertyName == "value") { if (propertyValue.isBool()) toggleSwitch.IsOn(propertyValue.asBool()); else if (pair.second.isNull()) toggleSwitch.ClearValue(winrt::ToggleSwitch::IsOnProperty()); } } Super::UpdateProperties(nodeToUpdate, reactDiffMap); }
void CheckBoxViewManager::UpdateProperties(ShadowNodeBase* nodeToUpdate, const folly::dynamic& reactDiffMap) { auto checkbox = nodeToUpdate->GetView().as<winrt::CheckBox>(); if (checkbox == nullptr) return; for (const auto& pair : reactDiffMap.items()) { const std::string& propertyName = pair.first.getString(); const folly::dynamic& propertyValue = pair.second; if (propertyName == "disabled") { if (propertyValue.isBool()) checkbox.IsEnabled(!propertyValue.asBool()); else if (pair.second.isNull()) checkbox.ClearValue(winrt::Control::IsEnabledProperty()); } else if (propertyName == "checked") { if (propertyValue.isBool()) checkbox.IsChecked(propertyValue.asBool()); else if (pair.second.isNull()) checkbox.ClearValue(winrt::Primitives::ToggleButton::IsCheckedProperty()); } } Super::UpdateProperties(nodeToUpdate, reactDiffMap); }
static Variant dynamic_to_variant(const folly::dynamic& v) { switch (v.type()) { case folly::dynamic::Type::NULLT: return init_null(); case folly::dynamic::Type::BOOL: return v.asBool(); case folly::dynamic::Type::DOUBLE: return v.asDouble(); case folly::dynamic::Type::INT64: return v.asInt(); case folly::dynamic::Type::STRING: return v.data(); case folly::dynamic::Type::ARRAY: case folly::dynamic::Type::OBJECT: ArrayInit arr_init(v.size(), ArrayInit::Mixed{}); for (auto& item : v.items()) { arr_init.add(dynamic_to_variant(item.first), dynamic_to_variant(item.second)); } Array ret = arr_init.toArray(); // Sort the array since folly::dynamic has a tendency to iterate from // back to front. This way a var_dump of the array, for example, looks // ordered. ret.sort(Array::SortNaturalAscending, true, false); return ret; } not_reached(); }
bool ini_on_update(const folly::dynamic& value, std::map<std::string, std::string>& p) { INI_ASSERT_ARR(value); for (auto& pair : value.items()) { p[pair.first.data()] = pair.second.data(); } return true; }
RouteNextHopsMulti RouteNextHopsMulti::fromFollyDynamic(const folly::dynamic& json) { RouteNextHopsMulti nh; for (const auto& pair : json.items()) { nh.update(ClientID(pair.first.asInt()), RouteNextHopEntry::fromFollyDynamic(pair.second)); } return nh; }
bool PhpConst::parseType(const folly::dynamic& cns) { auto it = cns.find("type"); if (it != cns.items().end()) { m_kindOf = kindOfFromDynamic(it->second); m_cppType = typeString(it->second, false); return true; } return false; }
PhpClass::PhpClass(const folly::dynamic &c) : m_class(c), m_idlName(c["name"].asString()), m_phpName(toPhpName(m_idlName)), m_cppName(toCppName(m_idlName)), m_flags(parseFlags(m_class["flags"])), m_desc(getFollyDynamicDefaultString(c, "desc", "")) { auto ifacesIt = m_class.find("ifaces"); if (ifacesIt != m_class.items().end()) { auto ifaces = ifacesIt->second; if (!ifaces.isArray()) { throw std::logic_error( folly::format("Class {0}.ifaces field must be an array", m_idlName).str() ); } for (auto &interface : ifaces) { m_ifaces.push_back(interface.asString()); } } for (auto const& f : c["funcs"]) { PhpFunc func(f, getCppName()); m_methods.push_back(func); } if (c.find("consts") != c.items().end()) { for (auto const& cns : c["consts"]) { PhpConst cons(cns, getCppName()); m_constants.push_back(cons); } } if (c.find("properties") != c.items().end()) { for (auto const& prp : c["properties"]) { PhpProp prop(prp, getCppName()); m_properties.push_back(prop); } } }
bool PhpConst::inferType(const folly::dynamic& cns) { auto it = cns.find("value"); if (it != cns.items().end()) { m_kindOf = kindOfFromValue(it->second); auto typeIt = g_typeMap.find((int)m_kindOf); if (typeIt != g_typeMap.end()) { m_cppType = typeIt->second; return true; } } return false; }
static fbstring getFollyDynamicDefaultString(const folly::dynamic& d, const fbstring& key, const fbstring& def) { auto it = d.find(key); if (it == d.items().end()) { return def; } auto val = it->second; if (val.isNull()) { return def; } return val.asString(); }
SharedShadowNode UITemplateProcessor::buildShadowTree( const std::string &jsonStr, Tag rootTag, const folly::dynamic ¶ms, const ComponentDescriptorRegistry &componentDescriptorRegistry, const NativeModuleRegistry &nativeModuleRegistry, const std::shared_ptr<const ReactNativeConfig> reactNativeConfig) { LOG(INFO) << "(strt) UITemplateProcessor inject hardcoded 'server rendered' view tree"; std::string content = jsonStr; for (const auto ¶m : params.items()) { const auto &key = param.first.asString(); size_t start_pos = content.find(key); if (start_pos != std::string::npos) { content.replace(start_pos, key.length(), param.second.asString()); } } auto parsed = folly::parseJson(content); auto commands = parsed["commands"]; std::vector<SharedShadowNode> nodes(commands.size() * 2); std::vector<folly::dynamic> registers(32); for (const auto &command : commands) { try { if (DEBUG_FLY) { LOG(INFO) << "try to run command " << folly::toJson(command); } auto ret = runCommand( command, rootTag, nodes, registers, componentDescriptorRegistry, nativeModuleRegistry, reactNativeConfig); if (ret != nullptr) { return ret; } } catch (const std::exception &e) { LOG(ERROR) << " >>> Exception <<< running previous command '" << folly::toJson(command) << "': '" << e.what() << "'"; } } LOG(ERROR) << "react ui template missing returnRoot command :("; throw std::runtime_error( "Missing returnRoot command in template content:\n" + content); return SharedShadowNode{}; }
LocationObserverOptions(const folly::dynamic& options) { if (!options.empty()) { for (auto& opt : options.items()) { if (opt.first == "timeout") timeout = opt.second.asDouble(); else if (opt.first == "maximumAge") maxAge = opt.second.asDouble(); else if (opt.first == "enableHighAccuracy") highAccuracy = opt.second.asBool(); else if (opt.first == "distanceFilter") distanceFilter = opt.second.asDouble(); } } }
AclEntryFields AclEntryFields::fromFollyDynamic( const folly::dynamic& aclEntryJson) { AclEntryFields aclEntry(AclEntryID(aclEntryJson[kId].asInt())); if (aclEntryJson.find(kSrcIp) != aclEntryJson.items().end()) { aclEntry.srcIp = IPAddress::createNetwork( aclEntryJson[kSrcIp].asString()); } if (aclEntryJson.find(kDstIp) != aclEntryJson.items().end()) { aclEntry.dstIp = IPAddress::createNetwork( aclEntryJson[kDstIp].asString()); } if (aclEntry.srcIp.first && aclEntry.dstIp.first && aclEntry.srcIp.first.isV4() != aclEntry.dstIp.first.isV4()) { throw FbossError( "Unmatched ACL IP versions ", aclEntryJson[kSrcIp].asString(), " vs ", aclEntryJson[kDstIp].asString() ); } if (aclEntryJson.find(kL4SrcPort) != aclEntryJson.items().end()) { aclEntry.l4SrcPort = aclEntryJson[kL4SrcPort].asInt(); } if (aclEntryJson.find(kL4DstPort) != aclEntryJson.items().end()) { aclEntry.l4DstPort = aclEntryJson[kL4DstPort].asInt(); } if (aclEntryJson.find(kProto) != aclEntryJson.items().end()) { aclEntry.proto = aclEntryJson[kProto].asInt(); } if (aclEntryJson.find(kTcpFlags) != aclEntryJson.items().end()) { aclEntry.tcpFlags = aclEntryJson[kTcpFlags].asInt(); } if (aclEntryJson.find(kTcpFlagsMask) != aclEntryJson.items().end()) { aclEntry.tcpFlagsMask = aclEntryJson[kTcpFlagsMask].asInt(); } auto itr_action = cfg::_AclAction_NAMES_TO_VALUES.find( aclEntryJson[kAction].asString().c_str()); if (itr_action == cfg::_AclAction_NAMES_TO_VALUES.end()) { throw FbossError( "Unsupported ACL action ", aclEntryJson[kAction].asString()); } aclEntry.action = cfg::AclAction(itr_action->second); return aclEntry; }
SwitchStateFields SwitchStateFields::fromFollyDynamic(const folly::dynamic& swJson) { SwitchStateFields switchState; switchState.interfaces = InterfaceMap::fromFollyDynamic( swJson[kInterfaces]); switchState.ports = PortMap::fromFollyDynamic(swJson[kPorts]); switchState.vlans = VlanMap::fromFollyDynamic(swJson[kVlans]); switchState.routeTables = RouteTableMap::fromFollyDynamic( swJson[kRouteTables]); switchState.acls = AclMap::fromFollyDynamic(swJson[kAcls]); if (swJson.count(kSflowCollectors) > 0) { switchState.sFlowCollectors = SflowCollectorMap::fromFollyDynamic( swJson[kSflowCollectors]); } switchState.defaultVlan = VlanID(swJson[kDefaultVlan].asInt()); if (swJson.find(kControlPlane) != swJson.items().end()) { switchState.controlPlane = ControlPlane::fromFollyDynamic( swJson[kControlPlane]); } //TODO verify that created state here is internally consistent t4155406 return switchState; }
static Variant dynamic_to_variant(const folly::dynamic& v) { switch (v.type()) { case folly::dynamic::Type::NULLT: return init_null_variant; case folly::dynamic::Type::BOOL: return v.asBool(); case folly::dynamic::Type::DOUBLE: return v.asDouble(); case folly::dynamic::Type::INT64: return v.asInt(); case folly::dynamic::Type::STRING: return v.data(); case folly::dynamic::Type::ARRAY: case folly::dynamic::Type::OBJECT: ArrayInit ret(v.size(), ArrayInit::Mixed{}); for (auto& item : v.items()) { ret.add(dynamic_to_variant(item.first), dynamic_to_variant(item.second)); } return ret.toArray(); } not_reached(); }
PhpFunc PhpFunc::fromDynamic(const folly::dynamic& d, const fbstring& className) { // Better at least have a name auto name = d["name"].asString(); auto args = d.find("args"); auto flags = d.find("flags"); auto ret = d.find("return"); if (args == d.items().end() || !args->second.isArray()) { throw std::logic_error( folly::format("'{0}' must have an array field 'args'", name).str() ); } if (flags == d.items().end() || !flags->second.isArray()) { throw std::logic_error( folly::format("'{0}' must have an array field 'flags'", name).str() ); } if (ret == d.items().end() || !ret->second.isObject() || ret->second.find("type") == ret->second.items().end()) { throw std::logic_error( folly::format("'{0}' must have an array field 'return', which must have " "a string field 'type'", name).str() ); } auto areVarargs = [](const fbstring& str) { return (str == "VariableArguments" || str == "RefVariableArguments" || str == "MixedVariableArguments"); }; fbvector<PhpParam> params; try { params = std::move(folly::convertTo<fbvector<PhpParam>>(args->second)); } catch (const std::exception& exc) { throw std::logic_error( folly::format("'{0}' has an arg with either 'name' or 'type' field " "missing", name).str() ); } if (name == "__get" || name == "__set" || name == "__isset" || name == "__unset" || name == "__call") { for (auto& param : params) { param.cppType = "HPHP::Variant"; } } auto refIt = d.find("ref"); bool ref = (refIt != d.items().end() && refIt->second.asString() == "true"); PhpFunc retval; retval.name = name; retval.className = className; retval.returnCppType = typeString(ret->second["type"], true); retval.returnByRef = ref; retval.params = params; retval.isVarargs = anyFlags(areVarargs, flags->second); retval.isStatic = false; if (!className.empty()) { auto areStatic = [](const fbstring& str) { return str == "IsStatic"; }; retval.isStatic = anyFlags(areStatic, flags->second); } retval.initComputedProps(); return retval; }
PhpFunc::PhpFunc(const folly::dynamic& d, const fbstring& className) : m_idlName(d["name"].asString()), m_phpName(toPhpName(m_idlName)), m_cppName(toCppName(m_idlName)), m_className(className), m_func(d), m_desc(getFollyDynamicDefaultString(d, "desc", "")), m_returnRef(d.getDefault("ref", "false") == "true"), m_returnKindOf(KindOfNull), m_returnCppType("void"), m_returnPhpType("void"), m_minNumParams(0), m_numTypeChecks(0) { if (isMethod() && m_idlName.find_last_of(NAMESPACE_STRING) != std::string::npos) { throw std::logic_error( folly::format("'{0}' is a method and cannot have a namespace in its name", m_idlName).str() ); } auto returnIt = d.find("return"); if (returnIt != d.items().end()) { auto retNode = returnIt->second; auto typeIt = retNode.find("type"); if (typeIt != retNode.items().end()) { auto type = typeIt->second; if ((type.isString()) && (type != "void") && (type != "null")) { m_returnKindOf = m_returnRef ? KindOfRef : kindOfFromDynamic(type); m_returnCppType = typeString(type, true); m_returnPhpType = phpTypeFromDataType(m_returnKindOf); } } m_returnDesc = getFollyDynamicDefaultString(retNode, "desc", ""); } auto args = d.find("args"); if (args == d.items().end() || !args->second.isArray()) { throw std::logic_error( folly::format("'{0}' must have an array field 'args'", m_idlName).str() ); } auto ret = d.find("return"); if (ret == d.items().end() || !ret->second.isObject() || ret->second.find("type") == ret->second.items().end()) { throw std::logic_error( folly::format("'{0}' must have an array field 'return', which must have " "a string field 'type'", m_idlName).str() ); } bool magic = isMagicMethod(); m_flags = parseFlags(m_func["flags"]); ParamMode paramMode = ParamMode::CoerceAndCall; if (m_flags & ParamCoerceModeNull) { paramMode = ParamMode::ZendNull; } else if (m_flags & ParamCoerceModeFalse) { paramMode = ParamMode::ZendFalse; } for (auto &p : args->second) { PhpParam param(p, magic, paramMode); m_params.push_back(param); if (!param.hasDefault()) { ++m_minNumParams; } if (param.isCheckedType()) { ++m_numTypeChecks; } } }
/* * Initializes list of classes that are reachable via reflection, and calls * or from code. * * These include: * - Classes used in the manifest (e.g. activities, services, etc) * - View or Fragment classes used in layouts * - Classes that are in certain packages (specified in the reflected_packages * section of the config) and classes that extend from them * - Classes marked with special annotations (keep_annotations in config) * - Classes reachable from native libraries */ static void init_permanently_reachable_classes(const Scope& scope, folly::dynamic& config, const std::vector<KeepRule>& proguard_rules) { std::string apk_dir; std::vector<std::string> reflected_package_names; auto config_apk_dir = config.find("apk_dir"); if (config_apk_dir != config.items().end()) { apk_dir = toStdString(config_apk_dir->second.asString()); } auto config_reflected_package_names = config.find("reflected_packages"); if (config_reflected_package_names != config.items().end()) { for (auto config_pkg_name : config_reflected_package_names->second) { std::string pkg_name = toStdString(config_pkg_name.asString()); reflected_package_names.push_back(pkg_name); } } std::unordered_set<DexType*> keep_annotations; auto config_keep_annotations = config.find("keep_annotations"); if (config_keep_annotations != config.items().end()) { for (auto const& config_anno_name : config_keep_annotations->second) { std::string anno_name = toStdString(config_anno_name.asString()); DexType* anno = DexType::get_type(anno_name.c_str()); if (anno) keep_annotations.insert(anno); } } keep_annotated_classes(scope, keep_annotations); std::vector<std::string> keep_pkgs; auto config_keep_packages = config.find("keep_packages"); if (config_keep_packages != config.items().end()) { for (auto const& config_pkg : config_keep_packages->second) { auto pkg_name = toStdString(config_pkg.asString()); keep_pkgs.push_back(pkg_name); } } keep_packages(scope, keep_pkgs); if (apk_dir.size()) { // Classes present in manifest std::string manifest = apk_dir + std::string("/AndroidManifest.xml"); for (std::string classname : get_manifest_classes(manifest)) { mark_reachable_by_classname(classname, false); } // Classes present in XML layouts for (std::string classname : get_layout_classes(apk_dir)) { mark_reachable_by_classname(classname, false); } // Classnames present in native libraries (lib/*/*.so) for (std::string classname : get_native_classes(apk_dir)) { mark_reachable_by_classname(classname, false); } } std::unordered_set<DexClass*> reflected_package_classes; for (auto clazz : scope) { const char* cname = clazz->get_type()->get_name()->c_str(); for (auto pkg : reflected_package_names) { if (starts_with(cname, pkg.c_str())) { reflected_package_classes.insert(clazz); continue; } } } for (auto clazz : scope) { if (in_reflected_pkg(clazz, reflected_package_classes)) { reflected_package_classes.insert(clazz); /* Note: * Some of these are by string, others by type * but we have no way in the config to distinguish * them currently. So, we mark with the most * conservative sense here. */ mark_reachable_by_classname(clazz, false); } } /* Do only keep class rules for now. * '*' and '**' rules are skipped, * because those are matching on something else, * which we haven't implemented yet. * Rules can be "*" or "**" on classname and match * on some other attribute. We don't match against * all attributes at once, so this prevents us * from matching everything. */ std::vector<std::string> cls_patterns; for (auto const& r : proguard_rules) { if (r.classname != nullptr && r.class_type == keeprules::ClassType::CLASS && strlen(r.classname) > 2) { std::string cls_pattern(r.classname); std::replace(cls_pattern.begin(), cls_pattern.end(), '.', '/'); auto prep_pat = 'L' + cls_pattern; TRACE(PGR, 1, "adding pattern %s \n", prep_pat.c_str()); cls_patterns.push_back(prep_pat); } } size_t pg_marked_classes = 0; for (auto clazz : scope) { auto cname = clazz->get_type()->get_name()->c_str(); auto cls_len = strlen(cname); for (auto const& pat : cls_patterns) { int pat_len = pat.size(); if (type_matches(pat.c_str(), cname, pat_len, cls_len)) { mark_reachable_directly(clazz); TRACE(PGR, 2, "matched cls %s against pattern %s \n", cname, pat.c_str()); pg_marked_classes++; break; } } } TRACE(PGR, 1, "matched on %lu classes with CLASS KEEP proguard rules \n", pg_marked_classes); }
ReadableNativeMapKeySetIterator::ReadableNativeMapKeySetIterator(const folly::dynamic& map) : iter_(map.items().begin()) , map_(map) {}
std::shared_ptr<ClientPool> PoolFactory::parsePool(const std::string& name, const folly::dynamic& json) { auto seenPoolIt = pools_.find(name); if (seenPoolIt != pools_.end()) { return seenPoolIt->second; } if (json.isString()) { // get the pool from ConfigApi std::string jsonStr; checkLogic(configApi_.get(ConfigType::Pool, name, jsonStr), "Can not read pool: {}", name); return parsePool(name, parseJsonString(jsonStr)); } else { // one day we may add inheriting from local pool if (auto jinherit = json.get_ptr("inherit")) { checkLogic(jinherit->isString(), "Pool {}: inherit is not a string", name); auto path = jinherit->stringPiece().str(); std::string jsonStr; checkLogic(configApi_.get(ConfigType::Pool, path, jsonStr), "Can not read pool from: {}", path); auto newJson = parseJsonString(jsonStr); for (auto& it : json.items()) { newJson.insert(it.first, it.second); } newJson.erase("inherit"); return parsePool(name, newJson); } } // pool_locality std::chrono::milliseconds timeout{opts_.server_timeout_ms}; if (auto jlocality = json.get_ptr("pool_locality")) { if (!jlocality->isString()) { MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig, "Pool {}: pool_locality is not a string", name); } else { auto str = jlocality->stringPiece(); if (str == "cluster") { if (opts_.cluster_pools_timeout_ms != 0) { timeout = std::chrono::milliseconds(opts_.cluster_pools_timeout_ms); } } else if (str == "region") { if (opts_.regional_pools_timeout_ms != 0) { timeout = std::chrono::milliseconds(opts_.regional_pools_timeout_ms); } } else { MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig, "Pool {}: '{}' pool locality is not supported", name, str); } } } // region & cluster std::string region, cluster; if (auto jregion = json.get_ptr("region")) { if (!jregion->isString()) { MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig, "Pool {}: pool_region is not a string", name); } else { region = jregion->stringPiece().str(); } } if (auto jcluster = json.get_ptr("cluster")) { if (!jcluster->isString()) { MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig, "Pool {}: pool_cluster is not a string", name); } else { cluster = jcluster->stringPiece().str(); } } if (auto jtimeout = json.get_ptr("server_timeout")) { if (!jtimeout->isInt()) { MC_LOG_FAILURE(opts_, memcache::failure::Category::kInvalidConfig, "Pool {}: server_timeout is not an int", name); } else { timeout = std::chrono::milliseconds(jtimeout->getInt()); } } if (!region.empty() && !cluster.empty()) { auto& route = opts_.default_route; if (region == route.getRegion() && cluster == route.getCluster()) { if (opts_.within_cluster_timeout_ms != 0) { timeout = std::chrono::milliseconds(opts_.within_cluster_timeout_ms); } } else if (region == route.getRegion()) { if (opts_.cross_cluster_timeout_ms != 0) { timeout = std::chrono::milliseconds(opts_.cross_cluster_timeout_ms); } } else { if (opts_.cross_region_timeout_ms != 0) { timeout = std::chrono::milliseconds(opts_.cross_region_timeout_ms); } } } auto protocol = parseProtocol(json, mc_ascii_protocol); bool keep_routing_prefix = false; if (auto jkeep_routing_prefix = json.get_ptr("keep_routing_prefix")) { checkLogic(jkeep_routing_prefix->isBool(), "Pool {}: keep_routing_prefix is not a bool"); keep_routing_prefix = jkeep_routing_prefix->getBool(); } uint64_t qosClass = opts_.default_qos_class; uint64_t qosPath = opts_.default_qos_path; if (auto jqos = json.get_ptr("qos")) { parseQos(folly::sformat("Pool {}", name), *jqos, qosClass, qosPath); } bool useSsl = false; if (auto juseSsl = json.get_ptr("use_ssl")) { checkLogic(juseSsl->isBool(), "Pool {}: use_ssl is not a bool", name); useSsl = juseSsl->getBool(); } // servers auto jservers = json.get_ptr("servers"); checkLogic(jservers, "Pool {}: servers not found", name); checkLogic(jservers->isArray(), "Pool {}: servers is not an array", name); auto clientPool = std::make_shared<ClientPool>(name); for (size_t i = 0; i < jservers->size(); ++i) { const auto& server = jservers->at(i); std::shared_ptr<AccessPoint> ap; bool serverUseSsl = useSsl; uint64_t serverQosClass = qosClass; uint64_t serverQosPath = qosPath; checkLogic(server.isString() || server.isObject(), "Pool {}: server #{} is not a string/object", name, i); if (server.isString()) { // we support both host:port and host:port:protocol ap = AccessPoint::create(server.stringPiece(), protocol); checkLogic(ap != nullptr, "Pool {}: invalid server {}", name, server.stringPiece()); } else { // object auto jhostname = server.get_ptr("hostname"); checkLogic(jhostname, "Pool {}: hostname not found for server #{}", name, i); checkLogic(jhostname->isString(), "Pool {}: hostname is not a string for server #{}", name, i); if (auto jqos = server.get_ptr("qos")) { parseQos(folly::sformat("Pool {}, server #{}", name, i), *jqos, qosClass, qosPath); } if (auto juseSsl = server.get_ptr("use_ssl")) { checkLogic(juseSsl->isBool(), "Pool {}: use_ssl is not a bool for server #{}", name, i); serverUseSsl = juseSsl->getBool(); } ap = AccessPoint::create(jhostname->stringPiece(), parseProtocol(server, protocol)); checkLogic(ap != nullptr, "Pool {}: invalid server #{}", name, i); } auto client = clientPool->emplaceClient( timeout, std::move(ap), keep_routing_prefix, serverUseSsl, serverQosClass, serverQosPath); clients_.push_back(std::move(client)); } // servers // weights if (auto jweights = json.get_ptr("weights")) { clientPool->setWeights(*jweights); } pools_.emplace(name, clientPool); return clientPool; }