Skip to content

Commit 9ea918f

Browse files
committed
New class to avoid bogus DiskUsage instances
1 parent 144e0f4 commit 9ea918f

File tree

3 files changed

+65
-13
lines changed

3 files changed

+65
-13
lines changed

server/src/main/java/org/elasticsearch/cluster/DiskUsage.java

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ public class DiskUsage implements ToXContentFragment, Writeable {
4545
* will always return 100.0% free
4646
*/
4747
public DiskUsage(String nodeId, String nodeName, String path, long totalBytes, long freeBytes) {
48+
assert totalBytes >= 0L : "totalBytes should be non-negative, but got " + totalBytes;
49+
assert freeBytes >= 0L : "freeBytes should be non-negative, but got " + freeBytes;
4850
this.nodeId = nodeId;
4951
this.nodeName = nodeName;
5052
this.freeBytes = freeBytes;

server/src/main/java/org/elasticsearch/cluster/routing/allocation/decider/DiskThresholdDecider.java

+61-12
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ public Decision canAllocate(ShardRouting shardRouting, RoutingNode node, Routing
139139

140140
// subtractLeavingShards is passed as false here, because they still use disk space, and therefore should we should be extra careful
141141
// and take the size into account
142-
DiskUsage usage = getDiskUsage(node, allocation, usages, false);
142+
DiskUsageWithRelocations usage = getDiskUsage(node, allocation, usages, false);
143143
// First, check that the node currently over the low watermark
144144
double freeDiskPercentage = usage.getFreeDiskAsPercentage();
145145
// Cache the used disk percentage for displaying disk percentages consistent with documentation
@@ -304,7 +304,7 @@ public Decision canRemain(ShardRouting shardRouting, RoutingNode node, RoutingAl
304304

305305
// subtractLeavingShards is passed as true here, since this is only for shards remaining, we will *eventually* have enough disk
306306
// since shards are moving away. No new shards will be incoming since in canAllocate we pass false for this check.
307-
final DiskUsage usage = getDiskUsage(node, allocation, usages, true);
307+
final DiskUsageWithRelocations usage = getDiskUsage(node, allocation, usages, true);
308308
final String dataPath = clusterInfo.getDataPath(shardRouting);
309309
// If this node is already above the high threshold, the shard cannot remain (get it off!)
310310
final double freeDiskPercentage = usage.getFreeDiskAsPercentage();
@@ -356,8 +356,8 @@ public Decision canRemain(ShardRouting shardRouting, RoutingNode node, RoutingAl
356356
"there is enough disk on this node for the shard to remain, free: [%s]", new ByteSizeValue(freeBytes));
357357
}
358358

359-
private DiskUsage getDiskUsage(RoutingNode node, RoutingAllocation allocation,
360-
ImmutableOpenMap<String, DiskUsage> usages, boolean subtractLeavingShards) {
359+
private DiskUsageWithRelocations getDiskUsage(RoutingNode node, RoutingAllocation allocation,
360+
ImmutableOpenMap<String, DiskUsage> usages, boolean subtractLeavingShards) {
361361
DiskUsage usage = usages.get(node.nodeId());
362362
if (usage == null) {
363363
// If there is no usage, and we have other nodes in the cluster,
@@ -367,13 +367,11 @@ private DiskUsage getDiskUsage(RoutingNode node, RoutingAllocation allocation,
367367
node.nodeId(), usage.getTotalBytes(), usage.getFreeBytes(), usage.getFreeDiskAsPercentage());
368368
}
369369

370-
final long relocatingShardsSize = sizeOfRelocatingShards(node, subtractLeavingShards, usage.getPath(),
371-
allocation.clusterInfo(), allocation.metaData(), allocation.routingTable());
372-
final DiskUsage usageIncludingRelocations = new DiskUsage(node.nodeId(), node.node().getName(), usage.getPath(),
373-
usage.getTotalBytes(), usage.getFreeBytes() - relocatingShardsSize);
374-
logger.trace("getDiskUsage: usage [{}] with [{}] bytes relocating yields [{}]",
375-
usage, relocatingShardsSize, usageIncludingRelocations);
376-
return usageIncludingRelocations;
370+
final DiskUsageWithRelocations diskUsageWithRelocations = new DiskUsageWithRelocations(usage,
371+
sizeOfRelocatingShards(node, subtractLeavingShards, usage.getPath(),
372+
allocation.clusterInfo(), allocation.metaData(), allocation.routingTable()));
373+
logger.trace("getDiskUsage(subtractLeavingShards={}) returning {}", subtractLeavingShards, diskUsageWithRelocations);
374+
return diskUsageWithRelocations;
377375
}
378376

379377
/**
@@ -403,7 +401,7 @@ DiskUsage averageUsage(RoutingNode node, ImmutableOpenMap<String, DiskUsage> usa
403401
* @param shardSize Size in bytes of the shard
404402
* @return Percentage of free space after the shard is assigned to the node
405403
*/
406-
double freeDiskPercentageAfterShardAssigned(DiskUsage usage, Long shardSize) {
404+
double freeDiskPercentageAfterShardAssigned(DiskUsageWithRelocations usage, Long shardSize) {
407405
shardSize = (shardSize == null) ? 0 : shardSize;
408406
DiskUsage newUsage = new DiskUsage(usage.getNodeId(), usage.getNodeName(), usage.getPath(),
409407
usage.getTotalBytes(), usage.getFreeBytes() - shardSize);
@@ -471,4 +469,55 @@ public static long getExpectedShardSize(ShardRouting shard, long defaultValue, C
471469
return clusterInfo.getShardSize(shard, defaultValue);
472470
}
473471
}
472+
473+
static class DiskUsageWithRelocations {
474+
475+
private final DiskUsage diskUsage;
476+
private final long relocatingShardSize;
477+
478+
DiskUsageWithRelocations(DiskUsage diskUsage, long relocatingShardSize) {
479+
this.diskUsage = diskUsage;
480+
this.relocatingShardSize = relocatingShardSize;
481+
}
482+
483+
@Override
484+
public String toString() {
485+
return "DiskUsageWithRelocations{" +
486+
"diskUsage=" + diskUsage +
487+
", relocatingShardSize=" + relocatingShardSize +
488+
'}';
489+
}
490+
491+
double getFreeDiskAsPercentage() {
492+
if (getTotalBytes() == 0L) {
493+
return 100.0;
494+
}
495+
return 100.0 * ((double)getFreeBytes() / getTotalBytes());
496+
}
497+
498+
double getUsedDiskAsPercentage() {
499+
return 100.0 - getFreeDiskAsPercentage();
500+
}
501+
502+
long getFreeBytes() {
503+
return diskUsage.getFreeBytes() - relocatingShardSize;
504+
}
505+
506+
String getPath() {
507+
return diskUsage.getPath();
508+
}
509+
510+
String getNodeId() {
511+
return diskUsage.getNodeId();
512+
}
513+
514+
String getNodeName() {
515+
return diskUsage.getNodeName();
516+
}
517+
518+
long getTotalBytes() {
519+
return diskUsage.getTotalBytes();
520+
}
521+
}
522+
474523
}

server/src/test/java/org/elasticsearch/cluster/routing/allocation/decider/DiskThresholdDeciderTests.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,8 @@ public void testFreeDiskPercentageAfterShardAssigned() {
630630
usages.put("node2", new DiskUsage("node2", "n2", "/dev/null", 100, 50)); // 50% used
631631
usages.put("node3", new DiskUsage("node3", "n3", "/dev/null", 100, 0)); // 100% used
632632

633-
Double after = decider.freeDiskPercentageAfterShardAssigned(new DiskUsage("node2", "n2", "/dev/null", 100, 30), 11L);
633+
Double after = decider.freeDiskPercentageAfterShardAssigned(
634+
new DiskThresholdDecider.DiskUsageWithRelocations(new DiskUsage("node2", "n2", "/dev/null", 100, 30), 0L), 11L);
634635
assertThat(after, equalTo(19.0));
635636
}
636637

0 commit comments

Comments
 (0)