[
https://issues.apache.org/jira/browse/GEODE-3976?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16286522#comment-16286522
]
ASF GitHub Bot commented on GEODE-3976:
---------------------------------------
dschneider-pivotal closed pull request #1146: GEODE-3976: improve exception
message
URL: https://github.com/apache/geode/pull/1146
This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:
As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreMonitor.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreMonitor.java
index 410bc3ab39..37f4e94dda 100644
---
a/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreMonitor.java
+++
b/geode-core/src/main/java/org/apache/geode/internal/cache/DiskStoreMonitor.java
@@ -262,11 +262,12 @@ public DiskState update(float warning, float critical) {
return current;
}
- long min = getMinimumSpace();
+ long minMegabytes = getMinimumSpace();
+ final long minBytes = minMegabytes * 1024 * 1024;
if (logger.isTraceEnabled(LogMarker.DISK_STORE_MONITOR)) {
logger.trace(LogMarker.DISK_STORE_MONITOR,
"Checking usage for directory {}, minimum free space is {} MB",
dir().getAbsolutePath(),
- min);
+ minMegabytes);
}
long start = System.nanoTime();
@@ -284,7 +285,7 @@ public DiskState update(float warning, float critical) {
remaining, total, pct);
}
- boolean belowMin = remaining < 1024 * 1024 * min;
+ boolean belowMin = remaining < minBytes;
DiskState next = DiskState.select(use, warning, critical, belowMin);
if (next == current) {
return next;
@@ -294,7 +295,17 @@ public DiskState update(float warning, float critical) {
state = next;
}
- handleStateChange(next, pct);
+ String criticalMessage = null;
+ if (next == DiskState.CRITICAL) {
+ if (belowMin) {
+ criticalMessage = "the file system only has " + remaining
+ + " bytes free which is below the minimum of " + minBytes + ".";
+ } else {
+ criticalMessage = "the file system is " + pct
+ + " full, which exceeds the critical threshold of " + critical +
"%.";
+ }
+ }
+ handleStateChange(next, pct, criticalMessage);
return next;
}
@@ -304,7 +315,7 @@ public DiskState update(float warning, float critical) {
protected abstract void recordStats(long total, long free, long elapsed);
- protected abstract void handleStateChange(DiskState next, String pct);
+ protected abstract void handleStateChange(DiskState next, String pct,
String criticalMessage);
}
static class LogUsage extends DiskUsage {
@@ -314,7 +325,7 @@ public LogUsage(File dir) {
this.dir = dir;
}
- protected void handleStateChange(DiskState next, String pct) {
+ protected void handleStateChange(DiskState next, String pct, String
critcalMessage) {
Object[] args = new Object[] {dir.getAbsolutePath(), pct};
switch (next) {
case NORMAL:
@@ -353,7 +364,7 @@ public DirectoryHolderUsage(DiskStoreImpl disk,
DirectoryHolder dir) {
this.dir = dir;
}
- protected void handleStateChange(DiskState next, String pct) {
+ protected void handleStateChange(DiskState next, String pct, String
criticalMessage) {
if (_testAction != null) {
logger.info(LogMarker.DISK_STORE_MONITOR, "Invoking test handler for
state change to {}",
next);
@@ -361,8 +372,6 @@ protected void handleStateChange(DiskState next, String
pct) {
}
Object[] args = new Object[] {dir.getDir(), disk.getName(), pct};
- String msg = "Critical disk usage threshold exceeded for volume "
- + dir.getDir().getAbsolutePath() + ": " + pct + " full";
switch (next) {
case NORMAL:
@@ -383,8 +392,8 @@ protected void handleStateChange(DiskState next, String
pct) {
case CRITICAL:
logger.error(LogMarker.DISK_STORE_MONITOR,
LocalizedMessage.create(LocalizedStrings.DiskStoreMonitor_DISK_CRITICAL, args));
-
- // TODO: this is weird...
+ String msg = "Critical disk usage threshold exceeded for volume "
+ + dir.getDir().getAbsolutePath() + ": " + criticalMessage;
disk.handleDiskAccessException(new DiskAccessException(msg, disk));
break;
}
diff --git
a/geode-core/src/test/java/org/apache/geode/internal/cache/DiskUsageTest.java
b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskUsageTest.java
new file mode 100644
index 0000000000..6c3cefa3ac
--- /dev/null
+++
b/geode-core/src/test/java/org/apache/geode/internal/cache/DiskUsageTest.java
@@ -0,0 +1,255 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+package org.apache.geode.internal.cache;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.internal.cache.DiskStoreMonitor.DiskState;
+import org.apache.geode.internal.cache.DiskStoreMonitor.DiskUsage;
+import org.apache.geode.test.junit.categories.UnitTest;
+
+@Category(UnitTest.class)
+public class DiskUsageTest {
+
+ @Test
+ public void defaultStateIsNormal() {
+ DiskUsage diskUsage = new TestableDiskUsage();
+ assertThat(diskUsage.getState()).isEqualTo(DiskState.NORMAL);
+ }
+
+ @Test
+ public void updateReturnsCurrentStateIfThresholdsDisabled() {
+ DiskUsage diskUsage = new TestableDiskUsage();
+ assertThat(diskUsage.update(0.0f, 0.0f)).isEqualTo(DiskState.NORMAL);
+ }
+
+ @Test
+ public void updateReturnsCurrentStateIfDirectoryDoesNotExist() {
+ File dir = mock(File.class);
+ DiskUsage diskUsage = new TestableDiskUsage(dir);
+ assertThat(diskUsage.update(1.0f, 0.0f)).isEqualTo(DiskState.NORMAL);
+ verify(dir, times(1)).exists();
+ }
+
+ @Test
+ public void updateSendsTotalToRecordsStats() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ final long expectedTotal = 123;
+ when(dir.getTotalSpace()).thenReturn(expectedTotal);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir);
+ diskUsage.update(0.0f, 1.0f);
+ assertThat(diskUsage.getTotal()).isEqualTo(expectedTotal);
+ }
+
+ @Test
+ public void updateSendsUsableSpaceToRecordsStats() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ final long expectedFree = 456;
+ when(dir.getUsableSpace()).thenReturn(expectedFree);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir);
+ diskUsage.update(0.0f, 1.0f);
+ assertThat(diskUsage.getFree()).isEqualTo(expectedFree);
+ }
+
+ @Test
+ public void updateChangesStateToWarn() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ // File indicates 2% of disk used
+ when(dir.getTotalSpace()).thenReturn(100L);
+ when(dir.getUsableSpace()).thenReturn(98L);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir);
+ // warn if over 1.9% used
+ assertThat(diskUsage.update(1.9f, 0.0f)).isEqualTo(DiskState.WARN);
+ assertThat(diskUsage.getNext()).isEqualTo(DiskState.WARN);
+ assertThat(diskUsage.getPct()).isEqualTo("2%");
+ assertThat(diskUsage.getCriticalMessage()).isNull();
+ }
+
+ @Test
+ public void updateStaysNormalIfBelowWarnThreshold() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ // File indicates 2% of disk used
+ when(dir.getTotalSpace()).thenReturn(100L);
+ when(dir.getUsableSpace()).thenReturn(98L);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir);
+ // warn if over 2.1% used
+ assertThat(diskUsage.update(2.1f, 0.0f)).isEqualTo(DiskState.NORMAL);
+ assertThat(diskUsage.getNext()).isNull();
+ assertThat(diskUsage.getPct()).isNull();
+ assertThat(diskUsage.getCriticalMessage()).isNull();
+ }
+
+ @Test
+ public void updateWarnThresholdIgnoresMinimum() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ // File indicates 2% of disk used
+ when(dir.getTotalSpace()).thenReturn(100L);
+ when(dir.getUsableSpace()).thenReturn(98L);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir, 1);
+ // warn if over 2.1% used
+ assertThat(diskUsage.update(2.1f, 0.0f)).isEqualTo(DiskState.NORMAL);
+ assertThat(diskUsage.getNext()).isNull();
+ assertThat(diskUsage.getPct()).isNull();
+ assertThat(diskUsage.getCriticalMessage()).isNull();
+ }
+
+ @Test
+ public void updateChangesStateToCritical() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ // File indicates 2% of disk used
+ when(dir.getTotalSpace()).thenReturn(100L);
+ when(dir.getUsableSpace()).thenReturn(98L);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir);
+ // critical if over 1.9% used
+ assertThat(diskUsage.update(0.0f, 1.9f)).isEqualTo(DiskState.CRITICAL);
+ assertThat(diskUsage.getNext()).isEqualTo(DiskState.CRITICAL);
+ assertThat(diskUsage.getPct()).isEqualTo("2%");
+ assertThat(diskUsage.getCriticalMessage())
+ .isEqualTo("the file system is 2% full, which exceeds the critical
threshold of 1.9%.");
+ }
+
+ @Test
+ public void updateStaysNormalIfBelowCriticalThreshold() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ // File indicates 2% of disk used
+ when(dir.getTotalSpace()).thenReturn(100L);
+ when(dir.getUsableSpace()).thenReturn(98L);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir);
+ // critical if over 2.1% used
+ assertThat(diskUsage.update(0.0f, 2.1f)).isEqualTo(DiskState.NORMAL);
+ assertThat(diskUsage.getNext()).isNull();
+ assertThat(diskUsage.getPct()).isNull();
+ assertThat(diskUsage.getCriticalMessage()).isNull();
+ }
+
+ @Test
+ public void updateCriticalThresholdGoesCriticalIfBelowMinimum() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ // File indicates 2% of disk used
+ when(dir.getTotalSpace()).thenReturn(100L);
+ when(dir.getUsableSpace()).thenReturn(98L);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir, 1/* one megabyte
*/);
+ // critical if over 2.1% used
+ assertThat(diskUsage.update(0.0f, 2.1f)).isEqualTo(DiskState.CRITICAL);
+ assertThat(diskUsage.getNext()).isEqualTo(DiskState.CRITICAL);
+ assertThat(diskUsage.getPct()).isEqualTo("2%");
+ assertThat(diskUsage.getCriticalMessage())
+ .isEqualTo("the file system only has 98 bytes free which is below the
minimum of 1048576.");
+ }
+
+ @Test
+ public void updateCriticalThresholdStaysNormalIfFreeSpaceAboveMinimum() {
+ File dir = mock(File.class);
+ when(dir.exists()).thenReturn(true);
+ // File indicates 98% of disk used
+ when(dir.getTotalSpace()).thenReturn(100L * 1024 * 1024);
+ when(dir.getUsableSpace()).thenReturn(2L * 1024 * 1024);
+ TestableDiskUsage diskUsage = new TestableDiskUsage(dir, 1/* one megabyte
*/);
+ // critical if over 98.1% used
+ assertThat(diskUsage.update(0.0f, 98.1f)).isEqualTo(DiskState.NORMAL);
+ assertThat(diskUsage.getNext()).isNull();
+ assertThat(diskUsage.getPct()).isNull();
+ assertThat(diskUsage.getCriticalMessage()).isNull();
+ }
+
+ private static class TestableDiskUsage extends DiskUsage {
+
+ private final File dir;
+ private final long minimum;
+
+ private long total;
+ private long free;
+ private long elapsed;
+ private DiskState next;
+ private String pct;
+ private String criticalMessage;
+
+ public TestableDiskUsage(File dir, long min) {
+ this.dir = dir;
+ this.minimum = min;
+ }
+
+ public TestableDiskUsage(File dir) {
+ this.dir = dir;
+ this.minimum = 0L;
+ }
+
+ public TestableDiskUsage() {
+ this.dir = null;
+ this.minimum = 0L;
+ }
+
+ @Override
+ protected File dir() {
+ return this.dir;
+ }
+
+ @Override
+ protected long getMinimumSpace() {
+ return this.minimum;
+ }
+
+ @Override
+ protected void recordStats(long total, long free, long elapsed) {
+ this.total = total;
+ this.free = free;
+ this.elapsed = elapsed;
+ }
+
+ @Override
+ protected void handleStateChange(DiskState next, String pct, String
criticalMessage) {
+ this.next = next;
+ this.pct = pct;
+ this.criticalMessage = criticalMessage;
+ }
+
+ public long getTotal() {
+ return this.total;
+ }
+
+ public long getFree() {
+ return this.free;
+ }
+
+ public DiskState getNext() {
+ return this.next;
+ }
+
+ public String getPct() {
+ return this.pct;
+ }
+
+ public String getCriticalMessage() {
+ return this.criticalMessage;
+ }
+ }
+}
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]
> Users want more meaningful oplog warning when creating 1GB persistent disk
> --------------------------------------------------------------------------
>
> Key: GEODE-3976
> URL: https://issues.apache.org/jira/browse/GEODE-3976
> Project: Geode
> Issue Type: Improvement
> Components: persistence
> Reporter: Fred Krone
> Assignee: Darrel Schneider
>
> Documentation: creating a server with 1GB persistent disk fails because
> GemFire creates a 1GB oplog by default
> When a 1GB persistent disk is created an obscure gemfire error message:
> DiskStore: DEFAULT: Critical disk usage threshold exceeded for volume
> /var/vcap/store/gemfire-server/.: 10% full
> at
> org.apache.geode.internal.cache.DiskStoreMonitor$DirectoryHolderUsage.handleStateChange(DiskStoreMonitor.java:393)
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)