std::vector<std::string> EventSubscriberPlugin::getIndexes(EventTime start, EventTime stop) { auto index_key = "indexes." + dbNamespace(); std::vector<std::string> indexes; EventTime l_start = (start > 0) ? start / 60 : 0; EventTime r_stop = (stop > 0) ? stop / 60 + 1 : 0; std::string content; getDatabaseValue(kEvents, index_key + ".60", content); if (content.empty()) { return indexes; } std::vector<std::string> bins, expirations; boost::split(bins, content, boost::is_any_of(",")); for (const auto& bin : bins) { auto step = timeFromRecord(bin); auto step_start = step * 60; auto step_stop = (step + 1) * 60; if (step_stop < expire_time_) { expirations.push_back(bin); } else if (step_start < expire_time_) { expireRecords("60", bin, false); } if (step >= l_start && (r_stop == 0 || step < r_stop)) { indexes.push_back("60." + bin); } } // Rewrite the index lists and delete each expired item. if (!expirations.empty()) { expireIndexes("60", bins, expirations); } // Return indexes in binning order. std::sort(indexes.begin(), indexes.end(), [](const std::string& left, const std::string& right) { auto n1 = timeFromRecord(left.substr(left.find(".") + 1)); auto n2 = timeFromRecord(right.substr(right.find(".") + 1)); return n1 < n2; }); // Update the new time that events expire to now - expiry. return indexes; }
std::set<std::string> EventSubscriberPlugin::getIndexes(EventTime start, EventTime stop, int list_key) { auto db = DBHandle::getInstance(); auto index_key = "indexes." + dbNamespace(); std::set<std::string> indexes; // Keep track of the tail/head of account time while bin searching. EventTime start_max = stop, stop_min = stop, local_start, local_stop; auto types = kEventTimeLists.size(); // List types are sized bins of time containing records for this namespace. for (size_t i = 0; i < types; ++i) { auto size = kEventTimeLists[i]; if (list_key > 0 && i != list_key) { // A specific list_type was requested, only return bins of this key. continue; } std::string time_list; auto list_type = boost::lexical_cast<std::string>(size); auto status = db->Get(kEvents, index_key + "." + list_type, time_list); if (time_list.length() == 0) { // No events in this binning size. return indexes; } if (list_key == 0 && i == (types - 1) && types > 1) { // Relax the requested start/stop bounds. if (start != start_max) { start = (start / size) * size; start_max = ((start / size) + 1) * size; if (start_max < stop) { start_max = start + kEventTimeLists[types - 2]; } } if (stop != stop_min) { stop = ((stop / size) + 1) * size; stop_min = (stop / size) * size; if (stop_min > start) { stop_min = stop_min - kEventTimeLists[types - 1]; } } } else if (list_key > 0 || types == 1) { // Relax the requested bounds to fit the requested/only index. start = (start / size) * size; start_max = ((start_max / size) + 1) * size; } // (1) The first iteration will have 1 range (start to start_max=stop). // (2) Intermediate iterations will have 2 (start-start_max, stop-stop_min). // For each iteration the range collapses based on the coverage using // the first bin's start time and the last bin's stop time. // (3) The last iteration's range includes relaxed bounds outside the // requested start to stop range. std::vector<std::string> all_bins, bins, expirations; boost::split(all_bins, time_list, boost::is_any_of(",")); for (const auto& bin : all_bins) { // Bins are identified by the binning size step. auto step = boost::lexical_cast<EventTime>(bin); // Check if size * step -> size * (step + 1) is within a range. int bin_start = size * step, bin_stop = size * (step + 1); if (expire_events_ && expire_time_ > 0) { if (bin_stop <= expire_time_) { expirations.push_back(bin); } else if (bin_start < expire_time_) { expireRecords(list_type, bin, false); } } if (bin_start >= start && bin_stop <= start_max) { bins.push_back(bin); } else if ((bin_start >= stop_min && bin_stop <= stop) || stop == 0) { bins.push_back(bin); } } // Rewrite the index lists and delete each expired item. if (expirations.size() > 0) { expireIndexes(list_type, all_bins, expirations); } if (bins.size() != 0) { // If more precision was achieved though this list's binning. local_start = boost::lexical_cast<EventTime>(bins.front()) * size; start_max = (local_start < start_max) ? local_start : start_max; local_stop = (boost::lexical_cast<EventTime>(bins.back()) + 1) * size; stop_min = (local_stop < stop_min) ? local_stop : stop_min; } for (const auto& bin : bins) { indexes.insert(list_type + "." + bin); } if (start == start_max && stop == stop_min) { break; } } // Update the new time that events expire to now - expiry. return indexes; }