use of org.apache.cassandra.notifications.SSTableAddedNotification in project cassandra by apache.
the class LeveledCompactionStrategyTest method testNewRepairedSSTable.
@Test
public void testNewRepairedSSTable() throws Exception {
byte[] b = new byte[100 * 1024];
new Random().nextBytes(b);
// 100 KiB value, make it easy to have multiple files
ByteBuffer value = ByteBuffer.wrap(b);
// Enough data to have a level 1 and 2
int rows = 40;
int columns = 20;
// Adds enough data to trigger multiple sstable per level
for (int r = 0; r < rows; r++) {
UpdateBuilder update = UpdateBuilder.create(cfs.metadata(), String.valueOf(r));
for (int c = 0; c < columns; c++) update.newRow("column" + c).add("val", value);
update.applyUnsafe();
cfs.forceBlockingFlush();
}
waitForLeveling(cfs);
cfs.disableAutoCompaction();
while (CompactionManager.instance.isCompacting(Arrays.asList(cfs), (sstable) -> true)) Thread.sleep(100);
CompactionStrategyManager manager = cfs.getCompactionStrategyManager();
List<List<AbstractCompactionStrategy>> strategies = manager.getStrategies();
LeveledCompactionStrategy repaired = (LeveledCompactionStrategy) strategies.get(0).get(0);
LeveledCompactionStrategy unrepaired = (LeveledCompactionStrategy) strategies.get(1).get(0);
assertEquals(0, repaired.manifest.getLevelCount());
assertEquals(2, unrepaired.manifest.getLevelCount());
assertTrue(manager.getSSTableCountPerLevel()[1] > 0);
assertTrue(manager.getSSTableCountPerLevel()[2] > 0);
for (SSTableReader sstable : cfs.getLiveSSTables()) assertFalse(sstable.isRepaired());
int sstableCount = unrepaired.manifest.getSSTables().size();
// we only have unrepaired sstables:
assertEquals(sstableCount, cfs.getLiveSSTables().size());
SSTableReader sstable1 = unrepaired.manifest.getLevel(2).iterator().next();
SSTableReader sstable2 = unrepaired.manifest.getLevel(1).iterator().next();
sstable1.descriptor.getMetadataSerializer().mutateRepairMetadata(sstable1.descriptor, System.currentTimeMillis(), null, false);
sstable1.reloadSSTableMetadata();
assertTrue(sstable1.isRepaired());
manager.handleNotification(new SSTableRepairStatusChanged(Arrays.asList(sstable1)), this);
int repairedSSTableCount = repaired.manifest.getSSTables().size();
assertEquals(1, repairedSSTableCount);
// make sure the repaired sstable ends up in the same level in the repaired manifest:
assertTrue(repaired.manifest.getLevel(2).contains(sstable1));
// and that it is gone from unrepaired
assertFalse(unrepaired.manifest.getLevel(2).contains(sstable1));
unrepaired.removeSSTable(sstable2);
manager.handleNotification(new SSTableAddedNotification(singleton(sstable2), null), this);
assertTrue(unrepaired.manifest.getLevel(1).contains(sstable2));
assertFalse(repaired.manifest.getLevel(1).contains(sstable2));
}
use of org.apache.cassandra.notifications.SSTableAddedNotification in project cassandra by apache.
the class SecondaryIndexManagerTest method addingSSTablesMarksTheIndexAsBuilt.
@Test
public void addingSSTablesMarksTheIndexAsBuilt() throws Throwable {
String tableName = createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b))");
String indexName = createIndex("CREATE INDEX ON %s(c)");
waitForIndex(KEYSPACE, tableName, indexName);
assertMarkedAsBuilt(indexName);
ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
cfs.indexManager.markAllIndexesRemoved();
assertNotMarkedAsBuilt(indexName);
try (Refs<SSTableReader> sstables = Refs.ref(cfs.getSSTables(SSTableSet.CANONICAL))) {
cfs.indexManager.handleNotification(new SSTableAddedNotification(sstables, null), cfs.getTracker());
assertMarkedAsBuilt(indexName);
}
}
use of org.apache.cassandra.notifications.SSTableAddedNotification in project cassandra by apache.
the class SecondaryIndexManagerTest method cannotRebuildWhileAnSSTableBuildIsInProgress.
@Test
public void cannotRebuildWhileAnSSTableBuildIsInProgress() throws Throwable {
final String tableName = createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b))");
final String indexName = createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
final AtomicBoolean error = new AtomicBoolean();
// wait for index initialization and verify it's built:
waitForIndex(KEYSPACE, tableName, indexName);
assertMarkedAsBuilt(indexName);
// add sstables in another thread, but make it block:
TestingIndex.blockBuild();
Thread asyncBuild = new Thread(() -> {
ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
try (Refs<SSTableReader> sstables = Refs.ref(cfs.getSSTables(SSTableSet.CANONICAL))) {
cfs.indexManager.handleNotification(new SSTableAddedNotification(sstables, null), cfs.getTracker());
} catch (Throwable ex) {
error.set(true);
}
});
asyncBuild.start();
// wait for the build to block, so that we can proceed unblocking all further operations:
TestingIndex.waitBlockedOnBuild();
// do not block further builds:
TestingIndex.shouldBlockBuild = false;
// verify rebuilding the index before the previous index build task has finished fails
assertFalse(tryRebuild(indexName, false));
assertNotMarkedAsBuilt(indexName);
// check that the index is marked as built when the build finishes
TestingIndex.unblockBuild();
asyncBuild.join();
assertMarkedAsBuilt(indexName);
// now verify you can rebuild
assertTrue(tryRebuild(indexName, false));
assertMarkedAsBuilt(indexName);
}
use of org.apache.cassandra.notifications.SSTableAddedNotification in project cassandra by apache.
the class SecondaryIndexManagerTest method initializingIndexNotQueryableButMaybeNotWritableAfterPartialRebuild.
@Test
public void initializingIndexNotQueryableButMaybeNotWritableAfterPartialRebuild() throws Throwable {
TestingIndex.blockCreate();
String tableName = createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b))");
String defaultIndexName = createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
String readOnlyIndexName = createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c) USING '%s'", ReadOnlyOnFailureIndex.class.getName()));
String writeOnlyIndexName = createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c) USING '%s'", WriteOnlyOnFailureIndex.class.getName()));
// the index should never be queryable while the initialization hasn't finished
assertFalse(isQueryable(defaultIndexName));
assertFalse(isQueryable(readOnlyIndexName));
assertFalse(isQueryable(writeOnlyIndexName));
// the index should always we writable while the initialization hasn't finished
assertTrue(isWritable(defaultIndexName));
assertTrue(isWritable(readOnlyIndexName));
assertTrue(isWritable(writeOnlyIndexName));
// a failing partial build doesn't set the index as queryable, but might set it as not writable
TestingIndex.shouldFailBuild = true;
ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
try {
cfs.indexManager.handleNotification(new SSTableAddedNotification(cfs.getLiveSSTables(), null), this);
fail("Should have failed!");
} catch (Throwable ex) {
assertTrue(ex.getMessage().contains("configured to fail"));
}
assertFalse(isQueryable(defaultIndexName));
assertFalse(isQueryable(readOnlyIndexName));
assertFalse(isQueryable(writeOnlyIndexName));
assertTrue(isWritable(defaultIndexName));
assertFalse(isWritable(readOnlyIndexName));
assertTrue(isWritable(writeOnlyIndexName));
// a successful partial build doesn't set the index as queryable nor writable
TestingIndex.shouldFailBuild = false;
cfs.indexManager.handleNotification(new SSTableAddedNotification(cfs.getLiveSSTables(), null), this);
assertFalse(isQueryable(defaultIndexName));
assertFalse(isQueryable(readOnlyIndexName));
assertFalse(isQueryable(writeOnlyIndexName));
assertTrue(isWritable(defaultIndexName));
assertFalse(isWritable(readOnlyIndexName));
assertTrue(isWritable(writeOnlyIndexName));
// the index should be queryable once the initialization has finished
TestingIndex.unblockCreate();
waitForIndex(KEYSPACE, tableName, defaultIndexName);
assertTrue(isQueryable(defaultIndexName));
assertTrue(isQueryable(readOnlyIndexName));
assertTrue(isQueryable(writeOnlyIndexName));
assertTrue(isWritable(defaultIndexName));
assertTrue(isWritable(readOnlyIndexName));
assertTrue(isWritable(writeOnlyIndexName));
}
use of org.apache.cassandra.notifications.SSTableAddedNotification in project cassandra by apache.
the class SecondaryIndexManagerTest method addingSSTableWithBuildFailureWhileRebuildIsInProgress.
@Test
public void addingSSTableWithBuildFailureWhileRebuildIsInProgress() throws Throwable {
final String tableName = createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, b))");
final String indexName = createIndex(String.format("CREATE CUSTOM INDEX ON %%s(c) USING '%s'", TestingIndex.class.getName()));
final AtomicBoolean error = new AtomicBoolean();
// wait for index initialization and verify it's built:
waitForIndex(KEYSPACE, tableName, indexName);
assertMarkedAsBuilt(indexName);
// rebuild the index in another thread, but make it block:
TestingIndex.blockBuild();
Thread asyncBuild = new Thread(() -> {
try {
tryRebuild(indexName, false);
} catch (Throwable ex) {
error.set(true);
}
});
asyncBuild.start();
// wait for the rebuild to block, so that we can proceed unblocking all further operations:
TestingIndex.waitBlockedOnBuild();
// do not block further builds:
TestingIndex.shouldBlockBuild = false;
// try adding sstables but make the build fail:
TestingIndex.shouldFailBuild = true;
ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
try (Refs<SSTableReader> sstables = Refs.ref(cfs.getSSTables(SSTableSet.CANONICAL))) {
cfs.indexManager.handleNotification(new SSTableAddedNotification(sstables, null), cfs.getTracker());
fail("Should have failed!");
} catch (Throwable ex) {
assertTrue(ex.getMessage().contains("configured to fail"));
}
// disable failures:
TestingIndex.shouldFailBuild = false;
// unblock the pending build:
TestingIndex.unblockBuild();
asyncBuild.join();
// verify the index is *not* built due to the failing sstable build:
assertNotMarkedAsBuilt(indexName);
assertFalse(error.get());
}
Aggregations