From 86bb1465e867d5d6af5506795b8e8ceace39cfbb Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Mon, 2 Dec 2019 21:52:19 -0600 Subject: [PATCH] getTracked does not need to read in entire database Related to issue #245. --- src/data.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/src/data.cpp b/src/data.cpp index 9677000d..19f763f4 100644 --- a/src/data.cpp +++ b/src/data.cpp @@ -24,6 +24,9 @@ // //////////////////////////////////////////////////////////////////////////////// +#include + +#include #include #include #include @@ -321,6 +324,19 @@ std::vector getAllInclusions (Database& database) return all; } +//////////////////////////////////////////////////////////////////////////////// +std::vector subset ( + const Interval& filter, + const std::deque & intervals) +{ + std::vector all; + for (auto& interval : intervals) + if (matchesFilter (interval, filter)) + all.push_back (interval); + + return all; +} + //////////////////////////////////////////////////////////////////////////////// std::vector subset ( const Interval& filter, @@ -573,8 +589,6 @@ std::vector getTracked ( const Rules& rules, Interval& filter) { - auto inclusions = getAllInclusions (database); - // Exclusions are only usable within a range, so if no filter range exists, // determine the infinite range starting at the first inclusion, i.e.: // @@ -583,9 +597,12 @@ std::vector getTracked ( // Avoid assigning a zero-width range - leave it unstarted instead. if (! filter.is_started ()) { - auto outer = outerRange (inclusions); - if (outer.total ()) - filter.setRange (outer); + auto begin = database.begin (); + auto end = database.end (); + if (begin != end) + { + filter.start = IntervalFactory::fromSerialization (*begin).start; + } // Use an infinite range instead of the last end date; this prevents // issues when there is an empty range [q, q) at the end of a filter @@ -593,11 +610,35 @@ std::vector getTracked ( filter.end = 0; } - std::vector intervals = inclusions; + int id_skip = 0; + std::deque intervals; + + auto it = database.rbegin (); + auto end = database.rend (); + for (; it != end; ++it) + { + Interval interval = IntervalFactory::fromSerialization(*it); + + // Since we are moving backwards, and the intervals are in sorted order, + // if the filter is after the interval, we know there will be no more + // matches + if (matchesFilter (interval, filter)) + { + intervals.push_front (interval); + } + else if (interval.start.toEpoch () >= filter.start.toEpoch ()) + { + ++id_skip; + } + else + { + break; + } + } if (! intervals.empty ()) { - auto latest = inclusions.back (); + auto latest = intervals.back (); if (latest.is_open ()) { @@ -625,7 +666,7 @@ std::vector getTracked ( // Assign an ID to each interval. for (unsigned int i = 0; i < intervals.size (); ++i) - intervals[i].id = intervals.size () - i; + intervals[i].id = intervals.size () - i + id_skip; debug (format ("Loaded {1} tracked intervals", intervals.size ())); return subset (filter, intervals);