|
23 | 23 | import org.junit.Test;
|
24 | 24 |
|
25 | 25 | import com.datastax.driver.core.ResultSet;
|
| 26 | +import com.datastax.driver.core.exceptions.ReadFailureException; |
26 | 27 | import org.apache.cassandra.db.marshal.Int32Type;
|
27 | 28 | import org.apache.cassandra.index.sai.IndexContext;
|
28 | 29 | import org.apache.cassandra.index.sai.SAITester;
|
29 | 30 | import org.apache.cassandra.index.sai.disk.v1.kdtree.NumericIndexWriter;
|
| 31 | +import org.apache.cassandra.inject.ActionBuilder; |
| 32 | +import org.apache.cassandra.inject.Expression; |
| 33 | +import org.apache.cassandra.inject.Injection; |
| 34 | +import org.apache.cassandra.inject.Injections; |
| 35 | +import org.apache.cassandra.inject.InvokePointBuilder; |
30 | 36 |
|
31 | 37 | import static org.junit.Assert.assertEquals;
|
| 38 | +import static org.junit.Assert.assertThrows; |
32 | 39 |
|
33 | 40 | public class FlushingTest extends SAITester
|
34 | 41 | {
|
@@ -84,4 +91,38 @@ public void testFlushingOverwriteDelete() throws Throwable
|
84 | 91 |
|
85 | 92 | assertIndexFilesInToc(indexFiles());
|
86 | 93 | }
|
| 94 | + |
| 95 | + @Test |
| 96 | + public void testMemtableIndexFlushFailure() throws Throwable |
| 97 | + { |
| 98 | + Injection failMemtableComplete = Injections.newCustom("FailMemtableIndexWriterComplete") |
| 99 | + .add(InvokePointBuilder.newInvokePoint() |
| 100 | + .onClass("org.apache.cassandra.index.sai.disk.v1.MemtableIndexWriter") |
| 101 | + .onMethod("complete", "com.google.common.base.Stopwatch") |
| 102 | + ) |
| 103 | + .add(ActionBuilder.newActionBuilder().actions() |
| 104 | + .doThrow(java.io.IOException.class, Expression.quote("Byteman-injected fault in MemtableIndexWriter.complete")) |
| 105 | + ) |
| 106 | + .build(); |
| 107 | + Injections.inject(failMemtableComplete); |
| 108 | + |
| 109 | + createTable(CREATE_TABLE_TEMPLATE); |
| 110 | + createIndex(String.format(CREATE_INDEX_TEMPLATE, "v1")); |
| 111 | + |
| 112 | + String pkValue = "key_bm_flush_fail"; |
| 113 | + int indexedValue = 456; |
| 114 | + |
| 115 | + execute("INSERT INTO %s (id1, v1) VALUES (?, ?)", pkValue, indexedValue); |
| 116 | + |
| 117 | + // The Byteman rule will cause the SAI part of the flush to fail |
| 118 | + assertThrows(RuntimeException.class, this::flush); |
| 119 | + |
| 120 | + // Assert that the index is still queryable for the inserted data despite the injected fault. |
| 121 | + ResultSet indexQueryResults = executeNet("SELECT id1 FROM %s WHERE v1 = ?", indexedValue); |
| 122 | + assertEquals("The index should be still usable despite flush failure", 1, indexQueryResults.all().size()); |
| 123 | + |
| 124 | + // Assert that the table is still queryable by primary key. |
| 125 | + ResultSet pkQueryResults = executeNet("SELECT v1 FROM %s WHERE id1 = ?", pkValue); |
| 126 | + assertEquals("Table should still be queryable by primary key", 1, pkQueryResults.all().size()); |
| 127 | + } |
87 | 128 | }
|
0 commit comments