From 2206030fe66ef84d444e64baaa9630e32767376c Mon Sep 17 00:00:00 2001 From: Yannick Welsch Date: Sat, 14 Nov 2015 23:38:48 +0100 Subject: [PATCH] Fix calculation of next delay for delayed shard allocation Currently the next delay is calculated based on System.currentTimeMillis() but the actual shards to delay based on the last time the GatewayAllocator tried to assign/delay the shard. This introduces an inconsistency for the case where shards should have been delay-allocated between the GatewayAllocator-based timestamp and System.currentTimeMillis(). Closes #14765 --- .../cluster/routing/RoutingService.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java b/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java index ed7c5c46aa3..db0a46de633 100644 --- a/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java +++ b/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java @@ -118,11 +118,17 @@ public class RoutingService extends AbstractLifecycleComponent i if (nextDelaySetting > 0 && nextDelaySetting < registeredNextDelaySetting) { FutureUtils.cancel(registeredNextDelayFuture); registeredNextDelaySetting = nextDelaySetting; - // We use System.currentTimeMillis here because we want the - // next delay from the "now" perspective, rather than the - // delay from the last time the GatewayAllocator tried to - // assign/delay the shard - TimeValue nextDelay = TimeValue.timeValueMillis(UnassignedInfo.findNextDelayedAllocationIn(System.currentTimeMillis(), settings, event.state())); + // We calculate nextDelay based on System.currentTimeMillis() here because we want the next delay from the "now" perspective + // rather than the delay from the last time the GatewayAllocator tried to assign/delay the shard. + // The actual calculation is based on the latter though, to account for shards that should have been allocated + // between unassignedShardsAllocatedTimestamp and System.currentTimeMillis() + long nextDelayBasedOnUnassignedShardsAllocatedTimestamp = UnassignedInfo.findNextDelayedAllocationIn(unassignedShardsAllocatedTimestamp, settings, event.state()); + // adjust from unassignedShardsAllocatedTimestamp to now + long nextDelayMillis = nextDelayBasedOnUnassignedShardsAllocatedTimestamp - (System.currentTimeMillis() - unassignedShardsAllocatedTimestamp); + if (nextDelayMillis < 0) { + nextDelayMillis = 0; + } + TimeValue nextDelay = TimeValue.timeValueMillis(nextDelayMillis); int unassignedDelayedShards = UnassignedInfo.getNumberOfDelayedUnassigned(unassignedShardsAllocatedTimestamp, settings, event.state()); if (unassignedDelayedShards > 0) { logger.info("delaying allocation for [{}] unassigned shards, next check in [{}]",