Skip to content

Commit 732133c

Browse files
arp7anuengineer
authored andcommitted
HDDS-1422. Exception during DataNode shutdown. Contributed by Arpit A… (#725)
* HDDS-1422. Exception during DataNode shutdown. Contributed by Arpit Agarwal. Change-Id: I6db6bdd19839a45e5341ed7e745cd38f68af8378 * Suppress spurious findbugs warning. * Remove log file that got committed in error
1 parent 12c8161 commit 732133c

File tree

4 files changed

+32
-52
lines changed

4 files changed

+32
-52
lines changed

hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeInfo.java

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ public final class VolumeInfo {
3939
private final StorageType storageType;
4040

4141
// Space usage calculator
42-
private VolumeUsage usage;
42+
private final VolumeUsage usage;
43+
4344
// Capacity configured. This is useful when we want to
4445
// limit the visible capacity for tests. If negative, then we just
4546
// query from the filesystem.
@@ -97,36 +98,21 @@ private VolumeInfo(Builder b) throws IOException {
9798

9899
public long getCapacity() throws IOException {
99100
if (configuredCapacity < 0) {
100-
if (usage == null) {
101-
throw new IOException("Volume Usage thread is not running. This error" +
102-
" is usually seen during DataNode shutdown.");
103-
}
104101
return usage.getCapacity();
105102
}
106103
return configuredCapacity;
107104
}
108105

109106
public long getAvailable() throws IOException {
110-
if (usage == null) {
111-
throw new IOException("Volume Usage thread is not running. This error " +
112-
"is usually seen during DataNode shutdown.");
113-
}
114107
return usage.getAvailable();
115108
}
116109

117110
public long getScmUsed() throws IOException {
118-
if (usage == null) {
119-
throw new IOException("Volume Usage thread is not running. This error " +
120-
"is usually seen during DataNode shutdown.");
121-
}
122111
return usage.getScmUsed();
123112
}
124113

125114
protected void shutdownUsageThread() {
126-
if (usage != null) {
127-
usage.shutdown();
128-
}
129-
usage = null;
115+
usage.shutdown();
130116
}
131117

132118
public String getRootDir() {

hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/common/volume/VolumeUsage.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.hadoop.ozone.container.common.volume;
2020

2121
import com.google.common.annotations.VisibleForTesting;
22+
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
2223
import org.apache.hadoop.conf.Configuration;
2324
import org.apache.hadoop.fs.CachingGetSpaceUsed;
2425
import org.apache.hadoop.fs.DF;
@@ -35,6 +36,7 @@
3536
import java.io.OutputStreamWriter;
3637
import java.nio.charset.StandardCharsets;
3738
import java.util.Scanner;
39+
import java.util.concurrent.atomic.AtomicReference;
3840

3941
/**
4042
* Class that wraps the space df of the Datanode Volumes used by SCM
@@ -46,7 +48,8 @@ public class VolumeUsage {
4648
private final File rootDir;
4749
private final DF df;
4850
private final File scmUsedFile;
49-
private GetSpaceUsed scmUsage;
51+
private AtomicReference<GetSpaceUsed> scmUsage;
52+
private boolean shutdownComplete;
5053

5154
private static final String DU_CACHE_FILE = "scmUsed";
5255
private volatile boolean scmUsedSaved = false;
@@ -65,10 +68,11 @@ public class VolumeUsage {
6568

6669
void startScmUsageThread(Configuration conf) throws IOException {
6770
// get SCM specific df
68-
this.scmUsage = new CachingGetSpaceUsed.Builder().setPath(rootDir)
69-
.setConf(conf)
70-
.setInitialUsed(loadScmUsed())
71-
.build();
71+
scmUsage = new AtomicReference<>(
72+
new CachingGetSpaceUsed.Builder().setPath(rootDir)
73+
.setConf(conf)
74+
.setInitialUsed(loadScmUsed())
75+
.build());
7276
}
7377

7478
long getCapacity() {
@@ -89,14 +93,18 @@ long getAvailable() throws IOException {
8993
}
9094

9195
long getScmUsed() throws IOException{
92-
return scmUsage.getUsed();
96+
return scmUsage.get().getUsed();
9397
}
9498

95-
public void shutdown() {
96-
saveScmUsed();
99+
public synchronized void shutdown() {
100+
if (!shutdownComplete) {
101+
saveScmUsed();
97102

98-
if (scmUsage instanceof CachingGetSpaceUsed) {
99-
IOUtils.cleanupWithLogger(null, ((CachingGetSpaceUsed) scmUsage));
103+
if (scmUsage.get() instanceof CachingGetSpaceUsed) {
104+
IOUtils.cleanupWithLogger(
105+
null, ((CachingGetSpaceUsed) scmUsage.get()));
106+
}
107+
shutdownComplete = true;
100108
}
101109
}
102110

@@ -175,7 +183,11 @@ void saveScmUsed() {
175183
* Only for testing. Do not use otherwise.
176184
*/
177185
@VisibleForTesting
186+
@SuppressFBWarnings(
187+
value = "IS2_INCONSISTENT_SYNC",
188+
justification = "scmUsage is an AtomicReference. No additional " +
189+
"synchronization is needed.")
178190
public void setScmUsageForTesting(GetSpaceUsed scmUsageForTest) {
179-
this.scmUsage = scmUsageForTest;
191+
scmUsage.set(scmUsageForTest);
180192
}
181193
}

hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestHddsVolume.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,12 @@
2929
import org.mockito.Mockito;
3030

3131
import java.io.File;
32-
import java.io.IOException;
3332
import java.util.Properties;
3433
import java.util.UUID;
3534

3635
import static org.junit.Assert.assertEquals;
3736
import static org.junit.Assert.assertFalse;
3837
import static org.junit.Assert.assertTrue;
39-
import static org.junit.Assert.fail;
4038

4139
/**
4240
* Unit tests for {@link HddsVolume}.
@@ -134,15 +132,8 @@ public void testShutdown() throws Exception {
134132
assertTrue("scmUsed cache file should be saved on shutdown",
135133
scmUsedFile.exists());
136134

137-
try {
138-
// Volume.getAvailable() should fail with IOException
139-
// as usage thread is shutdown.
140-
volume.getAvailable();
141-
fail("HddsVolume#shutdown test failed");
142-
} catch (Exception ex) {
143-
assertTrue(ex instanceof IOException);
144-
assertTrue(ex.getMessage().contains(
145-
"Volume Usage thread is not running."));
146-
}
135+
// Volume.getAvailable() should succeed even when usage thread
136+
// is shutdown.
137+
volume.getAvailable();
147138
}
148139
}

hadoop-hdds/container-service/src/test/java/org/apache/hadoop/ozone/container/common/volume/TestVolumeSet.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import static org.junit.Assert.assertEquals;
3636
import static org.junit.Assert.assertFalse;
3737
import static org.junit.Assert.assertTrue;
38-
import static org.junit.Assert.fail;
3938

4039
import org.junit.After;
4140
import org.junit.Assert;
@@ -213,18 +212,10 @@ public void testShutdown() throws Exception {
213212

214213
volumeSet.shutdown();
215214

216-
// Verify that the volumes are shutdown and the volumeUsage is set to null.
215+
// Verify that volume usage can be queried during shutdown.
217216
for (HddsVolume volume : volumesList) {
218-
Assert.assertNull(volume.getVolumeInfo().getUsageForTesting());
219-
try {
220-
// getAvailable() should throw null pointer exception as usage is null.
221-
volume.getAvailable();
222-
fail("Volume shutdown failed.");
223-
} catch (IOException ex) {
224-
// Do Nothing. Exception is expected.
225-
assertTrue(ex.getMessage().contains(
226-
"Volume Usage thread is not running."));
227-
}
217+
Assert.assertNotNull(volume.getVolumeInfo().getUsageForTesting());
218+
volume.getAvailable();
228219
}
229220
}
230221

0 commit comments

Comments
 (0)