Skip to content

Commit 7e32d92

Browse files
committed
Fix/Improve IntervalBTree
- Use AsymmetricComparator for seeking - Reimplement AbstractTransformer for more efficienct operation when only transforming a subset (i.e. Subtraction) - Reuse source node IntervalMaxIndex calculations for first branch level (to save iterating leaves) patch by Benedict; reviewed by Alex Petrov for CASSANDRA-20756
1 parent 92cbde1 commit 7e32d92

File tree

8 files changed

+1028
-586
lines changed

8 files changed

+1028
-586
lines changed

src/java/org/apache/cassandra/service/accord/CommandsForRanges.java

Lines changed: 18 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,21 @@
4848
import accord.primitives.TxnId;
4949
import accord.primitives.Unseekable;
5050
import accord.primitives.Unseekables;
51+
import accord.utils.AsymmetricComparator;
5152
import accord.utils.Invariants;
53+
import accord.utils.SymmetricComparator;
5254
import accord.utils.UnhandledEnum;
5355
import org.agrona.collections.Object2ObjectHashMap;
5456
import org.apache.cassandra.service.accord.api.TokenKey;
5557
import org.apache.cassandra.utils.btree.IntervalBTree;
5658

5759
import static accord.local.CommandSummaries.SummaryStatus.NOT_DIRECTLY_WITNESSED;
58-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.intervalEndWithKeyEnd;
59-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.intervalEndWithKeyStart;
60-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.intervalStartWithKeyEnd;
61-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.intervalStartWithKeyStart;
62-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.keyEndWithIntervalEnd;
63-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.keyEndWithIntervalStart;
64-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.keyStartWithIntervalEnd;
65-
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndKeyComparatorHelper.keyStartWithIntervalStart;
60+
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndHelper.endWithStart;
61+
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndHelper.keyEndWithStart;
62+
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndHelper.keyStartWithEnd;
63+
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndHelper.keyStartWithStart;
64+
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndHelper.startWithEnd;
65+
import static org.apache.cassandra.utils.btree.IntervalBTree.InclusiveEndHelper.startWithStart;
6666

6767
// TODO (expected): move to accord-core, merge with existing logic there
6868
public class CommandsForRanges extends TreeMap<Timestamp, Summary> implements CommandSummaries.ByTxnIdSnapshot
@@ -101,47 +101,18 @@ public int compareTo(TxnIdInterval that)
101101
static class IntervalComparators implements IntervalBTree.IntervalComparators<TxnIdInterval>
102102
{
103103
@Override public Comparator<TxnIdInterval> totalOrder() { return TxnIdInterval::compareTo; }
104-
@Override public Comparator<TxnIdInterval> startWithStartComparator() { return (a, b) -> a.start.compareTo(b.start); }
105-
@Override public Comparator<TxnIdInterval> startWithEndComparator() { return (a, b) -> a.start.compareTo(b.end); }
106-
@Override public Comparator<TxnIdInterval> endWithStartComparator() { return (a, b) -> a.end.compareTo(b.start); }
107-
@Override public Comparator<TxnIdInterval> endWithEndComparator() { return (a, b) -> a.end.compareTo(b.end); }
104+
@Override public Comparator<TxnIdInterval> endWithEndSorter() { return (a, b) -> a.end.compareTo(b.end); }
105+
106+
@Override public SymmetricComparator<TxnIdInterval> startWithStartSeeker() { return (a, b) -> startWithStart(a.start.compareTo(b.start)); }
107+
@Override public SymmetricComparator<TxnIdInterval> startWithEndSeeker() { return (a, b) -> startWithEnd(a.start.compareTo(b.end)); }
108+
@Override public SymmetricComparator<TxnIdInterval> endWithStartSeeker() { return (a, b) -> endWithStart(a.end.compareTo(b.start)); }
108109
}
109110

110-
static class IntervalKeyComparators implements IntervalBTree.IntervalComparators<Object>
111+
static class IntervalKeyComparators implements IntervalBTree.WithIntervalComparators<RoutingKey, TxnIdInterval>
111112
{
112-
@Override public Comparator<Object> totalOrder() { throw new UnsupportedOperationException(); }
113-
114-
@Override
115-
public Comparator<Object> startWithStartComparator()
116-
{
117-
return (a, b) -> a.getClass() == TxnIdInterval.class
118-
? intervalStartWithKeyStart(((TxnIdInterval) a).start.compareTo((RoutingKey)b))
119-
: keyStartWithIntervalStart(((RoutingKey)a).compareTo(((TxnIdInterval)b).start));
120-
}
121-
122-
@Override
123-
public Comparator<Object> startWithEndComparator()
124-
{
125-
return (a, b) -> a.getClass() == TxnIdInterval.class
126-
? intervalStartWithKeyEnd(((TxnIdInterval)a).start.compareTo((RoutingKey)b))
127-
: keyStartWithIntervalEnd(((RoutingKey)a).compareTo(((TxnIdInterval)b).end));
128-
}
129-
130-
@Override
131-
public Comparator<Object> endWithStartComparator()
132-
{
133-
return (a, b) -> a.getClass() == TxnIdInterval.class
134-
? intervalEndWithKeyStart(((TxnIdInterval)a).end.compareTo((RoutingKey)b))
135-
: keyEndWithIntervalStart(((RoutingKey)a).compareTo(((TxnIdInterval)b).start));
136-
}
137-
138-
@Override
139-
public Comparator<Object> endWithEndComparator()
140-
{
141-
return (a, b) -> a.getClass() == TxnIdInterval.class
142-
? intervalEndWithKeyEnd(((TxnIdInterval)a).end.compareTo((RoutingKey)b))
143-
: keyEndWithIntervalEnd(((RoutingKey)a).compareTo(((TxnIdInterval)b).end));
144-
}
113+
@Override public AsymmetricComparator<RoutingKey, TxnIdInterval> startWithStartSeeker() { return (a, b) -> keyStartWithStart(a.compareTo(b.start));}
114+
@Override public AsymmetricComparator<RoutingKey, TxnIdInterval> startWithEndSeeker() { return (a, b) -> keyStartWithEnd(a.compareTo(b.end)); }
115+
@Override public AsymmetricComparator<RoutingKey, TxnIdInterval> endWithStartSeeker() { return (a, b) -> keyEndWithStart(a.compareTo(b.start)); }
145116
}
146117

147118
public CommandsForRanges(Map<? extends Timestamp, ? extends Summary> m)
@@ -224,7 +195,7 @@ static Object[] toMap(TxnId txnId, RangeRoute route)
224195
case 1: return IntervalBTree.singleton(new TxnIdInterval(route.get(0), txnId));
225196
default:
226197
{
227-
try (IntervalBTree.FastInteralTreeBuilder<TxnIdInterval> builder = IntervalBTree.fastBuilder(COMPARATORS.endWithEndComparator()))
198+
try (IntervalBTree.FastIntervalTreeBuilder<TxnIdInterval> builder = IntervalBTree.fastBuilder(COMPARATORS))
228199
{
229200
for (int i = 0 ; i < size ; ++i)
230201
builder.add(new TxnIdInterval(route.get(i), txnId));

src/java/org/apache/cassandra/utils/IntervalTree.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public class IntervalTree<C extends Comparable<? super C>, D extends Comparable<
7575
private final I[] intervalsByMaxOrder;
7676

7777
@SuppressWarnings("unchecked")
78-
protected IntervalTree(Collection<I> intervals)
78+
public IntervalTree(Collection<I> intervals)
7979
{
8080
this.modCount = 0;
8181
if (intervals == null || intervals.isEmpty())

0 commit comments

Comments
 (0)