Search in sources :

Example 1 with IndexBuildingSupport

use of org.apache.cassandra.index.Index.IndexBuildingSupport in project cassandra by apache.

the class SecondaryIndexManager method buildIndexesBlocking.

/**
 * Performs a blocking (re)indexing/recovery of the specified SSTables for the specified indexes.
 *
 * If the index doesn't support ALL {@link Index.LoadType} it performs a recovery {@link Index#getRecoveryTaskSupport()}
 * instead of a build {@link Index#getBuildTaskSupport()}
 *
 * @param sstables      the SSTables to be (re)indexed
 * @param indexes       the indexes to be (re)built for the specifed SSTables
 * @param isFullRebuild True if this method is invoked as a full index rebuild, false otherwise
 */
@SuppressWarnings({ "unchecked" })
private void buildIndexesBlocking(Collection<SSTableReader> sstables, Set<Index> indexes, boolean isFullRebuild) {
    if (indexes.isEmpty())
        return;
    // Mark all indexes as building: this step must happen first, because if any index can't be marked, the whole
    // process needs to abort
    markIndexesBuilding(indexes, isFullRebuild, false);
    // Build indexes in a try/catch, so that any index not marked as either built or failed will be marked as failed:
    final Set<Index> builtIndexes = Sets.newConcurrentHashSet();
    final Set<Index> unbuiltIndexes = Sets.newConcurrentHashSet();
    // Any exception thrown during index building that could be suppressed by the finally block
    Exception accumulatedFail = null;
    try {
        logger.info("Submitting index {} of {} for data in {}", isFullRebuild ? "recovery" : "build", indexes.stream().map(i -> i.getIndexMetadata().name).collect(Collectors.joining(",")), sstables.stream().map(SSTableReader::toString).collect(Collectors.joining(",")));
        // Group all building tasks
        Map<Index.IndexBuildingSupport, Set<Index>> byType = new HashMap<>();
        for (Index index : indexes) {
            IndexBuildingSupport buildOrRecoveryTask = isFullRebuild ? index.getBuildTaskSupport() : index.getRecoveryTaskSupport();
            Set<Index> stored = byType.computeIfAbsent(buildOrRecoveryTask, i -> new HashSet<>());
            stored.add(index);
        }
        // Schedule all index building tasks with a callback to mark them as built or failed
        List<Future<?>> futures = new ArrayList<>(byType.size());
        byType.forEach((buildingSupport, groupedIndexes) -> {
            SecondaryIndexBuilder builder = buildingSupport.getIndexBuildTask(baseCfs, groupedIndexes, sstables);
            final AsyncPromise<Object> build = new AsyncPromise<>();
            CompactionManager.instance.submitIndexBuild(builder).addCallback(new FutureCallback() {

                @Override
                public void onFailure(Throwable t) {
                    logAndMarkIndexesFailed(groupedIndexes, t, false);
                    unbuiltIndexes.addAll(groupedIndexes);
                    build.tryFailure(t);
                }

                @Override
                public void onSuccess(Object o) {
                    groupedIndexes.forEach(i -> markIndexBuilt(i, isFullRebuild));
                    logger.info("Index build of {} completed", getIndexNames(groupedIndexes));
                    builtIndexes.addAll(groupedIndexes);
                    build.trySuccess(o);
                }
            });
            futures.add(build);
        });
        // Finally wait for the index builds to finish and flush the indexes that built successfully
        FBUtilities.waitOnFutures(futures);
    } catch (Exception e) {
        accumulatedFail = e;
        throw e;
    } finally {
        try {
            // Fail any indexes that couldn't be marked
            Set<Index> failedIndexes = Sets.difference(indexes, Sets.union(builtIndexes, unbuiltIndexes));
            if (!failedIndexes.isEmpty()) {
                logAndMarkIndexesFailed(failedIndexes, accumulatedFail, false);
            }
            // Flush all built indexes with an aynchronous callback to log the success or failure of the flush
            flushIndexesBlocking(builtIndexes, new FutureCallback() {

                String indexNames = StringUtils.join(builtIndexes.stream().map(i -> i.getIndexMetadata().name).collect(Collectors.toList()), ',');

                @Override
                public void onFailure(Throwable ignored) {
                    logger.info("Index flush of {} failed", indexNames);
                }

                @Override
                public void onSuccess(Object ignored) {
                    logger.info("Index flush of {} completed", indexNames);
                }
            });
        } catch (Exception e) {
            if (accumulatedFail != null) {
                accumulatedFail.addSuppressed(e);
            } else {
                throw e;
            }
        }
    }
}
Also used : SSTableSet(org.apache.cassandra.db.lifecycle.SSTableSet) IndexTarget(org.apache.cassandra.cql3.statements.schema.IndexTarget) LoggerFactory(org.slf4j.LoggerFactory) org.apache.cassandra.db(org.apache.cassandra.db) TimeoutException(java.util.concurrent.TimeoutException) INotification(org.apache.cassandra.notifications.INotification) StringUtils(org.apache.commons.lang3.StringUtils) SSTableReader(org.apache.cassandra.io.sstable.format.SSTableReader) UnfilteredPartitionIterator(org.apache.cassandra.db.partitions.UnfilteredPartitionIterator) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) org.apache.cassandra.index.transactions(org.apache.cassandra.index.transactions) INotificationConsumer(org.apache.cassandra.notifications.INotificationConsumer) ColumnFilter(org.apache.cassandra.db.filter.ColumnFilter) com.google.common.collect(com.google.common.collect) DatabaseDescriptor(org.apache.cassandra.config.DatabaseDescriptor) Longs(com.google.common.primitives.Longs) FBUtilities(org.apache.cassandra.utils.FBUtilities) SSTableAddedNotification(org.apache.cassandra.notifications.SSTableAddedNotification) ExecutorUtils.shutdown(org.apache.cassandra.utils.ExecutorUtils.shutdown) Collectors(java.util.stream.Collectors) Stream(java.util.stream.Stream) SinglePartitionPager(org.apache.cassandra.service.pager.SinglePartitionPager) IndexBuildingSupport(org.apache.cassandra.index.Index.IndexBuildingSupport) DataLimits(org.apache.cassandra.db.filter.DataLimits) Joiner(com.google.common.base.Joiner) java.util(java.util) CompactionManager(org.apache.cassandra.db.compaction.CompactionManager) PartitionUpdate(org.apache.cassandra.db.partitions.PartitionUpdate) ColumnMetadata(org.apache.cassandra.schema.ColumnMetadata) Callable(java.util.concurrent.Callable) Constructor(java.lang.reflect.Constructor) Function(java.util.function.Function) Indexes(org.apache.cassandra.schema.Indexes) org.apache.cassandra.db.rows(org.apache.cassandra.db.rows) Strings(com.google.common.base.Strings) ProtocolVersion(org.apache.cassandra.transport.ProtocolVersion) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) JVMStabilityInspector(org.apache.cassandra.utils.JVMStabilityInspector) Logger(org.slf4j.Logger) RowFilter(org.apache.cassandra.db.filter.RowFilter) IndexMetadata(org.apache.cassandra.schema.IndexMetadata) Tracing(org.apache.cassandra.tracing.Tracing) ClusteringIndexSliceFilter(org.apache.cassandra.db.filter.ClusteringIndexSliceFilter) FutureCallback(com.google.common.util.concurrent.FutureCallback) ExecutorPlus(org.apache.cassandra.concurrent.ExecutorPlus) org.apache.cassandra.utils.concurrent(org.apache.cassandra.utils.concurrent) TimeUnit(java.util.concurrent.TimeUnit) CassandraIndex(org.apache.cassandra.index.internal.CassandraIndex) Global.executorFactory(org.apache.cassandra.concurrent.ExecutorFactory.Global.executorFactory) VisibleForTesting(com.google.common.annotations.VisibleForTesting) ImmediateExecutor(org.apache.cassandra.concurrent.ImmediateExecutor) ExecutorUtils.awaitTermination(org.apache.cassandra.utils.ExecutorUtils.awaitTermination) View(org.apache.cassandra.db.lifecycle.View) SSTableSet(org.apache.cassandra.db.lifecycle.SSTableSet) CassandraIndex(org.apache.cassandra.index.internal.CassandraIndex) TimeoutException(java.util.concurrent.TimeoutException) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) SSTableReader(org.apache.cassandra.io.sstable.format.SSTableReader) IndexBuildingSupport(org.apache.cassandra.index.Index.IndexBuildingSupport) FutureCallback(com.google.common.util.concurrent.FutureCallback)

Aggregations

VisibleForTesting (com.google.common.annotations.VisibleForTesting)1 Joiner (com.google.common.base.Joiner)1 Strings (com.google.common.base.Strings)1 com.google.common.collect (com.google.common.collect)1 Longs (com.google.common.primitives.Longs)1 FutureCallback (com.google.common.util.concurrent.FutureCallback)1 Constructor (java.lang.reflect.Constructor)1 java.util (java.util)1 Callable (java.util.concurrent.Callable)1 TimeUnit (java.util.concurrent.TimeUnit)1 TimeoutException (java.util.concurrent.TimeoutException)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 Function (java.util.function.Function)1 Collectors (java.util.stream.Collectors)1 Stream (java.util.stream.Stream)1 Global.executorFactory (org.apache.cassandra.concurrent.ExecutorFactory.Global.executorFactory)1 ExecutorPlus (org.apache.cassandra.concurrent.ExecutorPlus)1 ImmediateExecutor (org.apache.cassandra.concurrent.ImmediateExecutor)1 DatabaseDescriptor (org.apache.cassandra.config.DatabaseDescriptor)1 IndexTarget (org.apache.cassandra.cql3.statements.schema.IndexTarget)1