Search in sources :

Example 1 with CountDownLatch

use of org.apache.cassandra.utils.concurrent.CountDownLatch in project cassandra by apache.

the class StorageProxy method describeSchemaVersions.

/**
 * initiate a request/response session with each live node to check whether or not everybody is using the same
 * migration id. This is useful for determining if a schema change has propagated through the cluster. Disagreement
 * is assumed if any node fails to respond.
 */
public static Map<String, List<String>> describeSchemaVersions(boolean withPort) {
    final String myVersion = Schema.instance.getVersion().toString();
    final Map<InetAddressAndPort, UUID> versions = new ConcurrentHashMap<>();
    final Set<InetAddressAndPort> liveHosts = Gossiper.instance.getLiveMembers();
    final CountDownLatch latch = newCountDownLatch(liveHosts.size());
    RequestCallback<UUID> cb = message -> {
        // record the response from the remote node.
        versions.put(message.from(), message.payload);
        latch.decrement();
    };
    // an empty message acts as a request to the SchemaVersionVerbHandler.
    Message message = out(SCHEMA_VERSION_REQ, noPayload);
    for (InetAddressAndPort endpoint : liveHosts) MessagingService.instance().sendWithCallback(message, endpoint, cb);
    try {
        // wait for as long as possible. timeout-1s if possible.
        latch.await(DatabaseDescriptor.getRpcTimeout(NANOSECONDS), NANOSECONDS);
    } catch (InterruptedException e) {
        throw new UncheckedInterruptedException(e);
    }
    // maps versions to hosts that are on that version.
    Map<String, List<String>> results = new HashMap<String, List<String>>();
    Iterable<InetAddressAndPort> allHosts = concat(Gossiper.instance.getLiveMembers(), Gossiper.instance.getUnreachableMembers());
    for (InetAddressAndPort host : allHosts) {
        UUID version = versions.get(host);
        String stringVersion = version == null ? UNREACHABLE : version.toString();
        List<String> hosts = results.get(stringVersion);
        if (hosts == null) {
            hosts = new ArrayList<String>();
            results.put(stringVersion, hosts);
        }
        hosts.add(host.getHostAddress(withPort));
    }
    // we're done: the results map is ready to return to the client.  the rest is just debug logging:
    if (results.get(UNREACHABLE) != null)
        logger.debug("Hosts not in agreement. Didn't get a response from everybody: {}", join(results.get(UNREACHABLE), ","));
    for (Map.Entry<String, List<String>> entry : results.entrySet()) {
        // check for version disagreement. log the hosts that don't agree.
        if (entry.getKey().equals(UNREACHABLE) || entry.getKey().equals(myVersion))
            continue;
        for (String host : entry.getValue()) logger.debug("{} disagrees ({})", host, entry.getKey());
    }
    if (results.size() == 1)
        logger.debug("Schemas are in agreement.");
    return results;
}
Also used : Arrays(java.util.Arrays) StorageMetrics(org.apache.cassandra.metrics.StorageMetrics) Stage(org.apache.cassandra.concurrent.Stage) EndpointsForToken(org.apache.cassandra.locator.EndpointsForToken) ClientRequestsMetricsHolder.readMetrics(org.apache.cassandra.metrics.ClientRequestsMetricsHolder.readMetrics) ReadResponse(org.apache.cassandra.db.ReadResponse) Global.nanoTime(org.apache.cassandra.utils.Clock.Global.nanoTime) ReadRepairMetrics(org.apache.cassandra.metrics.ReadRepairMetrics) UnfilteredPartitionIterator(org.apache.cassandra.db.partitions.UnfilteredPartitionIterator) Future(java.util.concurrent.Future) OverloadedException(org.apache.cassandra.exceptions.OverloadedException) Replicas(org.apache.cassandra.locator.Replicas) Mutation(org.apache.cassandra.db.Mutation) Pair(org.apache.cassandra.utils.Pair) Map(java.util.Map) HintsService(org.apache.cassandra.hints.HintsService) SinglePartitionReadCommand(org.apache.cassandra.db.SinglePartitionReadCommand) PartitionIterators(org.apache.cassandra.db.partitions.PartitionIterators) ReplicaPlans(org.apache.cassandra.locator.ReplicaPlans) ReplicaPlan(org.apache.cassandra.locator.ReplicaPlan) Keyspace(org.apache.cassandra.db.Keyspace) ReadAbortException(org.apache.cassandra.exceptions.ReadAbortException) PartitionRangeReadCommand(org.apache.cassandra.db.PartitionRangeReadCommand) FBUtilities(org.apache.cassandra.utils.FBUtilities) RejectException(org.apache.cassandra.db.RejectException) CasWriteTimeoutException(org.apache.cassandra.exceptions.CasWriteTimeoutException) Set(java.util.Set) WriteType(org.apache.cassandra.db.WriteType) Verb(org.apache.cassandra.net.Verb) MILLISECONDS(java.util.concurrent.TimeUnit.MILLISECONDS) UUIDGen(org.apache.cassandra.utils.UUIDGen) CassandraRelevantProperties(org.apache.cassandra.config.CassandraRelevantProperties) WriteFailureException(org.apache.cassandra.exceptions.WriteFailureException) ReplicaLayout(org.apache.cassandra.locator.ReplicaLayout) NoPayload.noPayload(org.apache.cassandra.net.NoPayload.noPayload) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) Iterables(com.google.common.collect.Iterables) TableId(org.apache.cassandra.schema.TableId) PrepareVerbHandler.doPrepare(org.apache.cassandra.service.paxos.PrepareVerbHandler.doPrepare) Global.currentTimeMillis(org.apache.cassandra.utils.Clock.Global.currentTimeMillis) ReadCommand(org.apache.cassandra.db.ReadCommand) Message(org.apache.cassandra.net.Message) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) TruncateRequest(org.apache.cassandra.db.TruncateRequest) Schema(org.apache.cassandra.schema.Schema) IEndpointSnitch(org.apache.cassandra.locator.IEndpointSnitch) Token(org.apache.cassandra.dht.Token) CountDownLatch.newCountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) BatchlogManager(org.apache.cassandra.batchlog.BatchlogManager) InvalidRequestException(org.apache.cassandra.exceptions.InvalidRequestException) RequestTimeoutException(org.apache.cassandra.exceptions.RequestTimeoutException) TriggerExecutor(org.apache.cassandra.triggers.TriggerExecutor) ConsistencyLevel(org.apache.cassandra.db.ConsistencyLevel) MessagingService(org.apache.cassandra.net.MessagingService) Uninterruptibles(com.google.common.util.concurrent.Uninterruptibles) ReadTimeoutException(org.apache.cassandra.exceptions.ReadTimeoutException) MessageParams(org.apache.cassandra.db.MessageParams) Hint(org.apache.cassandra.hints.Hint) FilteredPartition(org.apache.cassandra.db.partitions.FilteredPartition) RequestFailureReason(org.apache.cassandra.exceptions.RequestFailureReason) AtomicLong(java.util.concurrent.atomic.AtomicLong) ViewUtils(org.apache.cassandra.db.view.ViewUtils) CasWriteUnknownResultException(org.apache.cassandra.exceptions.CasWriteUnknownResultException) Preconditions(com.google.common.base.Preconditions) ClientRequestsMetricsHolder.casReadMetrics(org.apache.cassandra.metrics.ClientRequestsMetricsHolder.casReadMetrics) ClientRequestsMetricsHolder.casWriteMetrics(org.apache.cassandra.metrics.ClientRequestsMetricsHolder.casWriteMetrics) CounterMutation(org.apache.cassandra.db.CounterMutation) BatchlogCleanup(org.apache.cassandra.service.BatchlogResponseHandler.BatchlogCleanup) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) CountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch) Message.out(org.apache.cassandra.net.Message.out) ByteBuffer(java.nio.ByteBuffer) Gossiper(org.apache.cassandra.gms.Gossiper) CASClientRequestMetrics(org.apache.cassandra.metrics.CASClientRequestMetrics) DecoratedKey(org.apache.cassandra.db.DecoratedKey) ClientRequestsMetricsHolder.readMetricsForLevel(org.apache.cassandra.metrics.ClientRequestsMetricsHolder.readMetricsForLevel) ReadRepair(org.apache.cassandra.service.reads.repair.ReadRepair) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AbstractReadExecutor(org.apache.cassandra.service.reads.AbstractReadExecutor) Iterables.concat(com.google.common.collect.Iterables.concat) RowIterator(org.apache.cassandra.db.rows.RowIterator) DatabaseDescriptor(org.apache.cassandra.config.DatabaseDescriptor) Global.randomBallot(org.apache.cassandra.service.paxos.BallotGenerator.Global.randomBallot) UnavailableException(org.apache.cassandra.exceptions.UnavailableException) MessageFlag(org.apache.cassandra.net.MessageFlag) Collection(java.util.Collection) ClientRequestsMetricsHolder.writeMetrics(org.apache.cassandra.metrics.ClientRequestsMetricsHolder.writeMetrics) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) WriteTimeoutException(org.apache.cassandra.exceptions.WriteTimeoutException) UUID(java.util.UUID) NoSpamLogger(org.apache.cassandra.utils.NoSpamLogger) RequestCallback(org.apache.cassandra.net.RequestCallback) Collectors(java.util.stream.Collectors) SERIAL(org.apache.cassandra.db.ConsistencyLevel.SERIAL) Objects(java.util.Objects) CacheLoader(com.google.common.cache.CacheLoader) UncheckedInterruptedException(org.apache.cassandra.utils.concurrent.UncheckedInterruptedException) List(java.util.List) ProposeVerbHandler.doPropose(org.apache.cassandra.service.paxos.ProposeVerbHandler.doPropose) ColumnFamilyStore(org.apache.cassandra.db.ColumnFamilyStore) ForwardingInfo(org.apache.cassandra.net.ForwardingInfo) TableMetadata(org.apache.cassandra.schema.TableMetadata) Optional(java.util.Optional) PartitionIterator(org.apache.cassandra.db.partitions.PartitionIterator) ClientRequestsMetricsHolder.writeMetricsForLevel(org.apache.cassandra.metrics.ClientRequestsMetricsHolder.writeMetricsForLevel) SchemaConstants(org.apache.cassandra.schema.SchemaConstants) RangeCommands(org.apache.cassandra.service.reads.range.RangeCommands) org.apache.cassandra.service.paxos(org.apache.cassandra.service.paxos) ReadExecutionController(org.apache.cassandra.db.ReadExecutionController) PartitionDenylist(org.apache.cassandra.schema.PartitionDenylist) PartitionUpdate(org.apache.cassandra.db.partitions.PartitionUpdate) NANOSECONDS(java.util.concurrent.TimeUnit.NANOSECONDS) Config(org.apache.cassandra.config.Config) HashMap(java.util.HashMap) TombstoneOverwhelmingException(org.apache.cassandra.db.filter.TombstoneOverwhelmingException) RequestFailureException(org.apache.cassandra.exceptions.RequestFailureException) HashSet(java.util.HashSet) ClientRequestsMetricsHolder.viewWriteMetrics(org.apache.cassandra.metrics.ClientRequestsMetricsHolder.viewWriteMetrics) StringUtils.join(org.apache.commons.lang3.StringUtils.join) IsBootstrappingException(org.apache.cassandra.exceptions.IsBootstrappingException) Clock(org.apache.cassandra.utils.Clock) Global.nextBallotTimestampMicros(org.apache.cassandra.service.paxos.BallotGenerator.Global.nextBallotTimestampMicros) DenylistMetrics(org.apache.cassandra.metrics.DenylistMetrics) Logger(org.slf4j.Logger) ReadFailureException(org.apache.cassandra.exceptions.ReadFailureException) Tracing(org.apache.cassandra.tracing.Tracing) MonotonicClock(org.apache.cassandra.utils.MonotonicClock) Ints(com.google.common.primitives.Ints) Batch(org.apache.cassandra.batchlog.Batch) Replica(org.apache.cassandra.locator.Replica) TimeUnit(java.util.concurrent.TimeUnit) AbstractReplicationStrategy(org.apache.cassandra.locator.AbstractReplicationStrategy) ReadCallback(org.apache.cassandra.service.reads.ReadCallback) MBeanWrapper(org.apache.cassandra.utils.MBeanWrapper) IMutation(org.apache.cassandra.db.IMutation) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) Message(org.apache.cassandra.net.Message) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) CountDownLatch.newCountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch) CountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch) UncheckedInterruptedException(org.apache.cassandra.utils.concurrent.UncheckedInterruptedException) UncheckedInterruptedException(org.apache.cassandra.utils.concurrent.UncheckedInterruptedException) ArrayList(java.util.ArrayList) List(java.util.List) UUID(java.util.UUID) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 2 with CountDownLatch

use of org.apache.cassandra.utils.concurrent.CountDownLatch in project cassandra by apache.

the class StartupClusterConnectivityChecker method execute.

/**
 * @param peers The currently known peers in the cluster; argument is not modified.
 * @param getDatacenterSource A function for mapping peers to their datacenter.
 * @return true if the requested percentage of peers are marked ALIVE in gossip and have their connections opened;
 * else false.
 */
public boolean execute(Set<InetAddressAndPort> peers, Function<InetAddressAndPort, String> getDatacenterSource) {
    if (peers == null || this.timeoutNanos < 0)
        return true;
    // make a copy of the set, to avoid mucking with the input (in case it's a sensitive collection)
    peers = new HashSet<>(peers);
    InetAddressAndPort localAddress = FBUtilities.getBroadcastAddressAndPort();
    String localDc = getDatacenterSource.apply(localAddress);
    peers.remove(localAddress);
    if (peers.isEmpty())
        return true;
    // make a copy of the datacenter mapping (in case gossip updates happen during this method or some such)
    Map<InetAddressAndPort, String> peerToDatacenter = new HashMap<>();
    SetMultimap<String, InetAddressAndPort> datacenterToPeers = HashMultimap.create();
    for (InetAddressAndPort peer : peers) {
        String datacenter = getDatacenterSource.apply(peer);
        peerToDatacenter.put(peer, datacenter);
        datacenterToPeers.put(datacenter, peer);
    }
    // on the remaining local datacenter.
    if (!blockForRemoteDcs) {
        datacenterToPeers.keySet().retainAll(Collections.singleton(localDc));
        logger.info("Blocking coordination until only a single peer is DOWN in the local datacenter, timeout={}s", TimeUnit.NANOSECONDS.toSeconds(timeoutNanos));
    } else {
        logger.info("Blocking coordination until only a single peer is DOWN in each datacenter, timeout={}s", TimeUnit.NANOSECONDS.toSeconds(timeoutNanos));
    }
    // The threshold is 3 because for each peer we want to have 3 acks,
    // one for small message connection, one for large message connnection and one for alive event from gossip.
    AckMap acks = new AckMap(3, peers);
    Map<String, CountDownLatch> dcToRemainingPeers = new HashMap<>(datacenterToPeers.size());
    for (String datacenter : datacenterToPeers.keys()) {
        dcToRemainingPeers.put(datacenter, newCountDownLatch(Math.max(datacenterToPeers.get(datacenter).size() - 1, 0)));
    }
    long startNanos = nanoTime();
    // set up a listener to react to new nodes becoming alive (in gossip), and account for all the nodes that are already alive
    Set<InetAddressAndPort> alivePeers = Collections.newSetFromMap(new ConcurrentHashMap<>());
    AliveListener listener = new AliveListener(alivePeers, dcToRemainingPeers, acks, peerToDatacenter::get);
    Gossiper.instance.register(listener);
    // send out a ping message to open up the non-gossip connections to all peers. Note that this sends the
    // ping messages to _all_ peers, not just the ones we block for in dcToRemainingPeers.
    sendPingMessages(peers, dcToRemainingPeers, acks, peerToDatacenter::get);
    for (InetAddressAndPort peer : peers) {
        if (Gossiper.instance.isAlive(peer) && alivePeers.add(peer) && acks.incrementAndCheck(peer)) {
            String datacenter = peerToDatacenter.get(peer);
            // We have to check because we might only have the local DC in the map
            if (dcToRemainingPeers.containsKey(datacenter))
                dcToRemainingPeers.get(datacenter).decrement();
        }
    }
    boolean succeeded = true;
    for (CountDownLatch countDownLatch : dcToRemainingPeers.values()) {
        long remainingNanos = Math.max(1, timeoutNanos - (nanoTime() - startNanos));
        // noinspection UnstableApiUsage
        succeeded &= countDownLatch.awaitUninterruptibly(remainingNanos, TimeUnit.NANOSECONDS);
    }
    Gossiper.instance.unregister(listener);
    if (succeeded) {
        logger.info("Ensured sufficient healthy connections with {} after {} milliseconds", dcToRemainingPeers.keySet(), TimeUnit.NANOSECONDS.toMillis(nanoTime() - startNanos));
    } else {
        // dc -> missing peer host addresses
        Map<String, List<String>> peersDown = acks.getMissingPeers().stream().collect(groupingBy(peer -> {
            String dc = peerToDatacenter.get(peer);
            if (dc != null)
                return dc;
            return StringUtils.defaultString(getDatacenterSource.apply(peer), "unknown");
        }, mapping(InetAddressAndPort::getHostAddressAndPort, toList())));
        logger.warn("Timed out after {} milliseconds, was waiting for remaining peers to connect: {}", TimeUnit.NANOSECONDS.toMillis(nanoTime() - startNanos), peersDown);
    }
    return succeeded;
}
Also used : PING_REQ(org.apache.cassandra.net.Verb.PING_REQ) EndpointState(org.apache.cassandra.gms.EndpointState) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) StringUtils(org.apache.commons.lang.StringUtils) IEndpointStateChangeSubscriber(org.apache.cassandra.gms.IEndpointStateChangeSubscriber) LoggerFactory(org.slf4j.LoggerFactory) Collectors.groupingBy(java.util.stream.Collectors.groupingBy) HashMap(java.util.HashMap) Global.nanoTime(org.apache.cassandra.utils.Clock.Global.nanoTime) CountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch) Function(java.util.function.Function) Gossiper(org.apache.cassandra.gms.Gossiper) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) HashMultimap(com.google.common.collect.HashMultimap) CountDownLatch.newCountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) Collectors.mapping(java.util.stream.Collectors.mapping) Logger(org.slf4j.Logger) FBUtilities(org.apache.cassandra.utils.FBUtilities) LARGE_MESSAGES(org.apache.cassandra.net.ConnectionType.LARGE_MESSAGES) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) SMALL_MESSAGES(org.apache.cassandra.net.ConnectionType.SMALL_MESSAGES) SetMultimap(com.google.common.collect.SetMultimap) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) CountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch) CountDownLatch.newCountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch) ArrayList(java.util.ArrayList) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList)

Example 3 with CountDownLatch

use of org.apache.cassandra.utils.concurrent.CountDownLatch in project cassandra by apache.

the class StartupClusterConnectivityChecker method sendPingMessages.

/**
 * Sends a "connection warmup" message to each peer in the collection, on every {@link ConnectionType}
 * used for internode messaging (that is not gossip).
 */
private void sendPingMessages(Set<InetAddressAndPort> peers, Map<String, CountDownLatch> dcToRemainingPeers, AckMap acks, Function<InetAddressAndPort, String> getDatacenter) {
    RequestCallback responseHandler = msg -> {
        if (acks.incrementAndCheck(msg.from())) {
            String datacenter = getDatacenter.apply(msg.from());
            // We have to check because we might only have the local DC in the map
            if (dcToRemainingPeers.containsKey(datacenter))
                dcToRemainingPeers.get(datacenter).decrement();
        }
    };
    Message<PingRequest> small = Message.out(PING_REQ, PingRequest.forSmall);
    Message<PingRequest> large = Message.out(PING_REQ, PingRequest.forLarge);
    for (InetAddressAndPort peer : peers) {
        MessagingService.instance().sendWithCallback(small, peer, responseHandler, SMALL_MESSAGES);
        MessagingService.instance().sendWithCallback(large, peer, responseHandler, LARGE_MESSAGES);
    }
}
Also used : PING_REQ(org.apache.cassandra.net.Verb.PING_REQ) EndpointState(org.apache.cassandra.gms.EndpointState) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort) StringUtils(org.apache.commons.lang.StringUtils) IEndpointStateChangeSubscriber(org.apache.cassandra.gms.IEndpointStateChangeSubscriber) LoggerFactory(org.slf4j.LoggerFactory) Collectors.groupingBy(java.util.stream.Collectors.groupingBy) HashMap(java.util.HashMap) Global.nanoTime(org.apache.cassandra.utils.Clock.Global.nanoTime) CountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch) Function(java.util.function.Function) Gossiper(org.apache.cassandra.gms.Gossiper) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) HashMultimap(com.google.common.collect.HashMultimap) CountDownLatch.newCountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) Collectors.mapping(java.util.stream.Collectors.mapping) Logger(org.slf4j.Logger) FBUtilities(org.apache.cassandra.utils.FBUtilities) LARGE_MESSAGES(org.apache.cassandra.net.ConnectionType.LARGE_MESSAGES) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) SMALL_MESSAGES(org.apache.cassandra.net.ConnectionType.SMALL_MESSAGES) SetMultimap(com.google.common.collect.SetMultimap) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) InetAddressAndPort(org.apache.cassandra.locator.InetAddressAndPort)

Example 4 with CountDownLatch

use of org.apache.cassandra.utils.concurrent.CountDownLatch in project cassandra by apache.

the class PerSSTableIndexWriter method complete.

public void complete() {
    if (isComplete)
        return;
    currentKey = null;
    try {
        CountDownLatch latch = newCountDownLatch(indexes.size());
        for (Index index : indexes.values()) index.complete(latch);
        latch.awaitUninterruptibly();
    } finally {
        indexes.clear();
        isComplete = true;
    }
}
Also used : ColumnIndex(org.apache.cassandra.index.sasi.conf.ColumnIndex) CountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch) CountDownLatch.newCountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch)

Example 5 with CountDownLatch

use of org.apache.cassandra.utils.concurrent.CountDownLatch in project cassandra by apache.

the class TermIterator method build.

@SuppressWarnings("resource")
public static TermIterator build(final Expression e, Set<SSTableIndex> perSSTableIndexes) {
    final List<RangeIterator<Long, Token>> tokens = new CopyOnWriteArrayList<>();
    final AtomicLong tokenCount = new AtomicLong(0);
    RangeIterator<Long, Token> memtableIterator = e.index.searchMemtable(e);
    if (memtableIterator != null) {
        tokens.add(memtableIterator);
        tokenCount.addAndGet(memtableIterator.getCount());
    }
    final Set<SSTableIndex> referencedIndexes = new CopyOnWriteArraySet<>();
    try {
        final CountDownLatch latch = newCountDownLatch(perSSTableIndexes.size());
        final ExecutorService searchExecutor = SEARCH_EXECUTOR.get();
        for (final SSTableIndex index : perSSTableIndexes) {
            if (e.getOp() == PREFIX && index.mode() == CONTAINS && !index.hasMarkedPartials())
                throw new UnsupportedOperationException(format("The index %s has not yet been upgraded " + "to support prefix queries in CONTAINS mode. " + "Wait for compaction or rebuild the index.", index.getPath()));
            if (!index.reference()) {
                latch.decrement();
                continue;
            }
            // add to referenced right after the reference was acquired,
            // that helps to release index if something goes bad inside of the search
            referencedIndexes.add(index);
            searchExecutor.submit((Runnable) () -> {
                try {
                    e.checkpoint();
                    RangeIterator<Long, Token> keyIterator = index.search(e);
                    if (keyIterator == null) {
                        releaseIndex(referencedIndexes, index);
                        return;
                    }
                    tokens.add(keyIterator);
                    tokenCount.getAndAdd(keyIterator.getCount());
                } catch (Throwable e1) {
                    releaseIndex(referencedIndexes, index);
                    if (logger.isDebugEnabled())
                        logger.debug(format("Failed search an index %s, skipping.", index.getPath()), e1);
                } finally {
                    latch.decrement();
                }
            });
        }
        latch.awaitUninterruptibly();
        // checkpoint right away after all indexes complete search because we might have crossed the quota
        e.checkpoint();
        RangeIterator<Long, Token> ranges = RangeUnionIterator.build(tokens);
        return new TermIterator(e, ranges, referencedIndexes);
    } catch (Throwable ex) {
        // if execution quota was exceeded while opening indexes or something else happened
        // local (yet to be tracked) indexes should be released first before re-throwing exception
        referencedIndexes.forEach(TermIterator::releaseQuietly);
        throw ex;
    }
}
Also used : RangeIterator(org.apache.cassandra.index.sasi.utils.RangeIterator) Token(org.apache.cassandra.index.sasi.disk.Token) CountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch) CountDownLatch.newCountDownLatch(org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch) AtomicLong(java.util.concurrent.atomic.AtomicLong) AtomicLong(java.util.concurrent.atomic.AtomicLong)

Aggregations

CountDownLatch (org.apache.cassandra.utils.concurrent.CountDownLatch)6 CountDownLatch.newCountDownLatch (org.apache.cassandra.utils.concurrent.CountDownLatch.newCountDownLatch)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 InetAddressAndPort (org.apache.cassandra.locator.InetAddressAndPort)4 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 HashSet (java.util.HashSet)3 List (java.util.List)3 Map (java.util.Map)3 Set (java.util.Set)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 TimeUnit (java.util.concurrent.TimeUnit)3 Gossiper (org.apache.cassandra.gms.Gossiper)3 Global.nanoTime (org.apache.cassandra.utils.Clock.Global.nanoTime)3 FBUtilities (org.apache.cassandra.utils.FBUtilities)3 Logger (org.slf4j.Logger)3 LoggerFactory (org.slf4j.LoggerFactory)3 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 HashMultimap (com.google.common.collect.HashMultimap)2 SetMultimap (com.google.common.collect.SetMultimap)2