|
@@ -29,6 +29,7 @@ import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.RandomAccessFile;
|
|
|
import java.nio.ByteBuffer;
|
|
|
+import java.nio.channels.ClosedChannelException;
|
|
|
import java.nio.channels.FileChannel;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Collection;
|
|
@@ -75,6 +76,7 @@ import org.apache.hadoop.hdfs.server.datanode.Replica;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.ReplicaAlreadyExistsException;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.ReplicaBeingWritten;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.ReplicaInPipeline;
|
|
|
+import org.apache.hadoop.hdfs.server.datanode.ReplicaHandler;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.ReplicaInfo;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.ReplicaNotFoundException;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.ReplicaUnderRecovery;
|
|
@@ -82,6 +84,7 @@ import org.apache.hadoop.hdfs.server.datanode.ReplicaWaitingToBeRecovered;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.StorageLocation;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.UnexpectedReplicaStateException;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsDatasetSpi;
|
|
|
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeReference;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeSpi;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.LengthInputStream;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.ReplicaInputStreams;
|
|
@@ -137,22 +140,26 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
@Override // FsDatasetSpi
|
|
|
public StorageReport[] getStorageReports(String bpid)
|
|
|
throws IOException {
|
|
|
- StorageReport[] reports;
|
|
|
+ List<StorageReport> reports;
|
|
|
synchronized (statsLock) {
|
|
|
List<FsVolumeImpl> curVolumes = getVolumes();
|
|
|
- reports = new StorageReport[curVolumes.size()];
|
|
|
- int i = 0;
|
|
|
+ reports = new ArrayList<>(curVolumes.size());
|
|
|
for (FsVolumeImpl volume : curVolumes) {
|
|
|
- reports[i++] = new StorageReport(volume.toDatanodeStorage(),
|
|
|
- false,
|
|
|
- volume.getCapacity(),
|
|
|
- volume.getDfsUsed(),
|
|
|
- volume.getAvailable(),
|
|
|
- volume.getBlockPoolUsed(bpid));
|
|
|
+ try (FsVolumeReference ref = volume.obtainReference()) {
|
|
|
+ StorageReport sr = new StorageReport(volume.toDatanodeStorage(),
|
|
|
+ false,
|
|
|
+ volume.getCapacity(),
|
|
|
+ volume.getDfsUsed(),
|
|
|
+ volume.getAvailable(),
|
|
|
+ volume.getBlockPoolUsed(bpid));
|
|
|
+ reports.add(sr);
|
|
|
+ } catch (ClosedChannelException e) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return reports;
|
|
|
+ return reports.toArray(new StorageReport[reports.size()]);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -622,17 +629,24 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
public synchronized ReplicaInputStreams getTmpInputStreams(ExtendedBlock b,
|
|
|
long blkOffset, long ckoff) throws IOException {
|
|
|
ReplicaInfo info = getReplicaInfo(b);
|
|
|
- File blockFile = info.getBlockFile();
|
|
|
- RandomAccessFile blockInFile = new RandomAccessFile(blockFile, "r");
|
|
|
- if (blkOffset > 0) {
|
|
|
- blockInFile.seek(blkOffset);
|
|
|
- }
|
|
|
- File metaFile = info.getMetaFile();
|
|
|
- RandomAccessFile metaInFile = new RandomAccessFile(metaFile, "r");
|
|
|
- if (ckoff > 0) {
|
|
|
- metaInFile.seek(ckoff);
|
|
|
+ FsVolumeReference ref = info.getVolume().obtainReference();
|
|
|
+ try {
|
|
|
+ File blockFile = info.getBlockFile();
|
|
|
+ RandomAccessFile blockInFile = new RandomAccessFile(blockFile, "r");
|
|
|
+ if (blkOffset > 0) {
|
|
|
+ blockInFile.seek(blkOffset);
|
|
|
+ }
|
|
|
+ File metaFile = info.getMetaFile();
|
|
|
+ RandomAccessFile metaInFile = new RandomAccessFile(metaFile, "r");
|
|
|
+ if (ckoff > 0) {
|
|
|
+ metaInFile.seek(ckoff);
|
|
|
+ }
|
|
|
+ return new ReplicaInputStreams(
|
|
|
+ blockInFile.getFD(), metaInFile.getFD(), ref);
|
|
|
+ } catch (IOException e) {
|
|
|
+ IOUtils.cleanup(null, ref);
|
|
|
+ throw e;
|
|
|
}
|
|
|
- return new ReplicaInputStreams(blockInFile.getFD(), metaInFile.getFD());
|
|
|
}
|
|
|
|
|
|
static File moveBlockFiles(Block b, File srcfile, File destdir)
|
|
@@ -732,26 +746,27 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
+ replicaInfo.getVolume().getStorageType());
|
|
|
}
|
|
|
|
|
|
- FsVolumeImpl targetVolume = volumes.getNextVolume(targetStorageType,
|
|
|
- block.getNumBytes());
|
|
|
- File oldBlockFile = replicaInfo.getBlockFile();
|
|
|
- File oldMetaFile = replicaInfo.getMetaFile();
|
|
|
+ try (FsVolumeReference volumeRef = volumes.getNextVolume(
|
|
|
+ targetStorageType, block.getNumBytes())) {
|
|
|
+ File oldBlockFile = replicaInfo.getBlockFile();
|
|
|
+ File oldMetaFile = replicaInfo.getMetaFile();
|
|
|
+ FsVolumeImpl targetVolume = (FsVolumeImpl) volumeRef.getVolume();
|
|
|
+ // Copy files to temp dir first
|
|
|
+ File[] blockFiles = copyBlockFiles(block.getBlockId(),
|
|
|
+ block.getGenerationStamp(), oldMetaFile, oldBlockFile,
|
|
|
+ targetVolume.getTmpDir(block.getBlockPoolId()),
|
|
|
+ replicaInfo.isOnTransientStorage());
|
|
|
|
|
|
- // Copy files to temp dir first
|
|
|
- File[] blockFiles = copyBlockFiles(block.getBlockId(),
|
|
|
- block.getGenerationStamp(), oldMetaFile, oldBlockFile,
|
|
|
- targetVolume.getTmpDir(block.getBlockPoolId()),
|
|
|
- replicaInfo.isOnTransientStorage());
|
|
|
+ ReplicaInfo newReplicaInfo = new ReplicaInPipeline(
|
|
|
+ replicaInfo.getBlockId(), replicaInfo.getGenerationStamp(),
|
|
|
+ targetVolume, blockFiles[0].getParentFile(), 0);
|
|
|
+ newReplicaInfo.setNumBytes(blockFiles[1].length());
|
|
|
+ // Finalize the copied files
|
|
|
+ newReplicaInfo = finalizeReplica(block.getBlockPoolId(), newReplicaInfo);
|
|
|
|
|
|
- ReplicaInfo newReplicaInfo = new ReplicaInPipeline(
|
|
|
- replicaInfo.getBlockId(), replicaInfo.getGenerationStamp(),
|
|
|
- targetVolume, blockFiles[0].getParentFile(), 0);
|
|
|
- newReplicaInfo.setNumBytes(blockFiles[1].length());
|
|
|
- // Finalize the copied files
|
|
|
- newReplicaInfo = finalizeReplica(block.getBlockPoolId(), newReplicaInfo);
|
|
|
-
|
|
|
- removeOldReplica(replicaInfo, newReplicaInfo, oldBlockFile, oldMetaFile,
|
|
|
- oldBlockFile.length(), oldMetaFile.length(), block.getBlockPoolId());
|
|
|
+ removeOldReplica(replicaInfo, newReplicaInfo, oldBlockFile, oldMetaFile,
|
|
|
+ oldBlockFile.length(), oldMetaFile.length(), block.getBlockPoolId());
|
|
|
+ }
|
|
|
|
|
|
// Replace the old block if any to reschedule the scanning.
|
|
|
datanode.getBlockScanner().addBlock(block);
|
|
@@ -870,7 +885,7 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
|
|
|
|
|
|
@Override // FsDatasetSpi
|
|
|
- public synchronized ReplicaInPipeline append(ExtendedBlock b,
|
|
|
+ public synchronized ReplicaHandler append(ExtendedBlock b,
|
|
|
long newGS, long expectedBlockLen) throws IOException {
|
|
|
// If the block was successfully finalized because all packets
|
|
|
// were successfully processed at the Datanode but the ack for
|
|
@@ -895,8 +910,16 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
" expected length is " + expectedBlockLen);
|
|
|
}
|
|
|
|
|
|
- return append(b.getBlockPoolId(), (FinalizedReplica)replicaInfo, newGS,
|
|
|
- b.getNumBytes());
|
|
|
+ FsVolumeReference ref = replicaInfo.getVolume().obtainReference();
|
|
|
+ ReplicaBeingWritten replica = null;
|
|
|
+ try {
|
|
|
+ replica = append(b.getBlockPoolId(), (FinalizedReplica)replicaInfo, newGS,
|
|
|
+ b.getNumBytes());
|
|
|
+ } catch (IOException e) {
|
|
|
+ IOUtils.cleanup(null, ref);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ return new ReplicaHandler(replica, ref);
|
|
|
}
|
|
|
|
|
|
/** Append to a finalized replica
|
|
@@ -1017,22 +1040,30 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
|
|
|
return replicaInfo;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@Override // FsDatasetSpi
|
|
|
- public synchronized ReplicaInPipeline recoverAppend(ExtendedBlock b,
|
|
|
- long newGS, long expectedBlockLen) throws IOException {
|
|
|
+ public synchronized ReplicaHandler recoverAppend(
|
|
|
+ ExtendedBlock b, long newGS, long expectedBlockLen) throws IOException {
|
|
|
LOG.info("Recover failed append to " + b);
|
|
|
|
|
|
ReplicaInfo replicaInfo = recoverCheck(b, newGS, expectedBlockLen);
|
|
|
|
|
|
- // change the replica's state/gs etc.
|
|
|
- if (replicaInfo.getState() == ReplicaState.FINALIZED ) {
|
|
|
- return append(b.getBlockPoolId(), (FinalizedReplica) replicaInfo, newGS,
|
|
|
- b.getNumBytes());
|
|
|
- } else { //RBW
|
|
|
- bumpReplicaGS(replicaInfo, newGS);
|
|
|
- return (ReplicaBeingWritten)replicaInfo;
|
|
|
+ FsVolumeReference ref = replicaInfo.getVolume().obtainReference();
|
|
|
+ ReplicaBeingWritten replica;
|
|
|
+ try {
|
|
|
+ // change the replica's state/gs etc.
|
|
|
+ if (replicaInfo.getState() == ReplicaState.FINALIZED) {
|
|
|
+ replica = append(b.getBlockPoolId(), (FinalizedReplica) replicaInfo,
|
|
|
+ newGS, b.getNumBytes());
|
|
|
+ } else { //RBW
|
|
|
+ bumpReplicaGS(replicaInfo, newGS);
|
|
|
+ replica = (ReplicaBeingWritten) replicaInfo;
|
|
|
+ }
|
|
|
+ } catch (IOException e) {
|
|
|
+ IOUtils.cleanup(null, ref);
|
|
|
+ throw e;
|
|
|
}
|
|
|
+ return new ReplicaHandler(replica, ref);
|
|
|
}
|
|
|
|
|
|
@Override // FsDatasetSpi
|
|
@@ -1080,8 +1111,9 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
}
|
|
|
|
|
|
@Override // FsDatasetSpi
|
|
|
- public synchronized ReplicaInPipeline createRbw(StorageType storageType,
|
|
|
- ExtendedBlock b, boolean allowLazyPersist) throws IOException {
|
|
|
+ public synchronized ReplicaHandler createRbw(
|
|
|
+ StorageType storageType, ExtendedBlock b, boolean allowLazyPersist)
|
|
|
+ throws IOException {
|
|
|
ReplicaInfo replicaInfo = volumeMap.get(b.getBlockPoolId(),
|
|
|
b.getBlockId());
|
|
|
if (replicaInfo != null) {
|
|
@@ -1090,15 +1122,15 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
" and thus cannot be created.");
|
|
|
}
|
|
|
// create a new block
|
|
|
- FsVolumeImpl v;
|
|
|
+ FsVolumeReference ref;
|
|
|
while (true) {
|
|
|
try {
|
|
|
if (allowLazyPersist) {
|
|
|
// First try to place the block on a transient volume.
|
|
|
- v = volumes.getNextTransientVolume(b.getNumBytes());
|
|
|
+ ref = volumes.getNextTransientVolume(b.getNumBytes());
|
|
|
datanode.getMetrics().incrRamDiskBlocksWrite();
|
|
|
} else {
|
|
|
- v = volumes.getNextVolume(storageType, b.getNumBytes());
|
|
|
+ ref = volumes.getNextVolume(storageType, b.getNumBytes());
|
|
|
}
|
|
|
} catch (DiskOutOfSpaceException de) {
|
|
|
if (allowLazyPersist) {
|
|
@@ -1110,18 +1142,25 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
+ FsVolumeImpl v = (FsVolumeImpl) ref.getVolume();
|
|
|
// create an rbw file to hold block in the designated volume
|
|
|
- File f = v.createRbwFile(b.getBlockPoolId(), b.getLocalBlock());
|
|
|
+ File f;
|
|
|
+ try {
|
|
|
+ f = v.createRbwFile(b.getBlockPoolId(), b.getLocalBlock());
|
|
|
+ } catch (IOException e) {
|
|
|
+ IOUtils.cleanup(null, ref);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+
|
|
|
ReplicaBeingWritten newReplicaInfo = new ReplicaBeingWritten(b.getBlockId(),
|
|
|
b.getGenerationStamp(), v, f.getParentFile(), b.getNumBytes());
|
|
|
volumeMap.add(b.getBlockPoolId(), newReplicaInfo);
|
|
|
-
|
|
|
- return newReplicaInfo;
|
|
|
+ return new ReplicaHandler(newReplicaInfo, ref);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
@Override // FsDatasetSpi
|
|
|
- public synchronized ReplicaInPipeline recoverRbw(ExtendedBlock b,
|
|
|
- long newGS, long minBytesRcvd, long maxBytesRcvd)
|
|
|
+ public synchronized ReplicaHandler recoverRbw(
|
|
|
+ ExtendedBlock b, long newGS, long minBytesRcvd, long maxBytesRcvd)
|
|
|
throws IOException {
|
|
|
LOG.info("Recover RBW replica " + b);
|
|
|
|
|
@@ -1160,20 +1199,25 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
minBytesRcvd + ", " + maxBytesRcvd + "].");
|
|
|
}
|
|
|
|
|
|
- // Truncate the potentially corrupt portion.
|
|
|
- // If the source was client and the last node in the pipeline was lost,
|
|
|
- // any corrupt data written after the acked length can go unnoticed.
|
|
|
- if (numBytes > bytesAcked) {
|
|
|
- final File replicafile = rbw.getBlockFile();
|
|
|
- truncateBlock(replicafile, rbw.getMetaFile(), numBytes, bytesAcked);
|
|
|
- rbw.setNumBytes(bytesAcked);
|
|
|
- rbw.setLastChecksumAndDataLen(bytesAcked, null);
|
|
|
- }
|
|
|
+ FsVolumeReference ref = rbw.getVolume().obtainReference();
|
|
|
+ try {
|
|
|
+ // Truncate the potentially corrupt portion.
|
|
|
+ // If the source was client and the last node in the pipeline was lost,
|
|
|
+ // any corrupt data written after the acked length can go unnoticed.
|
|
|
+ if (numBytes > bytesAcked) {
|
|
|
+ final File replicafile = rbw.getBlockFile();
|
|
|
+ truncateBlock(replicafile, rbw.getMetaFile(), numBytes, bytesAcked);
|
|
|
+ rbw.setNumBytes(bytesAcked);
|
|
|
+ rbw.setLastChecksumAndDataLen(bytesAcked, null);
|
|
|
+ }
|
|
|
|
|
|
- // bump the replica's generation stamp to newGS
|
|
|
- bumpReplicaGS(rbw, newGS);
|
|
|
-
|
|
|
- return rbw;
|
|
|
+ // bump the replica's generation stamp to newGS
|
|
|
+ bumpReplicaGS(rbw, newGS);
|
|
|
+ } catch (IOException e) {
|
|
|
+ IOUtils.cleanup(null, ref);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+ return new ReplicaHandler(rbw, ref);
|
|
|
}
|
|
|
|
|
|
@Override // FsDatasetSpi
|
|
@@ -1238,8 +1282,8 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
}
|
|
|
|
|
|
@Override // FsDatasetSpi
|
|
|
- public synchronized ReplicaInPipeline createTemporary(StorageType storageType,
|
|
|
- ExtendedBlock b) throws IOException {
|
|
|
+ public synchronized ReplicaHandler createTemporary(
|
|
|
+ StorageType storageType, ExtendedBlock b) throws IOException {
|
|
|
ReplicaInfo replicaInfo = volumeMap.get(b.getBlockPoolId(), b.getBlockId());
|
|
|
if (replicaInfo != null) {
|
|
|
if (replicaInfo.getGenerationStamp() < b.getGenerationStamp()
|
|
@@ -1254,14 +1298,22 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
" and thus cannot be created.");
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- FsVolumeImpl v = volumes.getNextVolume(storageType, b.getNumBytes());
|
|
|
+
|
|
|
+ FsVolumeReference ref = volumes.getNextVolume(storageType, b.getNumBytes());
|
|
|
+ FsVolumeImpl v = (FsVolumeImpl) ref.getVolume();
|
|
|
// create a temporary file to hold block in the designated volume
|
|
|
- File f = v.createTmpFile(b.getBlockPoolId(), b.getLocalBlock());
|
|
|
+ File f;
|
|
|
+ try {
|
|
|
+ f = v.createTmpFile(b.getBlockPoolId(), b.getLocalBlock());
|
|
|
+ } catch (IOException e) {
|
|
|
+ IOUtils.cleanup(null, ref);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+
|
|
|
ReplicaInPipeline newReplicaInfo = new ReplicaInPipeline(b.getBlockId(),
|
|
|
b.getGenerationStamp(), v, f.getParentFile(), 0);
|
|
|
volumeMap.add(b.getBlockPoolId(), newReplicaInfo);
|
|
|
- return newReplicaInfo;
|
|
|
+ return new ReplicaHandler(newReplicaInfo, ref);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1644,10 +1696,15 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
// Delete the block asynchronously to make sure we can do it fast enough.
|
|
|
// It's ok to unlink the block file before the uncache operation
|
|
|
// finishes.
|
|
|
- asyncDiskService.deleteAsync(v, f,
|
|
|
- FsDatasetUtil.getMetaFile(f, invalidBlks[i].getGenerationStamp()),
|
|
|
- new ExtendedBlock(bpid, invalidBlks[i]),
|
|
|
- dataStorage.getTrashDirectoryForBlockFile(bpid, f));
|
|
|
+ try {
|
|
|
+ asyncDiskService.deleteAsync(v.obtainReference(), f,
|
|
|
+ FsDatasetUtil.getMetaFile(f, invalidBlks[i].getGenerationStamp()),
|
|
|
+ new ExtendedBlock(bpid, invalidBlks[i]),
|
|
|
+ dataStorage.getTrashDirectoryForBlockFile(bpid, f));
|
|
|
+ } catch (ClosedChannelException e) {
|
|
|
+ LOG.warn("Volume " + v + " is closed, ignore the deletion task for " +
|
|
|
+ "block " + invalidBlks[i]);
|
|
|
+ }
|
|
|
}
|
|
|
if (!errors.isEmpty()) {
|
|
|
StringBuilder b = new StringBuilder("Failed to delete ")
|
|
@@ -2282,14 +2339,17 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
ReplicaUnderRecovery replicaInfo, String bpid, long newBlkId, long newGS)
|
|
|
throws IOException {
|
|
|
String blockFileName = Block.BLOCK_FILE_PREFIX + newBlkId;
|
|
|
- FsVolumeImpl v = volumes.getNextVolume(
|
|
|
- replicaInfo.getVolume().getStorageType(), replicaInfo.getNumBytes());
|
|
|
- final File tmpDir = v.getBlockPoolSlice(bpid).getTmpDir();
|
|
|
- final File destDir = DatanodeUtil.idToBlockDir(tmpDir, newBlkId);
|
|
|
- final File dstBlockFile = new File(destDir, blockFileName);
|
|
|
- final File dstMetaFile = FsDatasetUtil.getMetaFile(dstBlockFile, newGS);
|
|
|
- return copyBlockFiles(replicaInfo.getMetaFile(), replicaInfo.getBlockFile(),
|
|
|
- dstMetaFile, dstBlockFile, true);
|
|
|
+ try (FsVolumeReference ref = volumes.getNextVolume(
|
|
|
+ replicaInfo.getVolume().getStorageType(), replicaInfo.getNumBytes())) {
|
|
|
+ FsVolumeImpl v = (FsVolumeImpl) ref.getVolume();
|
|
|
+ final File tmpDir = v.getBlockPoolSlice(bpid).getTmpDir();
|
|
|
+ final File destDir = DatanodeUtil.idToBlockDir(tmpDir, newBlkId);
|
|
|
+ final File dstBlockFile = new File(destDir, blockFileName);
|
|
|
+ final File dstMetaFile = FsDatasetUtil.getMetaFile(dstBlockFile, newGS);
|
|
|
+ return copyBlockFiles(replicaInfo.getMetaFile(),
|
|
|
+ replicaInfo.getBlockFile(),
|
|
|
+ dstMetaFile, dstBlockFile, true);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override // FsDatasetSpi
|
|
@@ -2345,9 +2405,11 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
for (FsVolumeImpl volume : getVolumes()) {
|
|
|
long used = 0;
|
|
|
long free = 0;
|
|
|
- try {
|
|
|
+ try (FsVolumeReference ref = volume.obtainReference()) {
|
|
|
used = volume.getDfsUsed();
|
|
|
free = volume.getAvailable();
|
|
|
+ } catch (ClosedChannelException e) {
|
|
|
+ continue;
|
|
|
} catch (IOException e) {
|
|
|
LOG.warn(e.getMessage());
|
|
|
used = 0;
|
|
@@ -2379,15 +2441,23 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
List<FsVolumeImpl> curVolumes = getVolumes();
|
|
|
if (!force) {
|
|
|
for (FsVolumeImpl volume : curVolumes) {
|
|
|
- if (!volume.isBPDirEmpty(bpid)) {
|
|
|
- LOG.warn(bpid + " has some block files, cannot delete unless forced");
|
|
|
- throw new IOException("Cannot delete block pool, "
|
|
|
- + "it contains some block files");
|
|
|
+ try (FsVolumeReference ref = volume.obtainReference()) {
|
|
|
+ if (!volume.isBPDirEmpty(bpid)) {
|
|
|
+ LOG.warn(bpid + " has some block files, cannot delete unless forced");
|
|
|
+ throw new IOException("Cannot delete block pool, "
|
|
|
+ + "it contains some block files");
|
|
|
+ }
|
|
|
+ } catch (ClosedChannelException e) {
|
|
|
+ // ignore.
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
for (FsVolumeImpl volume : curVolumes) {
|
|
|
- volume.deleteBPDirectories(bpid, force);
|
|
|
+ try (FsVolumeReference ref = volume.obtainReference()) {
|
|
|
+ volume.deleteBPDirectories(bpid, force);
|
|
|
+ } catch (ClosedChannelException e) {
|
|
|
+ // ignore.
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2620,6 +2690,7 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
*/
|
|
|
private boolean saveNextReplica() {
|
|
|
RamDiskReplica block = null;
|
|
|
+ FsVolumeReference targetReference;
|
|
|
FsVolumeImpl targetVolume;
|
|
|
ReplicaInfo replicaInfo;
|
|
|
boolean succeeded = false;
|
|
@@ -2637,8 +2708,9 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
if (replicaInfo != null &&
|
|
|
replicaInfo.getVolume().isTransientStorage()) {
|
|
|
// Pick a target volume to persist the block.
|
|
|
- targetVolume = volumes.getNextVolume(
|
|
|
+ targetReference = volumes.getNextVolume(
|
|
|
StorageType.DEFAULT, replicaInfo.getNumBytes());
|
|
|
+ targetVolume = (FsVolumeImpl) targetReference.getVolume();
|
|
|
|
|
|
ramDiskReplicaTracker.recordStartLazyPersist(
|
|
|
block.getBlockPoolId(), block.getBlockId(), targetVolume);
|
|
@@ -2654,7 +2726,7 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
block.getBlockPoolId(), block.getBlockId(),
|
|
|
replicaInfo.getGenerationStamp(), block.getCreationTime(),
|
|
|
replicaInfo.getMetaFile(), replicaInfo.getBlockFile(),
|
|
|
- targetVolume);
|
|
|
+ targetReference);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -2678,9 +2750,13 @@ class FsDatasetImpl implements FsDatasetSpi<FsVolumeImpl> {
|
|
|
// Don't worry about fragmentation for now. We don't expect more than one
|
|
|
// transient volume per DN.
|
|
|
for (FsVolumeImpl v : getVolumes()) {
|
|
|
- if (v.isTransientStorage()) {
|
|
|
- capacity += v.getCapacity();
|
|
|
- free += v.getAvailable();
|
|
|
+ try (FsVolumeReference ref = v.obtainReference()) {
|
|
|
+ if (v.isTransientStorage()) {
|
|
|
+ capacity += v.getCapacity();
|
|
|
+ free += v.getAvailable();
|
|
|
+ }
|
|
|
+ } catch (ClosedChannelException e) {
|
|
|
+ // ignore.
|
|
|
}
|
|
|
}
|
|
|
|