HDDS-754. VolumeInfo#getScmUsed throws NPE.

Contributed by Hanisha Koneru.
This commit is contained in:
Anu Engineer 2018-10-30 19:17:57 -07:00
parent e33b61f335
commit 773f0d1519
7 changed files with 58 additions and 12 deletions

View File

@ -95,15 +95,30 @@ private VolumeInfo(Builder b) throws IOException {
this.usage = new VolumeUsage(root, b.conf); this.usage = new VolumeUsage(root, b.conf);
} }
public long getCapacity() { public long getCapacity() throws IOException {
return configuredCapacity < 0 ? usage.getCapacity() : configuredCapacity; if (configuredCapacity < 0) {
if (usage == null) {
throw new IOException("Volume Usage thread is not running. This error" +
" is usually seen during DataNode shutdown.");
}
return usage.getCapacity();
}
return configuredCapacity;
} }
public long getAvailable() throws IOException { public long getAvailable() throws IOException {
if (usage == null) {
throw new IOException("Volume Usage thread is not running. This error " +
"is usually seen during DataNode shutdown.");
}
return usage.getAvailable(); return usage.getAvailable();
} }
public long getScmUsed() throws IOException { public long getScmUsed() throws IOException {
if (usage == null) {
throw new IOException("Volume Usage thread is not running. This error " +
"is usually seen during DataNode shutdown.");
}
return usage.getScmUsed(); return usage.getScmUsed();
} }

View File

@ -372,18 +372,21 @@ public StorageContainerDatanodeProtocolProtos.NodeReportProto getNodeReport()
for (Map.Entry<String, HddsVolume> entry : volumeMap.entrySet()) { for (Map.Entry<String, HddsVolume> entry : volumeMap.entrySet()) {
hddsVolume = entry.getValue(); hddsVolume = entry.getValue();
VolumeInfo volumeInfo = hddsVolume.getVolumeInfo(); VolumeInfo volumeInfo = hddsVolume.getVolumeInfo();
long scmUsed = 0; long scmUsed;
long remaining = 0; long remaining;
long capacity;
failed = false; failed = false;
try { try {
scmUsed = volumeInfo.getScmUsed(); scmUsed = volumeInfo.getScmUsed();
remaining = volumeInfo.getAvailable(); remaining = volumeInfo.getAvailable();
capacity = volumeInfo.getCapacity();
} catch (IOException ex) { } catch (IOException ex) {
LOG.warn("Failed to get scmUsed and remaining for container " + LOG.warn("Failed to get scmUsed and remaining for container " +
"storage location {}", volumeInfo.getRootDir()); "storage location {}", volumeInfo.getRootDir(), ex);
// reset scmUsed and remaining if df/du failed. // reset scmUsed and remaining if df/du failed.
scmUsed = 0; scmUsed = 0;
remaining = 0; remaining = 0;
capacity = 0;
failed = true; failed = true;
} }
@ -392,7 +395,7 @@ public StorageContainerDatanodeProtocolProtos.NodeReportProto getNodeReport()
builder.setStorageLocation(volumeInfo.getRootDir()) builder.setStorageLocation(volumeInfo.getRootDir())
.setId(hddsVolume.getStorageID()) .setId(hddsVolume.getStorageID())
.setFailed(failed) .setFailed(failed)
.setCapacity(hddsVolume.getCapacity()) .setCapacity(capacity)
.setRemaining(remaining) .setRemaining(remaining)
.setScmUsed(scmUsed) .setScmUsed(scmUsed)
.setStorageType(hddsVolume.getStorageType()); .setStorageType(hddsVolume.getStorageType());

View File

@ -31,6 +31,7 @@
import org.mockito.Mockito; import org.mockito.Mockito;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; import java.util.UUID;
@ -134,12 +135,14 @@ public void testShutdown() throws Exception{
scmUsedFile.exists()); scmUsedFile.exists());
try { try {
// Volume.getAvailable() should fail with NullPointerException as usage // Volume.getAvailable() should fail with IOException
// is shutdown. // as usage thread is shutdown.
volume.getAvailable(); volume.getAvailable();
fail("HddsVolume#shutdown test failed"); fail("HddsVolume#shutdown test failed");
} catch (Exception ex){ } catch (Exception ex){
assertTrue(ex instanceof NullPointerException); assertTrue(ex instanceof IOException);
assertTrue(ex.getMessage().contains(
"Volume Usage thread is not running."));
} }
} }
} }

View File

@ -222,8 +222,10 @@ public void testShutdown() throws Exception {
// getAvailable() should throw null pointer exception as usage is null. // getAvailable() should throw null pointer exception as usage is null.
volume.getAvailable(); volume.getAvailable();
fail("Volume shutdown failed."); fail("Volume shutdown failed.");
} catch (NullPointerException ex) { } catch (IOException ex) {
// Do Nothing. Exception is expected. // Do Nothing. Exception is expected.
assertTrue(ex.getMessage().contains(
"Volume Usage thread is not running."));
} }
} }
} }

View File

@ -99,7 +99,7 @@ public static void shutdown() {
} }
} }
@Test @Test(timeout = 300_000L)
public void testPipelineFail() throws InterruptedException, IOException, public void testPipelineFail() throws InterruptedException, IOException,
TimeoutException { TimeoutException {
Assert.assertEquals(ratisContainer1.getPipeline().getPipelineState(), Assert.assertEquals(ratisContainer1.getPipeline().getPipelineState(),
@ -118,6 +118,7 @@ public void testPipelineFail() throws InterruptedException, IOException,
pipelineManager.getPipeline(ratisContainer2.getPipeline().getId()) pipelineManager.getPipeline(ratisContainer2.getPipeline().getId())
.getPipelineState()); .getPipelineState());
// Now restart the datanode and make sure that a new pipeline is created. // Now restart the datanode and make sure that a new pipeline is created.
cluster.setWaitForClusterToBeReadyTimeout(300000);
cluster.restartHddsDatanode(dnToFail, true); cluster.restartHddsDatanode(dnToFail, true);
ContainerWithPipeline ratisContainer3 = ContainerWithPipeline ratisContainer3 =
containerManager.allocateContainer(RATIS, THREE, "testOwner"); containerManager.allocateContainer(RATIS, THREE, "testOwner");

View File

@ -66,6 +66,14 @@ static Builder newBuilder(OzoneConfiguration conf) {
*/ */
void waitForClusterToBeReady() throws TimeoutException, InterruptedException; void waitForClusterToBeReady() throws TimeoutException, InterruptedException;
/**
* Sets the timeout value after which
* {@link MiniOzoneCluster#waitForClusterToBeReady} times out.
*
* @param timeoutInMs timeout value in milliseconds
*/
void setWaitForClusterToBeReadyTimeout(int timeoutInMs);
/** /**
* Waits/blocks till the cluster is out of chill mode. * Waits/blocks till the cluster is out of chill mode.
* *

View File

@ -90,6 +90,9 @@ public final class MiniOzoneClusterImpl implements MiniOzoneCluster {
private final OzoneManager ozoneManager; private final OzoneManager ozoneManager;
private final List<HddsDatanodeService> hddsDatanodes; private final List<HddsDatanodeService> hddsDatanodes;
// Timeout for the cluster to be ready
private int waitForClusterToBeReadyTimeout = 60000; // 1 min
/** /**
* Creates a new MiniOzoneCluster. * Creates a new MiniOzoneCluster.
* *
@ -122,7 +125,18 @@ public void waitForClusterToBeReady()
isReady? "Cluster is ready" : "Waiting for cluster to be ready", isReady? "Cluster is ready" : "Waiting for cluster to be ready",
healthy, hddsDatanodes.size()); healthy, hddsDatanodes.size());
return isReady; return isReady;
}, 1000, 60 * 1000); //wait for 1 min. }, 1000, waitForClusterToBeReadyTimeout);
}
/**
* Sets the timeout value after which
* {@link MiniOzoneClusterImpl#waitForClusterToBeReady} times out.
*
* @param timeoutInMs timeout value in milliseconds
*/
@Override
public void setWaitForClusterToBeReadyTimeout(int timeoutInMs) {
waitForClusterToBeReadyTimeout = timeoutInMs;
} }
/** /**