|
20 | 20 |
|
21 | 21 | import java.util.ArrayList;
|
22 | 22 | import java.util.Collection;
|
| 23 | +import java.util.Collections; |
23 | 24 | import java.util.List;
|
24 | 25 | import java.util.concurrent.ExecutionException;
|
25 | 26 | import java.util.concurrent.ExecutorService;
|
26 | 27 | import java.util.concurrent.Executors;
|
| 28 | +import java.util.concurrent.Future; |
27 | 29 |
|
28 | 30 | import com.google.common.collect.Lists;
|
| 31 | +import org.junit.Assert; |
29 | 32 | import org.junit.Test;
|
30 | 33 | import org.junit.runner.RunWith;
|
| 34 | + |
| 35 | +import org.apache.cassandra.config.DatabaseDescriptor; |
| 36 | +import org.apache.cassandra.cql3.QueryProcessor; |
| 37 | +import org.apache.cassandra.db.ColumnFamilyStore; |
31 | 38 | import org.apache.cassandra.db.compaction.CompactionInterruptedException;
|
32 | 39 | import org.apache.cassandra.db.compaction.CompactionManager;
|
| 40 | +import org.apache.cassandra.dht.ByteOrderedPartitioner; |
33 | 41 | import org.apache.cassandra.dht.Range;
|
34 | 42 | import org.apache.cassandra.dht.Token;
|
35 | 43 | import org.apache.cassandra.io.sstable.format.SSTableReader;
|
| 44 | +import org.apache.cassandra.locator.InetAddressAndPort; |
36 | 45 | import org.apache.cassandra.locator.RangesAtEndpoint;
|
37 | 46 | import org.apache.cassandra.locator.Replica;
|
38 | 47 | import org.apache.cassandra.utils.TimeUUID;
|
| 48 | +import org.apache.cassandra.service.ActiveRepairService; |
| 49 | +import org.apache.cassandra.streaming.PreviewKind; |
| 50 | +import org.apache.cassandra.utils.ByteBufferUtil; |
| 51 | +import org.assertj.core.api.Assertions; |
39 | 52 | import org.jboss.byteman.contrib.bmunit.BMRule;
|
40 | 53 | import org.jboss.byteman.contrib.bmunit.BMRules;
|
41 | 54 | import org.jboss.byteman.contrib.bmunit.BMUnitRunner;
|
42 | 55 |
|
| 56 | +import static org.apache.cassandra.db.ColumnFamilyStore.FlushReason.UNIT_TESTS; |
43 | 57 | import static org.junit.Assert.assertEquals;
|
44 | 58 | import static org.junit.Assert.assertTrue;
|
45 | 59 | import static org.junit.Assert.fail;
|
@@ -97,4 +111,58 @@ private static RangesAtEndpoint atEndpoint(Collection<Range<Token>> full, Collec
|
97 | 111 |
|
98 | 112 | return builder.build();
|
99 | 113 | }
|
| 114 | + |
| 115 | + @BMRules(rules = { @BMRule(name = "Abort anti-compaction after first call to onOperationStart", |
| 116 | + targetClass = "CompactionManager", |
| 117 | + targetMethod = "antiCompactGroup", |
| 118 | + condition = "not flagged(\"done\")", |
| 119 | + targetLocation = "AFTER INVOKE compactionRateLimiterAcquire", |
| 120 | + action = "org.apache.cassandra.db.compaction.CompactionManager.instance.stopCompaction(\"ANTICOMPACTION\");") } ) |
| 121 | + @Test |
| 122 | + public void testStopAntiCompaction() |
| 123 | + { |
| 124 | + Assert.assertSame(ByteOrderedPartitioner.class, DatabaseDescriptor.getPartitioner().getClass()); |
| 125 | + cfs.disableAutoCompaction(); |
| 126 | + |
| 127 | + // create 2 sstables, one that will be split, and another that will be moved |
| 128 | + for (int i = 0; i < 10; i++) |
| 129 | + { |
| 130 | + QueryProcessor.executeInternal(String.format("INSERT INTO %s.%s (k, v) VALUES (?, ?)", ks, tbl), i, i); |
| 131 | + } |
| 132 | + cfs.forceBlockingFlush(UNIT_TESTS); |
| 133 | + for (int i = 10; i < 20; i++) |
| 134 | + { |
| 135 | + QueryProcessor.executeInternal(String.format("INSERT INTO %s.%s (k, v) VALUES (?, ?)", ks, tbl), i, i); |
| 136 | + } |
| 137 | + cfs.forceBlockingFlush(UNIT_TESTS); |
| 138 | + |
| 139 | + assertEquals(2, cfs.getLiveSSTables().size()); |
| 140 | + assertEquals(0, cfs.getLiveSSTables().stream().filter(SSTableReader::isPendingRepair).count()); |
| 141 | + |
| 142 | + Token left = ByteOrderedPartitioner.instance.getToken(ByteBufferUtil.bytes(5)); |
| 143 | + Token right = ByteOrderedPartitioner.instance.getToken(ByteBufferUtil.bytes(15)); |
| 144 | + List<Range<Token>> ranges = Collections.singletonList(new Range<>(left, right)); |
| 145 | + List<ColumnFamilyStore> tables = Collections.singletonList(cfs); |
| 146 | + |
| 147 | + // create a repair session so the anti-compaction job can find it |
| 148 | + TimeUUID sessionID = TimeUUID.Generator.nextTimeUUID(); |
| 149 | + ActiveRepairService.instance().registerParentRepairSession(sessionID, InetAddressAndPort.getLocalHost(), tables, ranges, true, 1, true, PreviewKind.NONE); |
| 150 | + |
| 151 | + ExecutorService executor = Executors.newSingleThreadExecutor(); |
| 152 | + try |
| 153 | + { |
| 154 | + PendingAntiCompaction pac = new PendingAntiCompaction(sessionID, tables, atEndpoint(ranges, NO_RANGES), executor, () -> false); |
| 155 | + Future<?> future = pac.run(); |
| 156 | + Assertions.assertThatThrownBy(future::get) |
| 157 | + .hasCauseInstanceOf(CompactionInterruptedException.class) |
| 158 | + .hasMessageContaining("Compaction interrupted"); |
| 159 | + } |
| 160 | + finally |
| 161 | + { |
| 162 | + executor.shutdown(); |
| 163 | + } |
| 164 | + |
| 165 | + assertEquals(2, cfs.getLiveSSTables().size()); |
| 166 | + assertEquals(0, cfs.getLiveSSTables().stream().filter(SSTableReader::isPendingRepair).count()); |
| 167 | + } |
100 | 168 | }
|
0 commit comments