Search in sources :

Example 26 with TimeValue

use of io.crate.common.unit.TimeValue in project crate by crate.

the class ActiveShardsObserver method waitForActiveShards.

/**
 * Waits on the specified number of active shards to be started before executing the
 *
 * @param indexNames the indices to wait for active shards on
 * @param activeShardCount the number of active shards to wait on before returning
 * @param timeout the timeout value
 * @param onResult a function that is executed in response to the requisite shards becoming active or a timeout (whichever comes first)
 * @param onFailure a function that is executed in response to an error occurring during waiting for the active shards
 */
public void waitForActiveShards(final String[] indexNames, final ActiveShardCount activeShardCount, final TimeValue timeout, final Consumer<Boolean> onResult, final Consumer<Exception> onFailure) {
    // wait for the configured number of active shards to be allocated before executing the result consumer
    if (activeShardCount == ActiveShardCount.NONE) {
        // not waiting, so just run whatever we were to run when the waiting is
        onResult.accept(true);
        return;
    }
    final ClusterState state = clusterService.state();
    final ClusterStateObserver observer = new ClusterStateObserver(state, clusterService, null, LOGGER);
    if (activeShardCount.enoughShardsActive(state, indexNames)) {
        onResult.accept(true);
    } else {
        final Predicate<ClusterState> shardsAllocatedPredicate = newState -> activeShardCount.enoughShardsActive(newState, indexNames);
        final ClusterStateObserver.Listener observerListener = new ClusterStateObserver.Listener() {

            @Override
            public void onNewClusterState(ClusterState state) {
                onResult.accept(true);
            }

            @Override
            public void onClusterServiceClose() {
                LOGGER.debug("[{}] cluster service closed while waiting for enough shards to be started.", Arrays.toString(indexNames));
                onFailure.accept(new NodeClosedException(clusterService.localNode()));
            }

            @Override
            public void onTimeout(TimeValue timeout) {
                onResult.accept(false);
            }
        };
        observer.waitForNextChange(observerListener, shardsAllocatedPredicate, timeout);
    }
}
Also used : Consumer(java.util.function.Consumer) ClusterState(org.elasticsearch.cluster.ClusterState) Arrays(java.util.Arrays) Logger(org.apache.logging.log4j.Logger) Predicate(java.util.function.Predicate) ClusterService(org.elasticsearch.cluster.service.ClusterService) TimeValue(io.crate.common.unit.TimeValue) ThreadPool(org.elasticsearch.threadpool.ThreadPool) ClusterStateObserver(org.elasticsearch.cluster.ClusterStateObserver) LogManager(org.apache.logging.log4j.LogManager) NodeClosedException(org.elasticsearch.node.NodeClosedException) ActionListener(org.elasticsearch.action.ActionListener) ClusterState(org.elasticsearch.cluster.ClusterState) ClusterStateObserver(org.elasticsearch.cluster.ClusterStateObserver) ActionListener(org.elasticsearch.action.ActionListener) NodeClosedException(org.elasticsearch.node.NodeClosedException) TimeValue(io.crate.common.unit.TimeValue)

Example 27 with TimeValue

use of io.crate.common.unit.TimeValue in project crate by crate.

the class ClusterStateObserver method waitForNextChange.

/**
 * Wait for the next cluster state which satisfies statePredicate
 *
 * @param listener        callback listener
 * @param statePredicate predicate to check whether cluster state changes are relevant and the callback should be called
 * @param timeOutValue    a timeout for waiting. If null the global observer timeout will be used.
 */
public void waitForNextChange(Listener listener, Predicate<ClusterState> statePredicate, @Nullable TimeValue timeOutValue) {
    if (observingContext.get() != null) {
        throw new ElasticsearchException("already waiting for a cluster state change");
    }
    Long timeoutTimeLeftMS;
    if (timeOutValue == null) {
        timeOutValue = this.timeOutValue;
        if (timeOutValue != null) {
            long timeSinceStartMS = TimeValue.nsecToMSec(System.nanoTime() - startTimeNS);
            timeoutTimeLeftMS = timeOutValue.millis() - timeSinceStartMS;
            if (timeoutTimeLeftMS <= 0L) {
                // things have timeout while we were busy -> notify
                logger.trace("observer timed out. notifying listener. timeout setting [{}], time since start [{}]", timeOutValue, new TimeValue(timeSinceStartMS));
                // update to latest, in case people want to retry
                timedOut = true;
                lastObservedState.set(new StoredState(clusterApplierService.state()));
                listener.onTimeout(timeOutValue);
                return;
            }
        } else {
            timeoutTimeLeftMS = null;
        }
    } else {
        this.startTimeNS = System.nanoTime();
        this.timeOutValue = timeOutValue;
        timeoutTimeLeftMS = timeOutValue.millis();
        timedOut = false;
    }
    // sample a new state. This state maybe *older* than the supplied state if we are called from an applier,
    // which wants to wait for something else to happen
    ClusterState newState = clusterApplierService.state();
    if (lastObservedState.get().isOlderOrDifferentMaster(newState) && statePredicate.test(newState)) {
        // good enough, let's go.
        logger.trace("observer: sampled state accepted by predicate ({})", newState);
        lastObservedState.set(new StoredState(newState));
        listener.onNewClusterState(newState);
    } else {
        logger.trace("observer: sampled state rejected by predicate ({}). adding listener to ClusterService", newState);
        final ObservingContext context = new ObservingContext(listener, statePredicate);
        if (!observingContext.compareAndSet(null, context)) {
            throw new ElasticsearchException("already waiting for a cluster state change");
        }
        clusterApplierService.addTimeoutListener(timeoutTimeLeftMS == null ? null : new TimeValue(timeoutTimeLeftMS), clusterStateListener);
    }
}
Also used : ElasticsearchException(org.elasticsearch.ElasticsearchException) TimeValue(io.crate.common.unit.TimeValue)

Example 28 with TimeValue

use of io.crate.common.unit.TimeValue in project crate by crate.

the class IncrementalClusterStateWriter method updateClusterState.

/**
 * Updates manifest and meta data on disk.
 *
 * @param newState new {@link ClusterState}
 *
 * @throws WriteStateException if exception occurs. See also {@link WriteStateException#isDirty()}.
 */
void updateClusterState(ClusterState newState) throws WriteStateException {
    Metadata newMetadata = newState.metadata();
    final long startTimeMillis = relativeTimeMillisSupplier.getAsLong();
    final AtomicClusterStateWriter writer = new AtomicClusterStateWriter(metaStateService, previousManifest);
    long globalStateGeneration = writeGlobalState(writer, newMetadata);
    Map<Index, Long> indexGenerations = writeIndicesMetadata(writer, newState);
    Manifest manifest = new Manifest(previousManifest.getCurrentTerm(), newState.version(), globalStateGeneration, indexGenerations);
    writeManifest(writer, manifest);
    previousManifest = manifest;
    previousClusterState = newState;
    final long durationMillis = relativeTimeMillisSupplier.getAsLong() - startTimeMillis;
    final TimeValue finalSlowWriteLoggingThreshold = this.slowWriteLoggingThreshold;
    if (durationMillis >= finalSlowWriteLoggingThreshold.getMillis()) {
        LOGGER.warn("writing cluster state took [{}ms] which is above the warn threshold of [{}]; " + "wrote metadata for [{}] indices and skipped [{}] unchanged indices", durationMillis, finalSlowWriteLoggingThreshold, writer.getIndicesWritten(), writer.getIndicesSkipped());
    } else {
        LOGGER.debug("writing cluster state took [{}ms]; wrote metadata for [{}] indices and skipped [{}] unchanged indices", durationMillis, writer.getIndicesWritten(), writer.getIndicesSkipped());
    }
}
Also used : IndexMetadata(org.elasticsearch.cluster.metadata.IndexMetadata) Metadata(org.elasticsearch.cluster.metadata.Metadata) Index(org.elasticsearch.index.Index) Manifest(org.elasticsearch.cluster.metadata.Manifest) TimeValue(io.crate.common.unit.TimeValue)

Example 29 with TimeValue

use of io.crate.common.unit.TimeValue in project crate by crate.

the class AddVotingConfigExclusionsRequestTests method testSerialization.

public void testSerialization() throws IOException {
    int descriptionCount = between(0, 5);
    String[] descriptions = new String[descriptionCount];
    for (int i = 0; i < descriptionCount; i++) {
        descriptions[i] = randomAlphaOfLength(10);
    }
    TimeValue timeout = TimeValue.timeValueMillis(between(0, 30000));
    final AddVotingConfigExclusionsRequest originalRequest = new AddVotingConfigExclusionsRequest(descriptions, timeout);
    final AddVotingConfigExclusionsRequest deserialized = copyWriteable(originalRequest, writableRegistry(), AddVotingConfigExclusionsRequest::new);
    assertThat(deserialized.getNodeDescriptions(), equalTo(originalRequest.getNodeDescriptions()));
    assertThat(deserialized.getTimeout(), equalTo(originalRequest.getTimeout()));
}
Also used : TimeValue(io.crate.common.unit.TimeValue)

Example 30 with TimeValue

use of io.crate.common.unit.TimeValue in project crate by crate.

the class RetentionLeaseIT method testRetentionLeasesSyncOnExpiration.

@Test
public void testRetentionLeasesSyncOnExpiration() throws Exception {
    final int numberOfReplicas = 2 - scaledRandomIntBetween(0, 2);
    internalCluster().ensureAtLeastNumDataNodes(1 + numberOfReplicas);
    final long estimatedTimeIntervalMillis = ThreadPool.ESTIMATED_TIME_INTERVAL_SETTING.get(Settings.EMPTY).millis();
    final TimeValue retentionLeaseTimeToLive = TimeValue.timeValueMillis(randomLongBetween(estimatedTimeIntervalMillis, 2 * estimatedTimeIntervalMillis));
    execute("create table doc.tbl (x int) clustered into 1 shards " + "with (" + "   number_of_replicas = ?, " + "   \"soft_deletes.enabled\" = true, " + "   \"soft_deletes.retention_lease.sync_interval\" = ?)", new Object[] { numberOfReplicas, retentionLeaseTimeToLive.getStringRep() });
    ensureGreen("tbl");
    final String primaryShardNodeId = clusterService().state().routingTable().index("tbl").shard(0).primaryShard().currentNodeId();
    final String primaryShardNodeName = clusterService().state().nodes().get(primaryShardNodeId).getName();
    final IndexShard primary = internalCluster().getInstance(IndicesService.class, primaryShardNodeName).getShardOrNull(new ShardId(resolveIndex("tbl"), 0));
    // we will add multiple retention leases, wait for some to expire, and assert a consistent view between the primary and the replicas
    final int length = randomIntBetween(1, 8);
    for (int i = 0; i < length; i++) {
        // update the index for retention leases to live a long time
        execute("alter table doc.tbl reset (\"soft_deletes.retention_lease.period\")");
        final String id = randomAlphaOfLength(8);
        final long retainingSequenceNumber = randomLongBetween(0, Long.MAX_VALUE);
        final String source = randomAlphaOfLength(8);
        final CountDownLatch latch = new CountDownLatch(1);
        final ActionListener<ReplicationResponse> listener = ActionListener.wrap(r -> latch.countDown(), e -> fail(e.toString()));
        final RetentionLease currentRetentionLease = primary.addRetentionLease(id, retainingSequenceNumber, source, listener);
        final long now = System.nanoTime();
        latch.await();
        // check current retention leases have been synced to all replicas
        for (final ShardRouting replicaShard : clusterService().state().routingTable().index("tbl").shard(0).replicaShards()) {
            final String replicaShardNodeId = replicaShard.currentNodeId();
            final String replicaShardNodeName = clusterService().state().nodes().get(replicaShardNodeId).getName();
            final IndexShard replica = internalCluster().getInstance(IndicesService.class, replicaShardNodeName).getShardOrNull(new ShardId(resolveIndex("tbl"), 0));
            assertThat(RetentionLeaseUtils.toMapExcludingPeerRecoveryRetentionLeases(replica.getRetentionLeases()).values(), anyOf(empty(), contains(currentRetentionLease)));
        }
        // update the index for retention leases to short a long time, to force expiration
        execute("alter table doc.tbl set (\"soft_deletes.retention_lease.period\" = ?)", new Object[] { retentionLeaseTimeToLive.getStringRep() });
        // sleep long enough that the current retention lease has expired
        final long later = System.nanoTime();
        Thread.sleep(Math.max(0, retentionLeaseTimeToLive.millis() - TimeUnit.NANOSECONDS.toMillis(later - now)));
        assertBusy(() -> assertThat(RetentionLeaseUtils.toMapExcludingPeerRecoveryRetentionLeases(primary.getRetentionLeases()).entrySet(), empty()));
        // now that all retention leases are expired should have been synced to all replicas
        assertBusy(() -> {
            for (final ShardRouting replicaShard : clusterService().state().routingTable().index("tbl").shard(0).replicaShards()) {
                final String replicaShardNodeId = replicaShard.currentNodeId();
                final String replicaShardNodeName = clusterService().state().nodes().get(replicaShardNodeId).getName();
                final IndexShard replica = internalCluster().getInstance(IndicesService.class, replicaShardNodeName).getShardOrNull(new ShardId(resolveIndex("tbl"), 0));
                assertThat(RetentionLeaseUtils.toMapExcludingPeerRecoveryRetentionLeases(replica.getRetentionLeases()).entrySet(), empty());
            }
        });
    }
}
Also used : ShardId(org.elasticsearch.index.shard.ShardId) IndexShard(org.elasticsearch.index.shard.IndexShard) IndicesService(org.elasticsearch.indices.IndicesService) CountDownLatch(java.util.concurrent.CountDownLatch) ShardRouting(org.elasticsearch.cluster.routing.ShardRouting) TimeValue(io.crate.common.unit.TimeValue) ReplicationResponse(org.elasticsearch.action.support.replication.ReplicationResponse) Test(org.junit.Test)

Aggregations

TimeValue (io.crate.common.unit.TimeValue)75 Test (org.junit.Test)23 ClusterState (org.elasticsearch.cluster.ClusterState)20 IOException (java.io.IOException)17 ParameterizedMessage (org.apache.logging.log4j.message.ParameterizedMessage)12 ActionListener (org.elasticsearch.action.ActionListener)12 IndexMetadata (org.elasticsearch.cluster.metadata.IndexMetadata)11 ArrayList (java.util.ArrayList)10 ThreadPool (org.elasticsearch.threadpool.ThreadPool)10 ElasticsearchException (org.elasticsearch.ElasticsearchException)9 Settings (org.elasticsearch.common.settings.Settings)9 Logger (org.apache.logging.log4j.Logger)8 ClusterStateUpdateTask (org.elasticsearch.cluster.ClusterStateUpdateTask)8 ClusterService (org.elasticsearch.cluster.service.ClusterService)8 List (java.util.List)7 LogManager (org.apache.logging.log4j.LogManager)7 Version (org.elasticsearch.Version)7 ElasticsearchTimeoutException (org.elasticsearch.ElasticsearchTimeoutException)6 ClusterStateObserver (org.elasticsearch.cluster.ClusterStateObserver)6 StreamInput (org.elasticsearch.common.io.stream.StreamInput)6