|
@@ -17,6 +17,9 @@
|
|
|
*/
|
|
|
package org.apache.hadoop.hdfs.server.balancer;
|
|
|
|
|
|
+import static org.apache.hadoop.hdfs.DFSConfigKeys.*;
|
|
|
+import static org.apache.hadoop.hdfs.StorageType.DEFAULT;
|
|
|
+import static org.apache.hadoop.hdfs.StorageType.RAM_DISK;
|
|
|
import static org.junit.Assert.assertEquals;
|
|
|
import static org.junit.Assert.assertTrue;
|
|
|
import static org.junit.Assert.fail;
|
|
@@ -41,12 +44,7 @@ import org.apache.commons.logging.impl.Log4JLogger;
|
|
|
import org.apache.hadoop.conf.Configuration;
|
|
|
import org.apache.hadoop.fs.FileSystem;
|
|
|
import org.apache.hadoop.fs.Path;
|
|
|
-import org.apache.hadoop.hdfs.DFSConfigKeys;
|
|
|
-import org.apache.hadoop.hdfs.DFSTestUtil;
|
|
|
-import org.apache.hadoop.hdfs.DFSUtil;
|
|
|
-import org.apache.hadoop.hdfs.HdfsConfiguration;
|
|
|
-import org.apache.hadoop.hdfs.MiniDFSCluster;
|
|
|
-import org.apache.hadoop.hdfs.NameNodeProxies;
|
|
|
+import org.apache.hadoop.hdfs.*;
|
|
|
import org.apache.hadoop.hdfs.protocol.Block;
|
|
|
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
|
|
|
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
|
@@ -57,6 +55,7 @@ import org.apache.hadoop.hdfs.server.balancer.Balancer.Cli;
|
|
|
import org.apache.hadoop.hdfs.server.balancer.Balancer.Parameters;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.DataNode;
|
|
|
import org.apache.hadoop.hdfs.server.datanode.SimulatedFSDataset;
|
|
|
+import org.apache.hadoop.test.GenericTestUtils;
|
|
|
import org.apache.hadoop.util.Time;
|
|
|
import org.apache.hadoop.util.Tool;
|
|
|
import org.apache.log4j.Level;
|
|
@@ -86,6 +85,7 @@ public class TestBalancer {
|
|
|
static final double CAPACITY_ALLOWED_VARIANCE = 0.005; // 0.5%
|
|
|
static final double BALANCE_ALLOWED_VARIANCE = 0.11; // 10%+delta
|
|
|
static final int DEFAULT_BLOCK_SIZE = 100;
|
|
|
+ static final int DEFAULT_RAM_DISK_BLOCK_SIZE = 5 * 1024 * 1024;
|
|
|
private static final Random r = new Random();
|
|
|
|
|
|
static {
|
|
@@ -108,6 +108,15 @@ public class TestBalancer {
|
|
|
conf.setLong(DFSConfigKeys.DFS_BALANCER_MOVEDWINWIDTH_KEY, 2000L);
|
|
|
}
|
|
|
|
|
|
+ static void initConfWithRamDisk(Configuration conf) {
|
|
|
+ conf.setLong(DFS_BLOCK_SIZE_KEY, DEFAULT_RAM_DISK_BLOCK_SIZE);
|
|
|
+ conf.setInt(DFS_NAMENODE_LAZY_PERSIST_FILE_SCRUB_INTERVAL_SEC, 3);
|
|
|
+ conf.setLong(DFS_HEARTBEAT_INTERVAL_KEY, 1);
|
|
|
+ conf.setInt(DFS_NAMENODE_HEARTBEAT_RECHECK_INTERVAL_KEY, 500);
|
|
|
+ conf.setInt(DFS_DATANODE_LAZY_WRITER_INTERVAL_SEC, 1);
|
|
|
+ conf.setInt(DFS_DATANODE_RAM_DISK_LOW_WATERMARK_REPLICAS, 1);
|
|
|
+ }
|
|
|
+
|
|
|
/* create a file with a length of <code>fileLen</code> */
|
|
|
static void createFile(MiniDFSCluster cluster, Path filePath, long fileLen,
|
|
|
short replicationFactor, int nnIndex)
|
|
@@ -1098,6 +1107,81 @@ public class TestBalancer {
|
|
|
CAPACITY, RACK2, new PortNumberBasedNodes(3, 0, 1), true, true);
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Test Balancer with Ram_Disk configured
|
|
|
+ * One DN has two files on RAM_DISK, other DN has no files on RAM_DISK.
|
|
|
+ * Then verify that the balancer does not migrate files on RAM_DISK across DN.
|
|
|
+ */
|
|
|
+ @Test(timeout=300000)
|
|
|
+ public void testBalancerWithRamDisk() throws Exception {
|
|
|
+ final int SEED = 0xFADED;
|
|
|
+ final short REPL_FACT = 1;
|
|
|
+ Configuration conf = new Configuration();
|
|
|
+ initConfWithRamDisk(conf);
|
|
|
+
|
|
|
+ final int defaultRamDiskCapacity = 10;
|
|
|
+ final int defaultDiskCapacity = 100;
|
|
|
+ final long ramDiskStorageLimit =
|
|
|
+ ((long) defaultRamDiskCapacity * DEFAULT_RAM_DISK_BLOCK_SIZE) +
|
|
|
+ (DEFAULT_RAM_DISK_BLOCK_SIZE - 1);
|
|
|
+ final long diskStorageLimit =
|
|
|
+ ((long) defaultRamDiskCapacity * DEFAULT_RAM_DISK_BLOCK_SIZE) +
|
|
|
+ (DEFAULT_RAM_DISK_BLOCK_SIZE - 1);
|
|
|
+
|
|
|
+ cluster = new MiniDFSCluster
|
|
|
+ .Builder(conf)
|
|
|
+ .numDataNodes(1)
|
|
|
+ .storageCapacities(new long[] { ramDiskStorageLimit, diskStorageLimit })
|
|
|
+ .storageTypes(new StorageType[] { RAM_DISK, DEFAULT })
|
|
|
+ .build();
|
|
|
+
|
|
|
+ try {
|
|
|
+ cluster.waitActive();
|
|
|
+ // Create few files on RAM_DISK
|
|
|
+ final String METHOD_NAME = GenericTestUtils.getMethodName();
|
|
|
+ final Path path1 = new Path("/" + METHOD_NAME + ".01.dat");
|
|
|
+ final Path path2 = new Path("/" + METHOD_NAME + ".02.dat");
|
|
|
+
|
|
|
+ DistributedFileSystem fs = cluster.getFileSystem();
|
|
|
+ DFSClient client = fs.getClient();
|
|
|
+ DFSTestUtil.createFile(fs, path1, true,
|
|
|
+ DEFAULT_RAM_DISK_BLOCK_SIZE, 4 * DEFAULT_RAM_DISK_BLOCK_SIZE,
|
|
|
+ DEFAULT_RAM_DISK_BLOCK_SIZE, REPL_FACT, SEED, true);
|
|
|
+ DFSTestUtil.createFile(fs, path1, true,
|
|
|
+ DEFAULT_RAM_DISK_BLOCK_SIZE, 1 * DEFAULT_RAM_DISK_BLOCK_SIZE,
|
|
|
+ DEFAULT_RAM_DISK_BLOCK_SIZE, REPL_FACT, SEED, true);
|
|
|
+
|
|
|
+ // Sleep for a short time to allow the lazy writer thread to do its job
|
|
|
+ Thread.sleep(6 * 1000);
|
|
|
+
|
|
|
+ // Add another fresh DN with the same type/capacity without files on RAM_DISK
|
|
|
+ StorageType[][] storageTypes = new StorageType[][] {{RAM_DISK, DEFAULT}};
|
|
|
+ long[][] storageCapacities = new long[][]{{ramDiskStorageLimit, diskStorageLimit}};
|
|
|
+ cluster.startDataNodes(conf, REPL_FACT, storageTypes, true, null,
|
|
|
+ null, null, storageCapacities, null, false, false, false, null);
|
|
|
+
|
|
|
+ cluster.triggerHeartbeats();
|
|
|
+ Collection<URI> namenodes = DFSUtil.getNsServiceRpcUris(conf);
|
|
|
+
|
|
|
+ // Run Balancer
|
|
|
+ Balancer.Parameters p = new Balancer.Parameters(
|
|
|
+ Parameters.DEFAULT.policy,
|
|
|
+ Parameters.DEFAULT.threshold,
|
|
|
+ Parameters.DEFAULT.nodesToBeExcluded,
|
|
|
+ Parameters.DEFAULT.nodesToBeIncluded);
|
|
|
+ final int r = Balancer.run(namenodes, p, conf);
|
|
|
+
|
|
|
+ // Validate no RAM_DISK block should be moved
|
|
|
+ assertEquals(ExitStatus.NO_MOVE_PROGRESS.getExitCode(), r);
|
|
|
+
|
|
|
+ // Verify files are still on RAM_DISK
|
|
|
+ DFSTestUtil.verifyFileReplicasOnStorageType(fs, client, path1, RAM_DISK);
|
|
|
+ DFSTestUtil.verifyFileReplicasOnStorageType(fs, client, path2, RAM_DISK);
|
|
|
+ } finally {
|
|
|
+ cluster.shutdown();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @param args
|
|
|
*/
|