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;
}
Exemplo n.º 2
0
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);
  }
}
Exemplo n.º 3
0
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());
}
Exemplo n.º 4
0
Arquivo: Dump.cpp Projeto: 1Hgm/folly
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;
    }
}
Exemplo n.º 6
0
  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;
  }
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
 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)));
     }
   }
 }
Exemplo n.º 9
0
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;
  }
}