/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.github.geophile.erdo.consolidate; import com.github.geophile.erdo.util.Interval; import java.util.*; import static com.github.geophile.erdo.consolidate.Consolidation.Element; // Make non-durable consolidation elements durable for the first time. This has to be done in // timestamp order. To do this find the maximal set of non-durable elements such that: // - The minimum timestamp is one greater than the maximum already durable timestamp. // - The sequence of timestamps has no holes. public class MakeDurableConsolidationPlanner extends ConsolidationPlanner { // ConsolidationPlanner interface @Override public boolean planConsolidation(Element newElement) { assert newElement == null : newElement; // Load a priority queue with (Interval, Element) for non-durable elements. List<Element> nonDurable = consolidationSet.nonDurable().availableForConsolidation(); if (nonDurable.isEmpty()) { consolidationElements = null; } else { PriorityQueue<IntervalAndOwner> intervals = new PriorityQueue<>(nonDurable.size()); for (Element element : nonDurable) { for (Interval interval : element.timestamps()) { intervals.add(new IntervalAndOwner(interval, element)); } } // Merge the intervals, stopping when a gap is found. A gap immediately following // the max durable timestamps is also grounds for stopping. As intervals are processed, // add the owning element to the consolidation candidates. long maxTimestampSoFar = maxDurableTimestamp(); Set<Element> consolidationElementSet = new HashSet<>(); IntervalAndOwner intervalAndOwner; while ((intervalAndOwner = intervals.poll()) != null && intervalAndOwner.min() == maxTimestampSoFar + 1) { consolidationElementSet.add(intervalAndOwner.owner()); maxTimestampSoFar = intervalAndOwner.max(); } // See if we have enough to bother writing to disk. long size = 0; for (Element element : consolidationElementSet) { size += element.sizeBytes(); } consolidationElements = size < minConsolidationSize ? null : new ArrayList<>(consolidationElementSet); } return consolidationElements != null; } @Override public List<Element> elementsToConsolidate() { return consolidationElements; } @Override public String type() { return "makeDurable"; } // MakeDurableConsolidationPlanner interface public static MakeDurableConsolidationPlanner newPlanner(ConsolidationSet consolidationSet) { return new MakeDurableConsolidationPlanner(consolidationSet); } // For use by this class private long maxDurableTimestamp() { long maxTimestamp = -1L; for (Element element : consolidationSet().durable().elements()) { long maxElementTimestamp = element.timestamps().maxTimestamp(); if (maxElementTimestamp > maxTimestamp) { maxTimestamp = maxElementTimestamp; } } return maxTimestamp; } private MakeDurableConsolidationPlanner(ConsolidationSet consolidationSet) { super(consolidationSet, false, true); minConsolidationSize = consolidationSet.configuration().consolidationMinSizeBytes(); } // Object state private final long minConsolidationSize; private List<Element> consolidationElements; // Inner classes private static class IntervalAndOwner extends Interval { IntervalAndOwner(Interval interval, Element owner) { super(interval.min(), interval.max()); this.owner = owner; } Element owner() { return owner; } private final Element owner; } }