size_t restoreSplayedValue(const std::string& name, size_t interval) { // Attempt to restore a previously-calculated splay. std::string content; getDatabaseValue(kPersistentSettings, "interval." + name, content); if (!content.empty()) { // This query name existed before, check the last requested interval. auto details = osquery::split(content, ":"); if (details.size() == 2) { long last_interval, last_splay; if (safeStrtol(details[0], 10, last_interval) && safeStrtol(details[1], 10, last_splay)) { if (last_interval == static_cast<long>(interval) && last_splay > 0) { // This is a matching interval, use the previous splay. return static_cast<size_t>(last_splay); } } } } // If the splayed interval was not restored from the database. auto splay = splayValue(interval, FLAGS_schedule_splay_percent); content = std::to_string(interval) + ":" + std::to_string(splay); setDatabaseValue(kPersistentSettings, "interval." + name, content); return splay; }
inline void additionalScheduledQuery(const std::string& name, const tree_node& node, ConfigData& conf) { // Read tree/JSON into a query structure. ScheduledQuery query; query.query = node.second.get<std::string>("query", ""); query.interval = node.second.get<int>("interval", 0); if (query.interval == 0) { VLOG(1) << "Setting invalid interval=0 to 84600 for query: " << name; query.interval = 86400; } // This is a candidate for a catch-all iterator with a catch for boolean type. query.options["snapshot"] = node.second.get<bool>("snapshot", false); query.options["removed"] = node.second.get<bool>("removed", true); // Check if this query exists, if so, check if it was changed. if (conf.schedule.count(name) > 0) { if (query == conf.schedule.at(name)) { return; } } // This is a new or updated scheduled query, update the splay. query.splayed_interval = splayValue(query.interval, FLAGS_schedule_splay_percent); // Update the schedule map and replace the all_data node record. conf.schedule[name] = query; }
// inline void mergeScheduledQuery(const tree_node& node, ConfigData& conf) { inline void mergeScheduledQuery(const std::string& name, const tree_node& node, ConfigData& conf) { // Read tree/JSON into a query structure. ScheduledQuery query; query.query = node.second.get<std::string>("query", ""); query.interval = node.second.get<int>("interval", 0); // Check if this query exists, if so, check if it was changed. if (conf.schedule.count(name) > 0) { if (query == conf.schedule.at(name)) { return; } } // This is a new or updated scheduled query, update the splay. query.splayed_interval = splayValue(query.interval, FLAGS_schedule_splay_percent); // Update the schedule map and replace the all_data node record. conf.schedule[name] = query; if (conf.all_data.count("schedule") > 0) { conf.all_data.get_child("schedule").erase(name); } conf.all_data.add_child("schedule." + name, node.second); }
TEST_F(ConfigTests, test_splay) { auto val1 = splayValue(100, 10); EXPECT_GE(val1, 90); EXPECT_LE(val1, 110); auto val2 = splayValue(100, 10); EXPECT_GE(val2, 90); EXPECT_LE(val2, 110); auto val3 = splayValue(10, 0); EXPECT_EQ(val3, 10); auto val4 = splayValue(100, 1); EXPECT_GE(val4, 99); EXPECT_LE(val4, 101); auto val5 = splayValue(1, 10); EXPECT_EQ(val5, 1); }
TEST_F(PacksTests, test_splay) { auto val1 = splayValue(100, 10); EXPECT_GE(val1, 90U); EXPECT_LE(val1, 110U); auto val2 = splayValue(100, 10); EXPECT_GE(val2, 90U); EXPECT_LE(val2, 110U); auto val3 = splayValue(10, 0); EXPECT_EQ(val3, 10U); auto val4 = splayValue(100, 1); EXPECT_GE(val4, 99U); EXPECT_LE(val4, 101U); auto val5 = splayValue(1, 10); EXPECT_EQ(val5, 1U); }
void Pack::initialize(const std::string& name, const std::string& source, const pt::ptree& tree) { name_ = name; source_ = source; discovery_queries_.clear(); if (tree.count("discovery") > 0) { for (const auto& item : tree.get_child("discovery")) { discovery_queries_.push_back(item.second.get_value<std::string>()); } } discovery_cache_ = std::make_pair<int, bool>(0, false); stats_ = {0, 0, 0}; platform_.clear(); if (tree.count("platform") > 0) { platform_ = tree.get<std::string>("platform"); } version_.clear(); if (tree.count("version") > 0) { version_ = tree.get<std::string>("version"); } schedule_.clear(); if (tree.count("queries") > 0) { for (const auto& q : tree.get_child("queries")) { if (q.second.count("platform")) { if (!checkPlatform(q.second.get<std::string>("platform"))) { continue; } } if (q.second.count("version")) { if (!checkVersion(q.second.get<std::string>("version"))) { continue; } } ScheduledQuery query; query.interval = q.second.get<int>("interval", FLAGS_schedule_default_interval); query.splayed_interval = splayValue(query.interval, FLAGS_schedule_splay_percent); query.query = q.second.get<std::string>("query"); query.options["snapshot"] = q.second.get<bool>("snapshot", false); query.options["removed"] = q.second.get<bool>("removed", true); schedule_[q.first] = query; } } }