public void prepare(ColumnFamilyStore cfs) { if (tree.partitioner() instanceof RandomPartitioner) { // You can't beat an even tree distribution for md5 tree.init(); } else { List<DecoratedKey> keys = new ArrayList<DecoratedKey>(); for (DecoratedKey sample : cfs.keySamples(request.range)) { assert request.range.contains(sample.token) : "Token " + sample.token + " is not within range " + request.range; keys.add(sample); } if (keys.isEmpty()) { // use an even tree distribution tree.init(); } else { int numkeys = keys.size(); Random random = new Random(); // sample the column family using random keys from the index while (true) { DecoratedKey dk = keys.get(random.nextInt(numkeys)); if (!tree.split(dk.token)) break; } } } logger.debug("Prepared AEService tree of size " + tree.size() + " for " + request); ranges = tree.invalids(); }
@Test public void testSplitLimitSize() { mt = new MerkleTree(partitioner, RECOMMENDED_DEPTH, 2); assertTrue(mt.split(tok(4))); assertEquals(2, mt.size()); // should fail to split above maxsize assertFalse(mt.split(tok(2))); assertEquals(2, mt.size()); assertEquals(new Range(tok(4), tok(-1)), mt.get(tok(-1))); assertEquals(new Range(tok(-1), tok(4)), mt.get(tok(4))); }
@Test public void testSplitLimitDepth() { mt = new MerkleTree(partitioner, (byte) 2, Integer.MAX_VALUE); assertTrue(mt.split(tok(4))); assertTrue(mt.split(tok(2))); assertEquals(3, mt.size()); // should fail to split below hashdepth assertFalse(mt.split(tok(1))); assertEquals(3, mt.size()); assertEquals(new Range(tok(4), tok(-1)), mt.get(tok(-1))); assertEquals(new Range(tok(-1), tok(2)), mt.get(tok(2))); assertEquals(new Range(tok(2), tok(4)), mt.get(tok(4))); }
@Test public void testSplit() { // split the range (zero, zero] into: // (zero,four], (four,six], (six,seven] and (seven, zero] mt.split(tok(4)); mt.split(tok(6)); mt.split(tok(7)); assertEquals(4, mt.size()); assertEquals(new Range(tok(7), tok(-1)), mt.get(tok(-1))); assertEquals(new Range(tok(-1), tok(4)), mt.get(tok(3))); assertEquals(new Range(tok(-1), tok(4)), mt.get(tok(4))); assertEquals(new Range(tok(4), tok(6)), mt.get(tok(6))); assertEquals(new Range(tok(6), tok(7)), mt.get(tok(7))); // check depths assertEquals((byte) 1, mt.get(tok(4)).depth); assertEquals((byte) 2, mt.get(tok(6)).depth); assertEquals((byte) 3, mt.get(tok(7)).depth); assertEquals((byte) 3, mt.get(tok(-1)).depth); try { mt.split(tok(-1)); fail("Shouldn't be able to split outside the initial range."); } catch (AssertionError e) { // pass } }
@Test public void testCompact() { // (zero, one], (one,two], ... (seven, zero] mt.split(tok(4)); mt.split(tok(2)); mt.split(tok(6)); mt.split(tok(1)); mt.split(tok(3)); mt.split(tok(5)); mt.split(tok(7)); // compact (zero,two] and then (four,six] mt.compact(tok(1)); mt.compact(tok(5)); assertEquals(6, mt.size()); assertEquals(new Range(tok(-1), tok(2)), mt.get(tok(2))); assertEquals(new Range(tok(2), tok(3)), mt.get(tok(3))); assertEquals(new Range(tok(3), tok(4)), mt.get(tok(4))); assertEquals(new Range(tok(4), tok(6)), mt.get(tok(5))); assertEquals(new Range(tok(6), tok(7)), mt.get(tok(7))); assertEquals(new Range(tok(7), tok(-1)), mt.get(tok(-1))); // compacted ranges should be at depth 2, and the rest at 3 for (int i : new int[] {2, 6}) { assertEquals((byte) 2, mt.get(tok(i)).depth); } for (int i : new int[] {3, 4, 7, -1}) { assertEquals((byte) 3, mt.get(tok(i)).depth); } // compact (two,four] and then (six,zero] mt.compact(tok(3)); mt.compact(tok(7)); assertEquals(4, mt.size()); assertEquals(new Range(tok(-1), tok(2)), mt.get(tok(2))); assertEquals(new Range(tok(2), tok(4)), mt.get(tok(4))); assertEquals(new Range(tok(4), tok(6)), mt.get(tok(5))); assertEquals(new Range(tok(6), tok(-1)), mt.get(tok(-1))); for (int i : new int[] {2, 4, 5, -1}) { assertEquals((byte) 2, mt.get(tok(i)).depth); } // compact (zero,four] mt.compact(tok(2)); assertEquals(3, mt.size()); assertEquals(new Range(tok(-1), tok(4)), mt.get(tok(2))); assertEquals(new Range(tok(4), tok(6)), mt.get(tok(6))); assertEquals(new Range(tok(6), tok(-1)), mt.get(tok(-1))); // compact (four, zero] mt.compact(tok(6)); assertEquals(2, mt.size()); assertEquals(new Range(tok(-1), tok(4)), mt.get(tok(2))); assertEquals(new Range(tok(4), tok(-1)), mt.get(tok(6))); assertEquals((byte) 1, mt.get(tok(2)).depth); assertEquals((byte) 1, mt.get(tok(6)).depth); // compact (zero, zero] (the root) mt.compact(tok(4)); assertEquals(1, mt.size()); assertEquals(new Range(tok(-1), tok(-1)), mt.get(tok(-1))); assertEquals((byte) 0, mt.get(tok(-1)).depth); }