aweisberg commented on code in PR #4042:
URL: https://github.com/apache/cassandra/pull/4042#discussion_r2114447024


##########
src/java/org/apache/cassandra/utils/IntervalTree.java:
##########
@@ -468,46 +749,140 @@ else if (center.compareTo(searchInterval.max) > 0)
                     right.searchInternal(searchInterval, results);
             }
         }
-    }
 
-    private class TreeIterator extends AbstractIterator<I>
-    {
-        private final Deque<IntervalNode> stack = new 
ArrayDeque<IntervalNode>();
-        private Iterator<I> current;
 
-        TreeIterator(IntervalNode node)
+        private IntervalNode replace(IntervalNode node, List<Pair<I, I>> 
replacements)
         {
-            super();
-            gotoMinOf(node);
-        }
+            if (node == null || replacements.isEmpty())
+                return node;
 
-        protected I computeNext()
-        {
-            while (true)
-            {
-                if (current != null && current.hasNext())
-                    return current.next();
+            List<Pair<I, I>> leftSegment = new ArrayList<>();
+            List<Pair<I, I>> rightSegment = new ArrayList<>();
+            List<I> newIntersectsLeft = null;
+            List<I> newIntersectsRight = null;
+            int updated = 0;
 
-                IntervalNode node = stack.pollFirst();
-                if (node == null)
-                    return endOfData();
+            for (Pair<I, I> entry : replacements)
+            {
+                I intervalToRemove = entry.left;
+                I intervalToAdd = entry.right;
+                if (node.center.compareTo(intervalToRemove.min) < 0)
+                {
+                    rightSegment.add(entry);
+                }
+                else if (node.center.compareTo(intervalToRemove.max) > 0)
+                {
+                    leftSegment.add(entry);
+                }
+                else
+                {
+                    // only init once if any interval resides in current node
+                    if (newIntersectsLeft == null)
+                    {
+                        newIntersectsLeft = new 
ArrayList<>(node.intersectsLeft);
+                        newIntersectsRight = new 
ArrayList<>(node.intersectsRight);
+                    }
+                    boolean leftUpdated = false;
+                    boolean rightUpdated = false;
+
+                    int i = Interval.<C, 
D>minOrdering().binarySearchAsymmetric(node.intersectsLeft, 
intervalToRemove.min, Op.CEIL);
+                    while (i < node.intersectsLeft.size())
+                    {
+                        if 
(node.intersectsLeft.get(i).equals(intervalToRemove))
+                        {
+                            newIntersectsLeft.set(i, intervalToAdd);
+                            leftUpdated = true;
+                            break;
+                        }
+                        i++;
+                    }
+
+                    int j = Interval.<C, 
D>maxOrdering().binarySearchAsymmetric(node.intersectsRight, 
intervalToRemove.max, Op.CEIL);
+                    while (j < node.intersectsRight.size())
+                    {
+                        if 
(node.intersectsRight.get(j).equals(intervalToRemove))
+                        {
+                            newIntersectsRight.set(j, intervalToAdd);
+                            rightUpdated = true;
+                            break;
+                        }
+                        j++;
+                    }
+                    assert leftUpdated && rightUpdated : "leftupdated = " + 
leftUpdated + ", rightupdated = " + rightUpdated;
+                    updated++;
+                }
+            }
 
-                current = node.intersectsLeft.iterator();
+            assert leftSegment.size() + rightSegment.size() + updated == 
replacements.size() :
+            "leftSegment size (" + leftSegment.size() + ") + rightSegment size 
(" + rightSegment.size() +
+            ") + updated (" + updated + ") != replacementMap size (" + 
replacements.size() + ')';
+            return new IntervalNode(node.center,
+                                    node.low,
+                                    node.high,
+                                    newIntersectsLeft != null ? 
newIntersectsLeft : node.intersectsLeft,
+                                    newIntersectsRight != null ? 
newIntersectsRight : node.intersectsRight,
+                                    replace(node.left, leftSegment),
+                                    replace(node.right, rightSegment));
+        }
 
-                // We know this is the smaller not returned yet, but before 
doing
-                // its parent, we must do everyone on it's right.
-                gotoMinOf(node.right);
-            }
+        private IntervalNode add(Collection<I> intervals)
+        {
+            return add(this, intervals);
         }
 
-        private void gotoMinOf(IntervalNode node)
+        private IntervalNode add(IntervalNode root, Collection<I> intervals)
         {
-            while (node != null)
+            if (intervals.isEmpty())
+                return root;
+
+            if (root == null)
+            {
+                List<I> minSortedIntervals = new ArrayList<>(intervals);
+                Collections.sort(minSortedIntervals, Interval.minOrdering());
+                List<I> maxSortedIntervals = new ArrayList<>(intervals);
+                Collections.sort(maxSortedIntervals, Interval.maxOrdering());
+                return new IntervalNode(minSortedIntervals, 
maxSortedIntervals);
+            }
+
+            List<I> leftSegment = new ArrayList<>();
+            List<I> rightSegment = new ArrayList<>();
+            C newLow = root.low;
+            C newHigh = root.high;
+            List<I> newIntersectsLeft = new ArrayList<>(root.intersectsLeft);
+            List<I> newIntersectsRight = new ArrayList<>(root.intersectsRight);
+            for (I i : intervals)
             {
-                stack.offerFirst(node);
-                node = node.left;
+                newLow = newLow.compareTo(i.min) < 0 ? newLow : i.min;
+                newHigh = newHigh.compareTo(i.max) > 0 ? newHigh : i.max;
+                if (i.max.compareTo(root.center) < 0)
+                {
+                    leftSegment.add(i);
+                }
+                else if (i.min.compareTo(root.center) > 0)
+                {
+                    rightSegment.add(i);
+                }
+                else
+                {
+                    int leftIdx = Collections.binarySearch(newIntersectsLeft, 
i, Interval.minOrdering());

Review Comment:
   Asymmetric solves the problem of the search being on a list of elements that 
is not the same type as the key and doesn't compare all the fields. This is 
fine when building an entire tree from scratch, but for add/replace there was 
the issue of having to deal with duplicates which I recall not allowing.
   
   However identity for detecting duplicates doesn't use object identity it 
requires the comparator for the interval to enforce identity so you don't want 
to use the asymmetric search in that case because it won't tell you the correct 
position and if the interval is already there.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: pr-unsubscr...@cassandra.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: pr-unsubscr...@cassandra.apache.org
For additional commands, e-mail: pr-h...@cassandra.apache.org

Reply via email to