use of org.opensearch.cluster.ClusterStateUpdateTask in project OpenSearch by opensearch-project.
the class BlobStoreRepository method executeConsistentStateUpdate.
@Override
public void executeConsistentStateUpdate(Function<RepositoryData, ClusterStateUpdateTask> createUpdateTask, String source, Consumer<Exception> onFailure) {
final RepositoryMetadata repositoryMetadataStart = metadata;
getRepositoryData(ActionListener.wrap(repositoryData -> {
final ClusterStateUpdateTask updateTask = createUpdateTask.apply(repositoryData);
clusterService.submitStateUpdateTask(source, new ClusterStateUpdateTask(updateTask.priority()) {
private boolean executedTask = false;
@Override
public ClusterState execute(ClusterState currentState) throws Exception {
// to change in any form.
if (repositoryMetadataStart.equals(getRepoMetadata(currentState))) {
executedTask = true;
return updateTask.execute(currentState);
}
return currentState;
}
@Override
public void onFailure(String source, Exception e) {
if (executedTask) {
updateTask.onFailure(source, e);
} else {
onFailure.accept(e);
}
}
@Override
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
if (executedTask) {
updateTask.clusterStateProcessed(source, oldState, newState);
} else {
executeConsistentStateUpdate(createUpdateTask, source, onFailure);
}
}
@Override
public TimeValue timeout() {
return updateTask.timeout();
}
});
}, onFailure));
}
use of org.opensearch.cluster.ClusterStateUpdateTask in project OpenSearch by opensearch-project.
the class BatchedRerouteServiceTests method testBatchesReroutesTogetherAtPriorityOfHighestSubmittedReroute.
public void testBatchesReroutesTogetherAtPriorityOfHighestSubmittedReroute() throws BrokenBarrierException, InterruptedException {
final CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
clusterService.submitStateUpdateTask("block master service", new ClusterStateUpdateTask() {
@Override
public ClusterState execute(ClusterState currentState) throws Exception {
// notify test that we are blocked
cyclicBarrier.await();
// wait to be unblocked by test
cyclicBarrier.await();
return currentState;
}
@Override
public void onFailure(String source, Exception e) {
throw new AssertionError(source, e);
}
});
// wait for master thread to be blocked
cyclicBarrier.await();
final AtomicBoolean rerouteExecuted = new AtomicBoolean();
final BatchedRerouteService batchedRerouteService = new BatchedRerouteService(clusterService, (s, r) -> {
// only called once
assertTrue(rerouteExecuted.compareAndSet(false, true));
return s;
});
final int iterations = scaledRandomIntBetween(1, 100);
final CountDownLatch tasksSubmittedCountDown = new CountDownLatch(iterations);
final CountDownLatch tasksCompletedCountDown = new CountDownLatch(iterations);
final List<Runnable> actions = new ArrayList<>(iterations);
final Function<Priority, Runnable> rerouteFromPriority = priority -> () -> {
final AtomicBoolean alreadyRun = new AtomicBoolean();
batchedRerouteService.reroute("reroute at " + priority, priority, ActionListener.wrap(() -> {
assertTrue(alreadyRun.compareAndSet(false, true));
tasksCompletedCountDown.countDown();
}));
tasksSubmittedCountDown.countDown();
};
// ensure at least one URGENT priority reroute
actions.add(rerouteFromPriority.apply(Priority.URGENT));
for (int i = 1; i < iterations; i++) {
final int iteration = i;
if (randomBoolean()) {
actions.add(rerouteFromPriority.apply(randomFrom(Priority.LOW, Priority.NORMAL, Priority.HIGH, Priority.URGENT)));
} else {
final Priority priority = randomFrom(Priority.NORMAL, Priority.HIGH, Priority.URGENT, Priority.IMMEDIATE);
final boolean submittedConcurrentlyWithReroute = randomBoolean();
if (submittedConcurrentlyWithReroute == false) {
// this task might be submitted later
tasksSubmittedCountDown.countDown();
}
actions.add(() -> {
clusterService.submitStateUpdateTask("other task " + iteration + " at " + priority, new ClusterStateUpdateTask(priority) {
@Override
public ClusterState execute(ClusterState currentState) {
switch(priority) {
case IMMEDIATE:
if (submittedConcurrentlyWithReroute) {
assertFalse("should have rerouted after " + priority + " priority task", rerouteExecuted.get());
}
// else this task might be submitted too late to precede the reroute
break;
case URGENT:
// may run either before or after reroute
break;
case HIGH:
case NORMAL:
assertTrue("should have rerouted before " + priority + " priority task", rerouteExecuted.get());
break;
default:
fail("unexpected priority: " + priority);
break;
}
return currentState;
}
@Override
public void onFailure(String source, Exception e) {
throw new AssertionError(source, e);
}
@Override
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
tasksCompletedCountDown.countDown();
}
});
if (submittedConcurrentlyWithReroute) {
tasksSubmittedCountDown.countDown();
}
});
}
}
Randomness.shuffle(actions);
actions.forEach(threadPool.generic()::execute);
assertTrue(tasksSubmittedCountDown.await(10, TimeUnit.SECONDS));
// allow master thread to continue;
cyclicBarrier.await();
// wait for reroute to complete
assertTrue(tasksCompletedCountDown.await(10, TimeUnit.SECONDS));
// see above for assertion that it's only called once
assertTrue(rerouteExecuted.get());
}
use of org.opensearch.cluster.ClusterStateUpdateTask in project OpenSearch by opensearch-project.
the class DelayedAllocationServiceTests method testDelayedUnassignedScheduleReroute.
public void testDelayedUnassignedScheduleReroute() throws Exception {
TimeValue delaySetting = timeValueMillis(100);
Metadata metadata = Metadata.builder().put(IndexMetadata.builder("test").settings(settings(Version.CURRENT).put(UnassignedInfo.INDEX_DELAYED_NODE_LEFT_TIMEOUT_SETTING.getKey(), delaySetting)).numberOfShards(1).numberOfReplicas(1)).build();
ClusterState clusterState = ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING.getDefault(Settings.EMPTY)).metadata(metadata).routingTable(RoutingTable.builder().addAsNew(metadata.index("test")).build()).build();
clusterState = ClusterState.builder(clusterState).nodes(DiscoveryNodes.builder().add(newNode("node1")).add(newNode("node2")).localNodeId("node1").masterNodeId("node1")).build();
final long baseTimestampNanos = System.nanoTime();
allocationService.setNanoTimeOverride(baseTimestampNanos);
clusterState = allocationService.reroute(clusterState, "reroute");
// starting primaries
clusterState = startInitializingShardsAndReroute(allocationService, clusterState);
// starting replicas
clusterState = startInitializingShardsAndReroute(allocationService, clusterState);
assertFalse("no shards should be unassigned", clusterState.getRoutingNodes().unassigned().size() > 0);
String nodeId = null;
final List<ShardRouting> allShards = clusterState.getRoutingTable().allShards("test");
// we need to find the node with the replica otherwise we will not reroute
for (ShardRouting shardRouting : allShards) {
if (shardRouting.primary() == false) {
nodeId = shardRouting.currentNodeId();
break;
}
}
assertNotNull(nodeId);
// remove node that has replica and reroute
clusterState = ClusterState.builder(clusterState).nodes(DiscoveryNodes.builder(clusterState.nodes()).remove(nodeId)).build();
clusterState = allocationService.disassociateDeadNodes(clusterState, true, "reroute");
ClusterState stateWithDelayedShard = clusterState;
// make sure the replica is marked as delayed (i.e. not reallocated)
assertEquals(1, UnassignedInfo.getNumberOfDelayedUnassigned(stateWithDelayedShard));
ShardRouting delayedShard = stateWithDelayedShard.getRoutingNodes().unassigned().iterator().next();
assertEquals(baseTimestampNanos, delayedShard.unassignedInfo().getUnassignedTimeInNanos());
// mock ClusterService.submitStateUpdateTask() method
CountDownLatch latch = new CountDownLatch(1);
AtomicReference<ClusterStateUpdateTask> clusterStateUpdateTask = new AtomicReference<>();
doAnswer(invocationOnMock -> {
clusterStateUpdateTask.set((ClusterStateUpdateTask) invocationOnMock.getArguments()[1]);
latch.countDown();
return null;
}).when(clusterService).submitStateUpdateTask(eq(CLUSTER_UPDATE_TASK_SOURCE), any(ClusterStateUpdateTask.class));
assertNull(delayedAllocationService.delayedRerouteTask.get());
long delayUntilClusterChangeEvent = TimeValue.timeValueNanos(randomInt((int) delaySetting.nanos() - 1)).nanos();
long clusterChangeEventTimestampNanos = baseTimestampNanos + delayUntilClusterChangeEvent;
delayedAllocationService.setNanoTimeOverride(clusterChangeEventTimestampNanos);
delayedAllocationService.clusterChanged(new ClusterChangedEvent("fake node left", stateWithDelayedShard, clusterState));
// check that delayed reroute task was created and registered with the proper settings
DelayedAllocationService.DelayedRerouteTask delayedRerouteTask = delayedAllocationService.delayedRerouteTask.get();
assertNotNull(delayedRerouteTask);
assertFalse(delayedRerouteTask.cancelScheduling.get());
assertThat(delayedRerouteTask.baseTimestampNanos, equalTo(clusterChangeEventTimestampNanos));
assertThat(delayedRerouteTask.nextDelay.nanos(), equalTo(delaySetting.nanos() - (clusterChangeEventTimestampNanos - baseTimestampNanos)));
// check that submitStateUpdateTask() was invoked on the cluster service mock
assertTrue(latch.await(30, TimeUnit.SECONDS));
verify(clusterService).submitStateUpdateTask(eq(CLUSTER_UPDATE_TASK_SOURCE), eq(clusterStateUpdateTask.get()));
// advance the time on the allocation service to a timestamp that happened after the delayed scheduling
long nanoTimeForReroute = clusterChangeEventTimestampNanos + delaySetting.nanos() + timeValueMillis(randomInt(200)).nanos();
allocationService.setNanoTimeOverride(nanoTimeForReroute);
// apply cluster state
ClusterState stateWithRemovedDelay = clusterStateUpdateTask.get().execute(stateWithDelayedShard);
// check that shard is not delayed anymore
assertEquals(0, UnassignedInfo.getNumberOfDelayedUnassigned(stateWithRemovedDelay));
// check that task is now removed
assertNull(delayedAllocationService.delayedRerouteTask.get());
// simulate calling listener (cluster change event)
delayedAllocationService.setNanoTimeOverride(nanoTimeForReroute + timeValueMillis(randomInt(200)).nanos());
delayedAllocationService.clusterChanged(new ClusterChangedEvent(CLUSTER_UPDATE_TASK_SOURCE, stateWithRemovedDelay, stateWithDelayedShard));
// check that no new task is scheduled
assertNull(delayedAllocationService.delayedRerouteTask.get());
// check that no further cluster state update was submitted
verifyNoMoreInteractions(clusterService);
}
use of org.opensearch.cluster.ClusterStateUpdateTask in project OpenSearch by opensearch-project.
the class MasterServiceTests method testMasterAwareExecution.
public void testMasterAwareExecution() throws Exception {
final MasterService nonMaster = createMasterService(false);
final boolean[] taskFailed = { false };
final CountDownLatch latch1 = new CountDownLatch(1);
nonMaster.submitStateUpdateTask("test", new ClusterStateUpdateTask() {
@Override
public ClusterState execute(ClusterState currentState) {
latch1.countDown();
return currentState;
}
@Override
public void onFailure(String source, Exception e) {
taskFailed[0] = true;
latch1.countDown();
}
});
latch1.await();
assertTrue("cluster state update task was executed on a non-master", taskFailed[0]);
final CountDownLatch latch2 = new CountDownLatch(1);
nonMaster.submitStateUpdateTask("test", new LocalClusterUpdateTask() {
@Override
public ClusterTasksResult<LocalClusterUpdateTask> execute(ClusterState currentState) {
taskFailed[0] = false;
latch2.countDown();
return unchanged();
}
@Override
public void onFailure(String source, Exception e) {
taskFailed[0] = true;
latch2.countDown();
}
});
latch2.await();
assertFalse("non-master cluster state update task was not executed", taskFailed[0]);
nonMaster.close();
}
use of org.opensearch.cluster.ClusterStateUpdateTask in project OpenSearch by opensearch-project.
the class PersistentTasksClusterServiceTests method createRecheckTestClusterService.
private ClusterService createRecheckTestClusterService(ClusterState initialState, boolean shouldSimulateFailure) {
AtomicBoolean testFailureNextTime = new AtomicBoolean(shouldSimulateFailure);
AtomicReference<ClusterState> state = new AtomicReference<>(initialState);
ClusterService recheckTestClusterService = mock(ClusterService.class);
when(recheckTestClusterService.getClusterSettings()).thenReturn(clusterService.getClusterSettings());
doAnswer(invocationOnMock -> state.get().getNodes().getLocalNode()).when(recheckTestClusterService).localNode();
doAnswer(invocationOnMock -> state.get()).when(recheckTestClusterService).state();
doAnswer(invocationOnMock -> {
@SuppressWarnings("unchecked") ClusterStateUpdateTask task = (ClusterStateUpdateTask) invocationOnMock.getArguments()[1];
ClusterState before = state.get();
ClusterState after = task.execute(before);
if (testFailureNextTime.compareAndSet(true, false)) {
task.onFailure("testing failure", new RuntimeException("foo"));
} else {
state.set(after);
task.clusterStateProcessed("test", before, after);
}
return null;
}).when(recheckTestClusterService).submitStateUpdateTask(anyString(), any(ClusterStateUpdateTask.class));
return recheckTestClusterService;
}
Aggregations