dynamic dynamic::merge_diff(const dynamic& source, const dynamic& target) { if (!source.isObject() || source.type() != target.type()) { return target; } dynamic diff = object; // added/modified keys for (const auto& pair : target.items()) { auto it = source.find(pair.first); if (it == source.items().end()) { diff[pair.first] = pair.second; } else { diff[pair.first] = merge_diff(source[pair.first], target[pair.first]); } } // removed keys for (const auto& pair : source.items()) { auto it = target.find(pair.first); if (it == target.items().end()) { diff[pair.first] = nullptr; } } return diff; }
SettingsMap::SettingsMap(const dynamic& d) { if (!d.isObject()) { throw BistroException("Can only create settings map from an object"); } for (const auto& pair : d.items()) { const string& name = pair.first.asString().toStdString(); set(name, pair.second); } }
CrontabSelector::CrontabSelector( const dynamic &d, int64_t min_val, int64_t max_val, function<int64_t(const string& lc_str)> str_to_value ) : start_(min_val), end_(max_val), period_(1), minVal_(min_val), maxVal_(max_val) { switch (d.type()) { case dynamic::Type::INT64: case dynamic::Type::STRING: sortedValues_.emplace_back(parseValue(d, str_to_value)); break; case dynamic::Type::ARRAY: for (const auto& val : d) { sortedValues_.emplace_back(parseValue(val, str_to_value)); } // If somebody specifies [] for a selector, we have to silently // accept it, since PHP's JSON library can morph {} into [], and {} // must mean "default selector accepting all values." break; case dynamic::Type::OBJECT: for (const auto& pair : d.items()) { // Interval is first so that it doesn't accept strings like "jan" if (pair.first == "period") { period_ = pair.second.asInt(); if (period_ < 1 || period_ >= maxVal_ - minVal_) { throw runtime_error(format( "period not in [1, {}]: {}", maxVal_ - minVal_, period_ ).str()); } continue; } // For start & end, we are happy to accept string names auto val = parseValue(pair.second, str_to_value); if (pair.first == "start") { start_ = val; } else if (pair.first == "end") { end_ = val; } else { throw runtime_error(format("Unknown key: {}", pair.first).str()); } } // If we got an empty object, no problem -- this selector will // follow the default of "match everything". break; default: throw runtime_error(format( "Bad type for crontab selector: {}", d.typeName() ).str()); } sort(sortedValues_.begin(), sortedValues_.end()); }
static void bserEncodeObject(dynamic const& dyn, QueueAppender& appender, const serialization_opts& opts) { appender.write((int8_t)BserType::Object); bserEncodeInt(dyn.size(), appender); if (opts.sort_keys) { std::vector<std::pair<dynamic, dynamic>> sorted(dyn.items().begin(), dyn.items().end()); std::sort(sorted.begin(), sorted.end()); for (const auto& item : sorted) { bserEncode(item.first, appender, opts); bserEncode(item.second, appender, opts); } } else { for (const auto& item : dyn.items()) { bserEncode(item.first, appender, opts); bserEncode(item.second, appender, opts); } } }
static void GenStat(Stat& stat, const dynamic& v) { switch (v.type()) { case dynamic::ARRAY: { for (auto &i : v) GenStat(stat, i); stat.arrayCount++; stat.elementCount += v.size(); } break; case dynamic::OBJECT: { auto p = v.items(); for (auto& i : p) { GenStat(stat, i.second); stat.stringLength += i.first.size(); } stat.objectCount++; stat.memberCount += v.size(); stat.stringCount += v.size(); } break; case dynamic::STRING: stat.stringCount++; stat.stringLength += v.size(); break; case dynamic::INT64: case dynamic::DOUBLE: stat.numberCount++; break; case dynamic::BOOL: if (v.getBool()) stat.trueCount++; else stat.falseCount++; break; case dynamic::NULLT: stat.nullCount++; break; } }
Optional<SchemaError> validate(ValidationContext& vc, const dynamic& value) const override { if (!value.isObject()) { return none; } for (const auto& pair : value.items()) { if (!pair.first.isString()) { continue; } const fbstring& key = pair.first.getString(); auto it = propertyValidators_.find(key); bool matched = false; if (it != propertyValidators_.end()) { if (auto se = vc.validate(it->second.get(), pair.second)) { return se; } matched = true; } const std::string& strkey = key.toStdString(); for (const auto& ppv : patternPropertyValidators_) { if (boost::regex_search(strkey, ppv.first)) { if (auto se = vc.validate(ppv.second.get(), pair.second)) { return se; } matched = true; } } if (matched) { continue; } if (!allowAdditionalProperties_) { return makeError("no more additional properties", value); } if (additionalPropertyValidator_) { if (auto se = vc.validate(additionalPropertyValidator_.get(), pair.second)) { return se; } } } return none; }
int MCRouterTestClient::set(const dynamic &kv_pairs, dynamic &results) { std::vector<mcrouter_msg_t> msgs(kv_pairs.size()); int i = 0; dynamic raw_results = dynamic::object; for (auto &kv_pair : kv_pairs.items()) { msgs[i] = make_set_request(kv_pair.first.asString().toStdString(), kv_pair.second.asString().toStdString()); i ++; } int ret = 0; bool res = issueRequests(msgs.data(), kv_pairs.size(), raw_results); if (res) { for ( auto& raw_reply : raw_results.items()) { bool stored = (raw_reply.second["result"] == (int) mc_res_stored); results[raw_reply.first] = stored; ret += (int) stored; } } return ret; }
DependencyValidator(SchemaValidatorContext& context, const dynamic& schema) { if (!schema.isObject()) { return; } for (const auto& pair : schema.items()) { if (!pair.first.isString()) { continue; } if (pair.second.isArray()) { auto p = make_pair(pair.first.getString(), std::vector<fbstring>()); for (const auto& item : pair.second) { if (item.isString()) { p.second.push_back(item.getString()); } } propertyDep_.emplace_back(std::move(p)); } if (pair.second.isObject()) { schemaDep_.emplace_back( make_pair(pair.first.getString(), SchemaValidator::make(context, pair.second))); } } }
Job::Job(const Config& config, const string& name, const dynamic& d) : id_(Job::JobNameTable->insert(name)), name_(name), enabled_(d.getDefault("enabled", true).asBool()), owner_(d.getDefault("owner", "").asString().toStdString()), levelForTasks_(config.levelForTasks), priority_(d.getDefault("priority", 1.0).asDouble()), resources_(config.defaultJobResources), config_(dynamic::object), filters_(config.levels.size()), levelForHostPlacement_(StringTable::NotFound), backoffSettings_(config.defaultBackoffSettings), killOrphanTasksAfter_(config.killOrphanTasksAfter) { try { if (owner_.empty()) { throw BistroException("Job ", name, " missing owner."); } if (const auto* level_for_tasks_ptr = d.get_ptr("level_for_tasks")) { if (!level_for_tasks_ptr->isString()) { throw BistroException("'level_for_tasks' must be a string for ", name); } const auto& str_level_for_tasks = level_for_tasks_ptr->asString().toStdString(); int level_for_tasks = config.levels.lookup(str_level_for_tasks); if (level_for_tasks == StringTable::NotFound) { throw BistroException("Bad level_for_tasks: ", str_level_for_tasks); } levelForTasks_ = level_for_tasks; } auto it = d.find("resources"); if (it != d.items().end()) { if (!it->second.isObject()) { throw BistroException("'resources' must be an object for ", name); } for (const auto& pair : it->second.items()) { const auto& name = pair.first.asString().toStdString(); const int resource_id = config.resourceNames.lookup(name); if (resource_id == StringTable::NotFound) { throw BistroException("Invalid resource: ", name); } resources_[resource_id] = pair.second.asInt(); } } it = d.find("config"); if (it != d.items().end()) { if (!it->second.isObject()) { throw BistroException("'config' must be an object for ", name); } update(config_, it->second); } it = d.find("backoff"); if (it != d.items().end()) { if (!it->second.isArray()) { throw BistroException("'backoff' must be an array for ", name); } backoffSettings_ = JobBackoffSettings(it->second); } it = d.find("filters"); if (it != d.items().end()) { if (!it->second.isObject()) { throw BistroException("'filters' must be an object for ", name); } for (const auto& pair : it->second.items()) { const auto& level = pair.first.asString().toStdString(); const int level_id = config.levels.lookup(level); if (level_id == StringTable::NotFound) { throw BistroException("Invalid level in filters: ", level); } filters_[level_id] = JobFilters(pair.second); } } detail::parseKillOrphanTasksAfter(d, &killOrphanTasksAfter_); if (auto* ptr = d.get_ptr("version_id")) { if (!ptr->isInt()) { throw std::runtime_error("'version_id' must be an integer"); } versionID_ = ptr->getInt(); } if (const auto* host_level_ptr = d.get_ptr("level_for_host_placement")) { if (!host_level_ptr->isString()) { throw BistroException( "'level_for_host_placement' must be a string for ", name ); } const auto& str_host_level = host_level_ptr->asString().toStdString(); int host_level = config.levels.lookup(str_host_level); if (host_level == StringTable::NotFound) { throw BistroException( "Bad level_for_host_placement: ", str_host_level ); } levelForHostPlacement_ = host_level; } if (const auto* host_ptr = d.get_ptr("host_placement")) { if (!host_ptr->isString()) { throw BistroException("'host_placement' must be a string for ", name); } hostPlacement_ = host_ptr->asString().toStdString(); if (!hostPlacement_.empty() && levelForHostPlacement_ != StringTable::NotFound) { throw BistroException( "It makes no sense to specify both 'level_for_host_placement' and " "'host_placement'" ); } } it = d.find("create_time"); // Silently ignore non-integers because this isn't critical configuration if (it != d.items().end() && it->second.isInt()) { createTime_ = it->second.asInt(); } it = d.find("modify_time"); // Silently ignore non-integers because this isn't critical configuration if (it != d.items().end() && it->second.isInt()) { modifyTime_ = it->second.asInt(); } // We don't check that the job names in depends_on are valid jobs. // If an invalid job is specified here, or if there is circular dependency, // this job can never run. it = d.find("depends_on"); if (it != d.items().end()) { if (!it->second.isArray()) { throw BistroException("'depends_on' must be an array for ", name); } for (const auto& job_name : it->second) { dependsOn_.push_back(static_cast<ID>(JobNameTable->insert( job_name.asString().toStdString() ))); } } } catch (const exception& e) { LOG(ERROR) << "Error creating job: " << e.what(); error_ = e.what(); enabled_ = false; } }