From 8e01b093d0307a67a09bcb238452078becb62707 Mon Sep 17 00:00:00 2001 From: Lee Hinman Date: Mon, 4 Apr 2016 08:28:03 -0600 Subject: [PATCH] When considering the size of shadow replica indices, set size to 0 Otherwise, when trying to calculate the amount of disk usage *after* the shard has been allocated, it has incorrectly subtracted the shadow replica size. Resolves #17460 --- .../cluster/InternalClusterInfoService.java | 17 +++++- .../elasticsearch/cluster/DiskUsageTests.java | 55 ++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java b/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java index 20837d9238e..b1362538cb9 100644 --- a/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java +++ b/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java @@ -30,7 +30,10 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsRequest; import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.admin.indices.stats.TransportIndicesStatsAction; +import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.allocation.decider.DiskThresholdDecider; @@ -330,7 +333,7 @@ public class InternalClusterInfoService extends AbstractComponent implements Clu ShardStats[] stats = indicesStatsResponse.getShards(); ImmutableOpenMap.Builder newShardSizes = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder newShardRoutingToDataPath = ImmutableOpenMap.builder(); - buildShardLevelInfo(logger, stats, newShardSizes, newShardRoutingToDataPath); + buildShardLevelInfo(logger, stats, newShardSizes, newShardRoutingToDataPath, clusterService.state()); shardSizes = newShardSizes.build(); shardRoutingToDataPath = newShardRoutingToDataPath.build(); } @@ -379,14 +382,24 @@ public class InternalClusterInfoService extends AbstractComponent implements Clu } static void buildShardLevelInfo(ESLogger logger, ShardStats[] stats, ImmutableOpenMap.Builder newShardSizes, - ImmutableOpenMap.Builder newShardRoutingToDataPath) { + ImmutableOpenMap.Builder newShardRoutingToDataPath, ClusterState state) { + MetaData meta = state.getMetaData(); for (ShardStats s : stats) { + IndexMetaData indexMeta = meta.index(s.getShardRouting().index()); + Settings indexSettings = indexMeta == null ? null : indexMeta.getSettings(); newShardRoutingToDataPath.put(s.getShardRouting(), s.getDataPath()); long size = s.getStats().getStore().sizeInBytes(); String sid = ClusterInfo.shardIdentifierFromRouting(s.getShardRouting()); if (logger.isTraceEnabled()) { logger.trace("shard: {} size: {}", sid, size); } + if (indexSettings != null && IndexMetaData.isIndexUsingShadowReplicas(indexSettings)) { + // Shards on a shared filesystem should be considered of size 0 + if (logger.isTraceEnabled()) { + logger.trace("shard: {} is using shadow replicas and will be treated as size 0", sid); + } + size = 0; + } newShardSizes.put(sid, size); } } diff --git a/core/src/test/java/org/elasticsearch/cluster/DiskUsageTests.java b/core/src/test/java/org/elasticsearch/cluster/DiskUsageTests.java index 964fb9ad7d4..1826ced24ea 100644 --- a/core/src/test/java/org/elasticsearch/cluster/DiskUsageTests.java +++ b/core/src/test/java/org/elasticsearch/cluster/DiskUsageTests.java @@ -23,11 +23,16 @@ import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; import org.elasticsearch.action.admin.indices.stats.CommonStats; import org.elasticsearch.action.admin.indices.stats.ShardStats; +import org.elasticsearch.cluster.ClusterName; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardRoutingHelper; import org.elasticsearch.cluster.routing.UnassignedInfo; import org.elasticsearch.common.collect.ImmutableOpenMap; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.DummyTransportAddress; import org.elasticsearch.index.Index; import org.elasticsearch.index.shard.ShardPath; @@ -113,7 +118,8 @@ public class DiskUsageTests extends ESTestCase { }; ImmutableOpenMap.Builder shardSizes = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder routingToPath = ImmutableOpenMap.builder(); - InternalClusterInfoService.buildShardLevelInfo(logger, stats, shardSizes, routingToPath); + ClusterState state = ClusterState.builder(new ClusterName("blarg")).version(0).build(); + InternalClusterInfoService.buildShardLevelInfo(logger, stats, shardSizes, routingToPath, state); assertEquals(2, shardSizes.size()); assertTrue(shardSizes.containsKey(ClusterInfo.shardIdentifierFromRouting(test_0))); assertTrue(shardSizes.containsKey(ClusterInfo.shardIdentifierFromRouting(test_1))); @@ -127,6 +133,53 @@ public class DiskUsageTests extends ESTestCase { assertEquals(test1Path.getParent().getParent().getParent().toAbsolutePath().toString(), routingToPath.get(test_1)); } + public void testFillShardsWithShadowIndices() { + final Index index = new Index("non-shadow", "0xcafe0000"); + ShardRouting s0 = ShardRouting.newUnassigned(index, 0, null, false, new UnassignedInfo(UnassignedInfo.Reason.INDEX_CREATED, "foo")); + ShardRoutingHelper.initialize(s0, "node1"); + ShardRoutingHelper.moveToStarted(s0); + Path i0Path = createTempDir().resolve("indices").resolve(index.getUUID()).resolve("0"); + CommonStats commonStats0 = new CommonStats(); + commonStats0.store = new StoreStats(100, 1); + final Index index2 = new Index("shadow", "0xcafe0001"); + ShardRouting s1 = ShardRouting.newUnassigned(index2, 0, null, false, new UnassignedInfo(UnassignedInfo.Reason.INDEX_CREATED, "foo")); + ShardRoutingHelper.initialize(s1, "node2"); + ShardRoutingHelper.moveToStarted(s1); + Path i1Path = createTempDir().resolve("indices").resolve(index2.getUUID()).resolve("0"); + CommonStats commonStats1 = new CommonStats(); + commonStats1.store = new StoreStats(1000, 1); + ShardStats[] stats = new ShardStats[] { + new ShardStats(s0, new ShardPath(false, i0Path, i0Path, s0.shardId()), commonStats0 , null), + new ShardStats(s1, new ShardPath(false, i1Path, i1Path, s1.shardId()), commonStats1 , null) + }; + ImmutableOpenMap.Builder shardSizes = ImmutableOpenMap.builder(); + ImmutableOpenMap.Builder routingToPath = ImmutableOpenMap.builder(); + ClusterState state = ClusterState.builder(new ClusterName("blarg")) + .version(0) + .metaData(MetaData.builder() + .put(IndexMetaData.builder("non-shadow") + .settings(Settings.builder() + .put(IndexMetaData.SETTING_INDEX_UUID, "0xcafe0000") + .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)) + .numberOfShards(1) + .numberOfReplicas(0)) + .put(IndexMetaData.builder("shadow") + .settings(Settings.builder() + .put(IndexMetaData.SETTING_INDEX_UUID, "0xcafe0001") + .put(IndexMetaData.SETTING_SHADOW_REPLICAS, true) + .put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)) + .numberOfShards(1) + .numberOfReplicas(0))) + .build(); + logger.info("--> calling buildShardLevelInfo with state: {}", state); + InternalClusterInfoService.buildShardLevelInfo(logger, stats, shardSizes, routingToPath, state); + assertEquals(2, shardSizes.size()); + assertTrue(shardSizes.containsKey(ClusterInfo.shardIdentifierFromRouting(s0))); + assertTrue(shardSizes.containsKey(ClusterInfo.shardIdentifierFromRouting(s1))); + assertEquals(100L, shardSizes.get(ClusterInfo.shardIdentifierFromRouting(s0)).longValue()); + assertEquals(0L, shardSizes.get(ClusterInfo.shardIdentifierFromRouting(s1)).longValue()); + } + public void testFillDiskUsage() { ImmutableOpenMap.Builder newLeastAvaiableUsages = ImmutableOpenMap.builder(); ImmutableOpenMap.Builder newMostAvaiableUsages = ImmutableOpenMap.builder();