@Override public SimplifiedIntervalList getVolatileIntervals() { return new SimplifiedIntervalList(); } }
/** * Back elements off the list until the insertion is at the correct endpoint of the list and then merge and append * the original contents of the list back in. * * @param interval The interval to be merged and added */ private void mergeInner(Interval interval) { Interval previous = peekLast(); LinkedList<Interval> buffer = new LinkedList<>(); while (previous != null && interval.getStart().isBefore(previous.getStart())) { buffer.addFirst(previous); removeLast(); previous = peekLast(); } appendWithMerge(interval); buffer.stream().forEach(this::appendWithMerge); }
/** * Takes one or more lists of intervals, and combines them into a single, sorted list with the minimum number of * intervals needed to capture exactly the same instants as the original intervals. * <p> * If any subintervals of the input collection abut or overlap they will be replaced with a single, combined * interval. * <p> * Examples: * <ul> * <li>['2014/2017', '2015/2020'] will combine into ['2014/2020'] * <li>['2015/2016', '2016/2017'] will combine into ['2015/2017] * <li>['2015/2016', '2013/2014'] will sort into ['2013/2014', '2015/2016'] * <li>['2015/2015', '2015/2016', '2012/2013'] will sort and combine to ['2012/2013', '2015/2016'] * </ul> * @param intervals The collection(s) of intervals being collated * * @return A single list of sorted intervals simplified to the smallest number of intervals able to describe the * duration */ @SafeVarargs public static SimplifiedIntervalList simplifyIntervals(Collection<Interval>... intervals) { Stream<Interval> allIntervals = Stream.empty(); for (Collection<Interval> intervalCollection : intervals) { allIntervals = Stream.concat(allIntervals, intervalCollection.stream()); } return allIntervals .sorted(IntervalStartComparator.INSTANCE::compare) .collect(getCollector()); }
/** * Sum the length of the intervals in this collection. * * @param intervals A collection of time intervals * * @return The total duration of all the intervals */ public static long getTotalDuration(Collection<Interval> intervals) { return new SimplifiedIntervalList(intervals).stream() .map(Interval::toDuration) .mapToLong(Duration::getMillis) .sum(); }
/** * Calculate the missing intervals based on the subpartitions availability. * formula is: * Union(subpart availabilitiy) - Union(subpart missing intervals) * * @param constraint The filtering constraint * * @return The intervals which are available for the given constraint */ private SimplifiedIntervalList mergeAvailabilities(PhysicalDataSourceConstraint constraint) { SimplifiedIntervalList unionOfAvailableIntervals = new SimplifiedIntervalList(); SimplifiedIntervalList unionOfMissingIntervals = new SimplifiedIntervalList(); for (Availability availability : filteredAvailabilities(constraint).collect(Collectors.toSet())) { unionOfAvailableIntervals = unionOfAvailableIntervals.union(availability.getAvailableIntervals(constraint)); unionOfMissingIntervals = unionOfMissingIntervals.union( getBoundedMissingIntervalsWithConstraint(availability, constraint) ); } return unionOfAvailableIntervals.subtract(unionOfMissingIntervals); }
if (isEmpty()) { addLast(interval); return; final Interval previous = peekLast(); mergeInner(interval); return; addLast(interval); return; removeLast(); Interval newEnd = new Interval( Math.min(previous.getStartMillis(), interval.getStartMillis()), Math.max(previous.getEndMillis(), interval.getEndMillis()) ); addLast(newEnd);
@Override public SimplifiedIntervalList getVolatileIntervals( Granularity granularity, List<Interval> intervals, PhysicalTable factSource ) { SimplifiedIntervalList simplifiedIntervals = new SimplifiedIntervalList(intervals); SimplifiedIntervalList volatileIntervals = IntervalUtils.collectBucketedIntervalsIntersectingIntervalList( intervalsFunctions.getOrDefault(factSource.getName(), defaultIntervals).getVolatileIntervals(), simplifiedIntervals, granularity ); if (granularity instanceof AllGranularity && !volatileIntervals.isEmpty()) { volatileIntervals = simplifiedIntervals; } LOG.trace("Volatile intervals: {} for grain {}", volatileIntervals, granularity); return volatileIntervals; } }
/** * Return the intersection of all subintervals in two interval lists. * * @param that A simplified list of intervals * * @return A new simplified interval list whose intervals are all subintervals of this and that. */ public SimplifiedIntervalList intersect(SimplifiedIntervalList that) { Iterator<Interval> theseIntervals = this.iterator(); Iterator<Interval> thoseIntervals = that.iterator(); Interval thisCurrent = getNextIfAvailable.apply(theseIntervals); Interval thatCurrent = getNextIfAvailable.apply(thoseIntervals); List<Interval> collected = new ArrayList<>(); while (thisCurrent != null && thatCurrent != null) { if (thisCurrent.overlaps(thatCurrent)) { collected.add(thisCurrent.overlap(thatCurrent)); } if (thisCurrent.isBefore(thatCurrent.getEnd())) { thisCurrent = getNextIfAvailable.apply(theseIntervals); } else { thatCurrent = getNextIfAvailable.apply(thoseIntervals); } } return new SimplifiedIntervalList(collected); }
intervals.add(new Interval(jsonNode.asText())); SimplifiedIntervalList druidIntervals = new SimplifiedIntervalList(intervals); return druidIntervals.intersect( query.getDataSource().getPhysicalTable().getAvailableIntervals() );
/** * Calculates the MISSING intervals for a given a availability and datasource constraint. * * @param availability The availability to find the missing intervals for * @param constraint The constraint for the query * @return the missing intervals */ private SimplifiedIntervalList getBoundedMissingIntervalsWithConstraint( Availability availability, PhysicalDataSourceConstraint constraint ) { SimplifiedIntervalList availableIntervals = availability.getAvailableIntervals(constraint); DateTime expectedStart = availability.getExpectedStartDate(constraint).orElse(Availability.DISTANT_PAST); DateTime expectedEnd = availability.getExpectedEndDate(constraint).orElse(Availability.FAR_FUTURE); return new SimplifiedIntervalList(Collections.singleton(new Interval(expectedStart, expectedEnd))) .subtract(availableIntervals); }
if (granularity instanceof AllGranularity && !missingIntervals.isEmpty()) { missingIntervals = requestedIntervals;
/** * Remove result records which are missing and not marked as volatile. * Any bucket which is partially volatile is not removed. In the case of the All granularity, all data is * considered to be in a single bucket. * * @param result The result row being transformed * @param schema The schema for that result * @return Null if the bucket this result falls in is missing but not volatile */ @Override public Result map(Result result, ResultSetSchema schema) { Granularity grain = schema.getGranularity(); if (grain.equals(AllGranularity.INSTANCE)) { return ! volatileIntervalSupply.get().isEmpty() || missingIntervals.isEmpty() ? result : null; } // Currently any Granularity which isn't 'ALL' must currently be a TimeGrain Interval resultInterval = new Interval(result.getTimeStamp(), ((TimeGrain) grain).getPeriod()); return getMissingNotVolatile().stream().anyMatch((it) -> it.overlaps(resultInterval)) ? null : result; }
/** * Bind the query interval string to a list of intervals. * * @param intervalsName The query string describing the intervals * @param granularity The granularity for this request * @param timeZone The time zone to evaluate interval timestamps in * * @return A bound list of intervals for the query */ protected List<Interval> bindIntervals(String intervalsName, Granularity granularity, DateTimeZone timeZone) { DateTimeFormatter dateTimeFormatter = generateDateTimeFormatter(timeZone); List<Interval> result; if (BardFeatureFlag.CURRENT_MACRO_USES_LATEST.isOn()) { SimplifiedIntervalList availability = TableUtils.logicalTableAvailability(getTable()); DateTime adjustedNow = new DateTime(); if (! availability.isEmpty()) { DateTime firstUnavailable = availability.getLast().getEnd(); if (firstUnavailable.isBeforeNow()) { adjustedNow = firstUnavailable; } } result = generateIntervals(adjustedNow, intervalsName, granularity, dateTimeFormatter); } else { result = generateIntervals(intervalsName, granularity, dateTimeFormatter); } return result; }
@Override public Iterator<Interval> intervalsIterator(SimplifiedIntervalList intervals) { return intervals.iterator(); }
new SimplifiedIntervalList(request.getIntervals()), request.getGranularity() ); if (! missingIntervals.isEmpty()) { ResponseContext responseContext = response.getResponseContext();
Iterator<Interval> theseIntervals = this.iterator(); Interval thisCurrent = getNextIfAvailable.apply(theseIntervals); return new SimplifiedIntervalList(); Iterator<Interval> thoseIntervals = that.iterator(); return new SimplifiedIntervalList(collected);
SimplifiedIntervalList requestIntervals = new SimplifiedIntervalList(requestConstraint.getIntervals()); Granularity apiRequestGranularity = requestConstraint.getRequestGranularity(); return IntervalUtils.getTotalDuration(tableAvailability.intersect(volatilePartialRequestIntervals));
/** * A request is cacheable if it does not refer to partial data. * * @return whether request can be cached */ private boolean isCacheable() { SimplifiedIntervalList missingIntervals = getPartialIntervalsWithDefault(getResponseContext()); SimplifiedIntervalList volatileIntervals = getVolatileIntervalsWithDefault(getResponseContext()); return missingIntervals.isEmpty() && volatileIntervals.isEmpty(); } }
/** * Constructor to build a predicate that applies an arbitrary predicate to not-before intervals from the * iterator. * * @param supplyList The SimplifiedList of intervals to test the predicate against * @param testPredicate The predicate to use when testing an interval against the supply * @param defaultValue The value for the test if no comparison interval can be found in the list. */ public SkippingIntervalPredicate( SimplifiedIntervalList supplyList, BiPredicate<Interval, Interval> testPredicate, boolean defaultValue ) { this.supply = supplyList.iterator(); this.testPredicate = testPredicate; this.defaultValue = defaultValue; activeInterval = null; if (supply.hasNext()) { activeInterval = supply.next(); } }
/** * Return the volatile intervals from the context. * * @param context The RequestContext object containing the volatile intervals if any * * @return the volatile intervals from the request or an empty list */ public static SimplifiedIntervalList getVolatileIntervalsWithDefault(Map<String, Serializable> context) { return new SimplifiedIntervalList( (Collection<Interval>) context.computeIfAbsent( VOLATILE_INTERVALS_CONTEXT_KEY.getName(), (ignored) -> new SimplifiedIntervalList() ) ); } }