Merge branch 'cassandra-3.0' into trunk

This commit is contained in:
Sam Tunnicliffe 2015-10-28 17:26:43 +00:00
commit a88d3e8962
6 changed files with 66 additions and 12 deletions

View File

@ -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)

View File

@ -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
{

View File

@ -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)

View File

@ -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();

View File

@ -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)

View File

@ -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();