use of org.apache.cassandra.schema.IndexMetadata in project cassandra by apache.
the class DirectoriesTest method testSecondaryIndexDirectories.
@Test
public void testSecondaryIndexDirectories() {
TableMetadata.Builder builder = TableMetadata.builder(KS, "cf").addPartitionKeyColumn("thekey", UTF8Type.instance).addClusteringColumn("col", UTF8Type.instance);
ColumnIdentifier col = ColumnIdentifier.getInterned("col", true);
IndexMetadata indexDef = IndexMetadata.fromIndexTargets(Collections.singletonList(new IndexTarget(col, IndexTarget.Type.VALUES)), "idx", IndexMetadata.Kind.KEYS, Collections.emptyMap());
builder.indexes(Indexes.of(indexDef));
TableMetadata PARENT_CFM = builder.build();
TableMetadata INDEX_CFM = CassandraIndex.indexCfsMetadata(PARENT_CFM, indexDef);
Directories parentDirectories = new Directories(PARENT_CFM);
Directories indexDirectories = new Directories(INDEX_CFM);
// secondary index has its own directory
for (File dir : indexDirectories.getCFDirectories()) {
assertEquals(cfDir(INDEX_CFM), dir);
}
Descriptor parentDesc = new Descriptor(parentDirectories.getDirectoryForNewSSTables(), KS, PARENT_CFM.name, 0, SSTableFormat.Type.BIG);
Descriptor indexDesc = new Descriptor(indexDirectories.getDirectoryForNewSSTables(), KS, INDEX_CFM.name, 0, SSTableFormat.Type.BIG);
// snapshot dir should be created under its parent's
File parentSnapshotDirectory = Directories.getSnapshotDirectory(parentDesc, "test");
File indexSnapshotDirectory = Directories.getSnapshotDirectory(indexDesc, "test");
assertEquals(parentSnapshotDirectory, indexSnapshotDirectory.getParentFile());
// check if snapshot directory exists
parentSnapshotDirectory.mkdirs();
assertTrue(parentDirectories.snapshotExists("test"));
assertTrue(indexDirectories.snapshotExists("test"));
// check their creation time
assertEquals(parentDirectories.snapshotCreationTime("test"), indexDirectories.snapshotCreationTime("test"));
// check true snapshot size
Descriptor parentSnapshot = new Descriptor(parentSnapshotDirectory, KS, PARENT_CFM.name, 0, SSTableFormat.Type.BIG);
createFile(parentSnapshot.filenameFor(Component.DATA), 30);
Descriptor indexSnapshot = new Descriptor(indexSnapshotDirectory, KS, INDEX_CFM.name, 0, SSTableFormat.Type.BIG);
createFile(indexSnapshot.filenameFor(Component.DATA), 40);
assertEquals(30, parentDirectories.trueSnapshotsSize());
assertEquals(40, indexDirectories.trueSnapshotsSize());
// check snapshot details
Map<String, Pair<Long, Long>> parentSnapshotDetail = parentDirectories.getSnapshotDetails();
assertTrue(parentSnapshotDetail.containsKey("test"));
assertEquals(30L, parentSnapshotDetail.get("test").right.longValue());
Map<String, Pair<Long, Long>> indexSnapshotDetail = indexDirectories.getSnapshotDetails();
assertTrue(indexSnapshotDetail.containsKey("test"));
assertEquals(40L, indexSnapshotDetail.get("test").right.longValue());
// check backup directory
File parentBackupDirectory = Directories.getBackupsDirectory(parentDesc);
File indexBackupDirectory = Directories.getBackupsDirectory(indexDesc);
assertEquals(parentBackupDirectory, indexBackupDirectory.getParentFile());
}
use of org.apache.cassandra.schema.IndexMetadata in project cassandra by apache.
the class SecondaryIndexTest method testIndexCreate.
@Test
public void testIndexCreate() throws IOException, InterruptedException, ExecutionException {
Keyspace keyspace = Keyspace.open(KEYSPACE1);
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(COMPOSITE_INDEX_TO_BE_ADDED);
// create a row and update the birthdate value, test that the index query fetches the new version
new RowUpdateBuilder(cfs.metadata(), 0, "k1").clustering("c").add("birthdate", 1L).build().applyUnsafe();
String indexName = "birthdate_index";
ColumnMetadata old = cfs.metadata().getColumn(ByteBufferUtil.bytes("birthdate"));
IndexMetadata indexDef = IndexMetadata.fromIndexTargets(Collections.singletonList(new IndexTarget(old.name, IndexTarget.Type.VALUES)), indexName, IndexMetadata.Kind.COMPOSITES, Collections.EMPTY_MAP);
TableMetadata current = cfs.metadata();
TableMetadata updated = current.unbuild().indexes(current.indexes.with(indexDef)).build();
MigrationManager.announceTableUpdate(updated, true);
// fait for the index to be built
Index index = cfs.indexManager.getIndex(indexDef);
do {
TimeUnit.MILLISECONDS.sleep(100);
} while (!cfs.indexManager.isIndexQueryable(index));
// we had a bug (CASSANDRA-2244) where index would get created but not flushed -- check for that
// the way we find the index cfs is a bit convoluted at the moment
ColumnFamilyStore indexCfs = cfs.indexManager.getIndex(indexDef).getBackingTable().orElseThrow(throwAssert("Index not found"));
assertFalse(indexCfs.getLiveSSTables().isEmpty());
assertIndexedOne(cfs, ByteBufferUtil.bytes("birthdate"), 1L);
// validate that drop clears it out & rebuild works (CASSANDRA-2320)
assertTrue(cfs.getBuiltIndexes().contains(indexName));
cfs.indexManager.removeIndex(indexDef.name);
assertFalse(cfs.getBuiltIndexes().contains(indexName));
// rebuild & re-query
Future future = cfs.indexManager.addIndex(indexDef);
future.get();
assertIndexedOne(cfs, ByteBufferUtil.bytes("birthdate"), 1L);
}
use of org.apache.cassandra.schema.IndexMetadata in project cassandra by apache.
the class CustomIndexTest method assertIndexCreated.
private void assertIndexCreated(String name, Map<String, String> options, List<IndexTarget> targets) {
// all tests here use StubIndex as the custom index class,
// so add that to the map of options
options.put(CUSTOM_INDEX_OPTION_NAME, StubIndex.class.getName());
IndexMetadata expected = IndexMetadata.fromIndexTargets(targets, name, IndexMetadata.Kind.CUSTOM, options);
Indexes indexes = getCurrentColumnFamilyStore().metadata().indexes;
for (IndexMetadata actual : indexes) if (actual.equals(expected))
return;
fail(String.format("Index %s not found", expected));
}
use of org.apache.cassandra.schema.IndexMetadata in project cassandra by apache.
the class SecondaryIndexTest method createAndDropCollectionValuesIndex.
private void createAndDropCollectionValuesIndex(String columnName) throws Throwable {
String indexName = columnName + "_idx";
SecondaryIndexManager indexManager = getCurrentColumnFamilyStore().indexManager;
createIndex(String.format("CREATE INDEX %s on %%s(%s)", indexName, columnName));
IndexMetadata indexDef = indexManager.getIndexByName(indexName).getIndexMetadata();
assertEquals(String.format("values(%s)", columnName), indexDef.options.get(IndexTarget.TARGET_OPTION_NAME));
dropIndex(String.format("DROP INDEX %s.%s", KEYSPACE, indexName));
assertFalse(indexManager.hasIndexes());
createIndex(String.format("CREATE INDEX %s on %%s(values(%s))", indexName, columnName));
assertEquals(indexDef, indexManager.getIndexByName(indexName).getIndexMetadata());
dropIndex(String.format("DROP INDEX %s.%s", KEYSPACE, indexName));
}
use of org.apache.cassandra.schema.IndexMetadata in project cassandra by apache.
the class CreateIndexStatement method announceMigration.
public Event.SchemaChange announceMigration(QueryState queryState, boolean isLocalOnly) throws RequestValidationException {
TableMetadata current = Schema.instance.getTableMetadata(keyspace(), columnFamily());
List<IndexTarget> targets = new ArrayList<>(rawTargets.size());
for (IndexTarget.Raw rawTarget : rawTargets) targets.add(rawTarget.prepare(current));
String acceptedName = indexName;
if (Strings.isNullOrEmpty(acceptedName)) {
acceptedName = Indexes.getAvailableIndexName(keyspace(), columnFamily(), targets.size() == 1 ? targets.get(0).column.toString() : null);
}
if (Schema.instance.getKeyspaceMetadata(keyspace()).existingIndexNames(null).contains(acceptedName)) {
if (ifNotExists)
return null;
else
throw new InvalidRequestException(String.format("Index %s already exists", acceptedName));
}
IndexMetadata.Kind kind;
Map<String, String> indexOptions;
if (properties.isCustom) {
kind = IndexMetadata.Kind.CUSTOM;
indexOptions = properties.getOptions();
} else {
indexOptions = Collections.emptyMap();
kind = current.isCompound() ? IndexMetadata.Kind.COMPOSITES : IndexMetadata.Kind.KEYS;
}
IndexMetadata index = IndexMetadata.fromIndexTargets(targets, acceptedName, kind, indexOptions);
// check to disallow creation of an index which duplicates an existing one in all but name
Optional<IndexMetadata> existingIndex = Iterables.tryFind(current.indexes, existing -> existing.equalsWithoutName(index));
if (existingIndex.isPresent()) {
if (ifNotExists)
return null;
else
throw new InvalidRequestException(String.format("Index %s is a duplicate of existing index %s", index.name, existingIndex.get().name));
}
TableMetadata updated = current.unbuild().indexes(current.indexes.with(index)).build();
logger.trace("Updating index definition for {}", indexName);
MigrationManager.announceTableUpdate(updated, isLocalOnly);
// Creating an index is akin to updating the CF
return new Event.SchemaChange(Event.SchemaChange.Change.UPDATED, Event.SchemaChange.Target.TABLE, keyspace(), columnFamily());
}
Aggregations