HDFS-14631. The DirectoryScanner doesn't fix the wrongly placed replica. Contributed by Jinglun.
This commit is contained in:
parent
63531be505
commit
97600cd916
|
@ -174,7 +174,7 @@ abstract public class ReplicaInfo extends Block
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReplicaDirInfo dirInfo = parseBaseDir(dir);
|
ReplicaDirInfo dirInfo = parseBaseDir(dir, getBlockId());
|
||||||
this.hasSubdirs = dirInfo.hasSubidrs;
|
this.hasSubdirs = dirInfo.hasSubidrs;
|
||||||
|
|
||||||
synchronized (internedBaseDirs) {
|
synchronized (internedBaseDirs) {
|
||||||
|
@ -200,7 +200,7 @@ abstract public class ReplicaInfo extends Block
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static ReplicaDirInfo parseBaseDir(File dir) {
|
public static ReplicaDirInfo parseBaseDir(File dir, long blockId) {
|
||||||
|
|
||||||
File currentDir = dir;
|
File currentDir = dir;
|
||||||
boolean hasSubdirs = false;
|
boolean hasSubdirs = false;
|
||||||
|
@ -208,8 +208,15 @@ abstract public class ReplicaInfo extends Block
|
||||||
hasSubdirs = true;
|
hasSubdirs = true;
|
||||||
currentDir = currentDir.getParentFile();
|
currentDir = currentDir.getParentFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ReplicaDirInfo(currentDir.getAbsolutePath(), hasSubdirs);
|
if (hasSubdirs) {
|
||||||
|
// set baseDir to currentDir if it matches id(idToBlockDir).
|
||||||
|
File idToBlockDir = DatanodeUtil.idToBlockDir(currentDir, blockId);
|
||||||
|
if (idToBlockDir.equals(dir)) {
|
||||||
|
return new ReplicaDirInfo(currentDir.getAbsolutePath(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ReplicaDirInfo(dir.getAbsolutePath(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -25,6 +25,7 @@ import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.apache.hadoop.hdfs.protocol.Block.BLOCK_FILE_PREFIX;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -66,6 +67,7 @@ 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.FsVolumeSpi;
|
||||||
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetTestUtil;
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsDatasetTestUtil;
|
||||||
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.LazyPersistTestCase;
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.LazyPersistTestCase;
|
||||||
|
import org.apache.hadoop.hdfs.server.datanode.ReplicaInfo.ReplicaDirInfo;
|
||||||
import org.apache.hadoop.io.IOUtils;
|
import org.apache.hadoop.io.IOUtils;
|
||||||
import org.apache.hadoop.test.GenericTestUtils;
|
import org.apache.hadoop.test.GenericTestUtils;
|
||||||
import org.apache.hadoop.util.AutoCloseableLock;
|
import org.apache.hadoop.util.AutoCloseableLock;
|
||||||
|
@ -1124,6 +1126,72 @@ public class TestDirectoryScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String SEP = System.getProperty("file.separator");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test parsing LocalReplica. We should be able to find the replica's path
|
||||||
|
* even if the replica's dir doesn't match the idToBlockDir.
|
||||||
|
*/
|
||||||
|
@Test(timeout = 3000)
|
||||||
|
public void testLocalReplicaParsing() {
|
||||||
|
String baseDir = GenericTestUtils.getRandomizedTempPath();
|
||||||
|
long blkId = getRandomBlockId();
|
||||||
|
File blockDir = DatanodeUtil.idToBlockDir(new File(baseDir), blkId);
|
||||||
|
String subdir1 = new File(blockDir.getParent()).getName();
|
||||||
|
|
||||||
|
// test parsing dir without ./subdir/subdir
|
||||||
|
ReplicaDirInfo info = ReplicaInfo.parseBaseDir(new File(baseDir), blkId);
|
||||||
|
assertEquals(baseDir, info.baseDirPath);
|
||||||
|
assertEquals(false, info.hasSubidrs);
|
||||||
|
|
||||||
|
// test when path doesn't match the idToBLockDir.
|
||||||
|
String pathWithOneSubdir = baseDir + SEP + subdir1;
|
||||||
|
info = ReplicaInfo.parseBaseDir(new File(pathWithOneSubdir), blkId);
|
||||||
|
assertEquals(pathWithOneSubdir, info.baseDirPath);
|
||||||
|
assertEquals(false, info.hasSubidrs);
|
||||||
|
|
||||||
|
// test when path doesn't match the idToBlockDir.
|
||||||
|
String badPath = baseDir + SEP + subdir1 + SEP + "subdir-not-exist";
|
||||||
|
info = ReplicaInfo.parseBaseDir(new File(badPath), blkId);
|
||||||
|
assertEquals(badPath, info.baseDirPath);
|
||||||
|
assertEquals(false, info.hasSubidrs);
|
||||||
|
|
||||||
|
// test when path matches the idToBlockDir.
|
||||||
|
info = ReplicaInfo.parseBaseDir(blockDir, blkId);
|
||||||
|
assertEquals(baseDir, info.baseDirPath);
|
||||||
|
assertEquals(true, info.hasSubidrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether can LocalReplica.updateWithReplica() correct the wrongly
|
||||||
|
* recorded replica location.
|
||||||
|
*/
|
||||||
|
@Test(timeout = 3000)
|
||||||
|
public void testLocalReplicaUpdateWithReplica() throws Exception {
|
||||||
|
String baseDir = GenericTestUtils.getRandomizedTempPath();
|
||||||
|
long blkId = getRandomBlockId();
|
||||||
|
File blockDir = DatanodeUtil.idToBlockDir(new File(baseDir), blkId);
|
||||||
|
String subdir2 = blockDir.getName();
|
||||||
|
String subdir1 = new File(blockDir.getParent()).getName();
|
||||||
|
String diskSub = subdir2.equals("subdir0") ? "subdir1" : "subdir0";
|
||||||
|
|
||||||
|
// the block file on disk.
|
||||||
|
File diskBlockDir = new File(baseDir + SEP + subdir1 + SEP + diskSub);
|
||||||
|
File realBlkFile = new File(diskBlockDir, BLOCK_FILE_PREFIX + blkId);
|
||||||
|
// the block file in mem.
|
||||||
|
File memBlockDir = blockDir;
|
||||||
|
ReplicaInfo localReplica =
|
||||||
|
new FinalizedReplica(blkId, 0, 0, null, memBlockDir);
|
||||||
|
|
||||||
|
// DirectoryScanner find the inconsistent file and try to make it right
|
||||||
|
localReplica.setDir(diskBlockDir);
|
||||||
|
assertEquals(realBlkFile, localReplica.getBlockFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getRandomBlockId() {
|
||||||
|
return Math.abs(new Random().nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
private void writeFile(FileSystem fs, int numFiles) throws IOException {
|
private void writeFile(FileSystem fs, int numFiles) throws IOException {
|
||||||
final String fileName = "/" + GenericTestUtils.getMethodName();
|
final String fileName = "/" + GenericTestUtils.getMethodName();
|
||||||
final Path filePath = new Path(fileName);
|
final Path filePath = new Path(fileName);
|
||||||
|
|
Loading…
Reference in New Issue