mirror of https://github.com/apache/cassandra
Merge branch 'cassandra-3.0' into trunk
This commit is contained in:
commit
a88d3e8962
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
|
||||
3.0
|
||||
* Execute the metadata reload task of all registered indexes on CFS::reload (CASSANDRA-10604)
|
||||
* Fix thrift cas operations with defined columns (CASSANDRA-10576)
|
||||
* Fix PartitionUpdate.operationCount()for updates with static column operations (CASSANDRA-10606)
|
||||
* Fix thrift get() queries with defined columns (CASSANDRA-10586)
|
||||
|
|
|
|||
|
|
@ -296,9 +296,20 @@ public interface Index
|
|||
* Listener for processing events emitted during a single partition update.
|
||||
* Instances of this are responsible for applying modifications to the index in response to a single update
|
||||
* operation on a particular partition of the base table.
|
||||
*
|
||||
* That update may be generated by the normal write path, by iterating SSTables during streaming operations or when
|
||||
* building or rebuilding an index from source. Updates also occur during compaction when multiple versions of a
|
||||
* source partition from different SSTables are merged.
|
||||
*
|
||||
* Implementations should not make assumptions about resolution or filtering of the partition update being
|
||||
* processed. That is to say that it is possible for an Indexer instance to receive notification of a
|
||||
* PartitionDelete or RangeTombstones which shadow a Row it then receives via insertRow/updateRow.
|
||||
*
|
||||
* It is important to note that the only ordering guarantee made for the methods here is that the first call will
|
||||
* be to begin() and the last call to finish(). The other methods may be called to process update events in any
|
||||
* order. This can also include duplicate calls, in cases where a memtable partition is under contention from
|
||||
* several updates. In that scenario, the same set of events may be delivered to the Indexer as memtable update
|
||||
* which failed due to contention is re-applied.
|
||||
*/
|
||||
public interface Indexer
|
||||
{
|
||||
|
|
|
|||
|
|
@ -142,17 +142,11 @@ public class SecondaryIndexManager implements IndexRegistry
|
|||
|
||||
private Future<?> reloadIndex(IndexMetadata indexDef)
|
||||
{
|
||||
// if the index metadata has changed, reload the index
|
||||
IndexMetadata registered = indexes.get(indexDef.name).getIndexMetadata();
|
||||
if (!registered.equals(indexDef))
|
||||
{
|
||||
Index index = indexes.remove(registered.name);
|
||||
index.register(this);
|
||||
return blockingExecutor.submit(index.getMetadataReloadTask(indexDef));
|
||||
}
|
||||
|
||||
// otherwise, nothing to do
|
||||
return Futures.immediateFuture(null);
|
||||
Index index = indexes.get(indexDef.name);
|
||||
Callable<?> reloadTask = index.getMetadataReloadTask(indexDef);
|
||||
return reloadTask == null
|
||||
? Futures.immediateFuture(null)
|
||||
: blockingExecutor.submit(index.getMetadataReloadTask(indexDef));
|
||||
}
|
||||
|
||||
private Future<?> createIndex(IndexMetadata indexDef)
|
||||
|
|
|
|||
|
|
@ -183,7 +183,6 @@ public abstract class CassandraIndex implements Index
|
|||
|
||||
public Callable<?> getMetadataReloadTask(IndexMetadata indexDef)
|
||||
{
|
||||
setMetadata(indexDef);
|
||||
return () -> {
|
||||
indexCfs.metadata.reloadIndexMetadataProperties(baseCfs.metadata);
|
||||
indexCfs.reload();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package org.apache.cassandra.index;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
|
@ -452,6 +454,23 @@ public class CustomIndexTest extends CQLTester
|
|||
"SELECT * FROM %s WHERE expr(int_index, 'foo')");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void reloadIndexMetadataOnBaseCfsReload() throws Throwable
|
||||
{
|
||||
// verify that whenever the base table CFMetadata is reloaded, a reload of the index
|
||||
// metadata is performed
|
||||
createTable("CREATE TABLE %s (k int, v1 int, PRIMARY KEY(k))");
|
||||
createIndex(String.format("CREATE CUSTOM INDEX reload_counter ON %%s() USING '%s'",
|
||||
CountMetadataReloadsIndex.class.getName()));
|
||||
ColumnFamilyStore cfs = getCurrentColumnFamilyStore();
|
||||
CountMetadataReloadsIndex index = (CountMetadataReloadsIndex)cfs.indexManager.getIndexByName("reload_counter");
|
||||
assertEquals(0, index.reloads.get());
|
||||
|
||||
// reloading the CFS, even without any metadata changes invokes the index's metadata reload task
|
||||
cfs.reload();
|
||||
assertEquals(1, index.reloads.get());
|
||||
}
|
||||
|
||||
private void testCreateIndex(String indexName, String... targetColumnNames) throws Throwable
|
||||
{
|
||||
createIndex(String.format("CREATE CUSTOM INDEX %s ON %%s(%s) USING '%s'",
|
||||
|
|
@ -495,6 +514,27 @@ public class CustomIndexTest extends CQLTester
|
|||
return new IndexTarget(ColumnIdentifier.getInterned(name, true), type);
|
||||
}
|
||||
|
||||
public static final class CountMetadataReloadsIndex extends StubIndex
|
||||
{
|
||||
private final AtomicInteger reloads = new AtomicInteger(0);
|
||||
|
||||
public CountMetadataReloadsIndex(ColumnFamilyStore baseCfs, IndexMetadata metadata)
|
||||
{
|
||||
super(baseCfs, metadata);
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
reloads.set(0);
|
||||
}
|
||||
|
||||
public Callable<?> getMetadataReloadTask(IndexMetadata indexMetadata)
|
||||
{
|
||||
return reloads::incrementAndGet;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class IndexIncludedInBuild extends StubIndex
|
||||
{
|
||||
public IndexIncludedInBuild(ColumnFamilyStore baseCfs, IndexMetadata metadata)
|
||||
|
|
|
|||
|
|
@ -639,9 +639,18 @@ public class CassandraIndexTest extends CQLTester
|
|||
assertRows(execute(selectFirstRowCql), firstRow);
|
||||
assertEmpty(execute(selectSecondRowCql));
|
||||
|
||||
// reload the base cfs and verify queries still work as expected
|
||||
getCurrentColumnFamilyStore().reload();
|
||||
assertRows(execute(selectFirstRowCql), firstRow);
|
||||
assertEmpty(execute(selectSecondRowCql));
|
||||
|
||||
// drop the index and assert we can no longer query using it
|
||||
execute(dropIndexCql);
|
||||
assertInvalidThrowMessage(missingIndexMessage, InvalidRequestException.class, selectFirstRowCql);
|
||||
// reload the base cfs and verify again
|
||||
getCurrentColumnFamilyStore().reload();
|
||||
assertInvalidThrowMessage(missingIndexMessage, InvalidRequestException.class, selectFirstRowCql);
|
||||
|
||||
flush();
|
||||
compact();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue