From 728a5647c385ad74914cd1b9eebfe40d1a833523 Mon Sep 17 00:00:00 2001 From: Adrien Grand Date: Mon, 20 Jan 2014 17:52:24 +0100 Subject: [PATCH] Allow to configure indices.fielddata.breaker.limit with a ratio of the heap size. Close #4616 --- .../settings/ClusterDynamicSettingsModule.java | 4 ++-- .../cluster/settings/Validator.java | 16 +++++++++++++++- .../common/unit/MemorySizeValue.java | 13 +++++++++++-- .../breaker/InternalCircuitBreakerService.java | 15 ++++++--------- .../breaker/CircuitBreakerServiceTests.java | 12 ++++++++++-- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java b/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java index 4322b209485..200855dfe08 100644 --- a/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java +++ b/src/main/java/org/elasticsearch/cluster/settings/ClusterDynamicSettingsModule.java @@ -27,10 +27,10 @@ import org.elasticsearch.cluster.routing.allocation.decider.*; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.discovery.zen.elect.ElectMasterService; import org.elasticsearch.indices.cache.filter.IndicesFilterCache; +import org.elasticsearch.indices.fielddata.breaker.InternalCircuitBreakerService; import org.elasticsearch.indices.recovery.RecoverySettings; import org.elasticsearch.indices.store.IndicesStore; import org.elasticsearch.indices.ttl.IndicesTTLService; -import org.elasticsearch.indices.fielddata.breaker.InternalCircuitBreakerService; import org.elasticsearch.threadpool.ThreadPool; /** @@ -78,7 +78,7 @@ public class ClusterDynamicSettingsModule extends AbstractModule { clusterDynamicSettings.addDynamicSetting(DiskThresholdDecider.CLUSTER_ROUTING_ALLOCATION_DISK_THRESHOLD_ENABLED); clusterDynamicSettings.addDynamicSetting(InternalClusterInfoService.INTERNAL_CLUSTER_INFO_UPDATE_INTERVAL, Validator.TIME); clusterDynamicSettings.addDynamicSetting(SnapshotInProgressAllocationDecider.CLUSTER_ROUTING_ALLOCATION_SNAPSHOT_RELOCATION_ENABLED); - clusterDynamicSettings.addDynamicSetting(InternalCircuitBreakerService.CIRCUIT_BREAKER_MAX_BYTES_SETTING, Validator.BYTES_SIZE); + clusterDynamicSettings.addDynamicSetting(InternalCircuitBreakerService.CIRCUIT_BREAKER_MAX_BYTES_SETTING, Validator.MEMORY_SIZE); clusterDynamicSettings.addDynamicSetting(InternalCircuitBreakerService.CIRCUIT_BREAKER_OVERHEAD_SETTING, Validator.NON_NEGATIVE_DOUBLE); clusterDynamicSettings.addDynamicSetting(DestructiveOperations.REQUIRES_NAME); } diff --git a/src/main/java/org/elasticsearch/cluster/settings/Validator.java b/src/main/java/org/elasticsearch/cluster/settings/Validator.java index b3a2a0842b0..ef37b21352f 100644 --- a/src/main/java/org/elasticsearch/cluster/settings/Validator.java +++ b/src/main/java/org/elasticsearch/cluster/settings/Validator.java @@ -24,6 +24,8 @@ import org.elasticsearch.common.Booleans; import org.elasticsearch.common.unit.TimeValue; import static org.elasticsearch.common.unit.ByteSizeValue.parseBytesSizeValue; +import static org.elasticsearch.common.unit.MemorySizeValue.parseBytesSizeValueOrHeapRatio; + /** * Validates a setting, returning a failure message if applicable. @@ -184,7 +186,19 @@ public interface Validator { return null; } }; - + + public static final Validator MEMORY_SIZE = new Validator() { + @Override + public String validate(String setting, String value) { + try { + parseBytesSizeValueOrHeapRatio(value); + } catch (ElasticsearchParseException ex) { + return ex.getMessage(); + } + return null; + } + }; + public static final Validator BOOLEAN = new Validator() { @Override public String validate(String setting, String value) { diff --git a/src/main/java/org/elasticsearch/common/unit/MemorySizeValue.java b/src/main/java/org/elasticsearch/common/unit/MemorySizeValue.java index 42293b4ed47..81a293459f2 100644 --- a/src/main/java/org/elasticsearch/common/unit/MemorySizeValue.java +++ b/src/main/java/org/elasticsearch/common/unit/MemorySizeValue.java @@ -19,6 +19,7 @@ package org.elasticsearch.common.unit; +import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.monitor.jvm.JvmInfo; import static org.elasticsearch.common.unit.ByteSizeValue.parseBytesSizeValue; @@ -32,8 +33,16 @@ public enum MemorySizeValue { * the heap is 1G, 10% will be parsed as 100mb. */ public static ByteSizeValue parseBytesSizeValueOrHeapRatio(String sValue) { if (sValue.endsWith("%")) { - double percent = Double.parseDouble(sValue.substring(0, sValue.length() - 1)); - return new ByteSizeValue((long) ((percent / 100) * JvmInfo.jvmInfo().getMem().getHeapMax().bytes()), ByteSizeUnit.BYTES); + final String percentAsString = sValue.substring(0, sValue.length() - 1); + try { + final double percent = Double.parseDouble(percentAsString); + if (percent < 0 || percent > 100) { + throw new ElasticsearchParseException("Percentage should be in [0-100], got " + percentAsString); + } + return new ByteSizeValue((long) ((percent / 100) * JvmInfo.jvmInfo().getMem().getHeapMax().bytes()), ByteSizeUnit.BYTES); + } catch (NumberFormatException e) { + throw new ElasticsearchParseException("Failed to parse [" + percentAsString + "] as a double", e); + } } else { return parseBytesSizeValue(sValue); } diff --git a/src/main/java/org/elasticsearch/indices/fielddata/breaker/InternalCircuitBreakerService.java b/src/main/java/org/elasticsearch/indices/fielddata/breaker/InternalCircuitBreakerService.java index 24fe6cb1a1f..c5ac6e5f936 100644 --- a/src/main/java/org/elasticsearch/indices/fielddata/breaker/InternalCircuitBreakerService.java +++ b/src/main/java/org/elasticsearch/indices/fielddata/breaker/InternalCircuitBreakerService.java @@ -24,7 +24,6 @@ import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.ByteSizeValue; -import org.elasticsearch.monitor.jvm.JvmInfo; import org.elasticsearch.node.settings.NodeSettingsService; /** @@ -39,9 +38,7 @@ public class InternalCircuitBreakerService extends AbstractLifecycleComponent