blob: 362157dc3702c29a56227765f83bd2e7c575a17e [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.hdfs;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.protocol.SystemErasureCodingPolicies;
import org.apache.hadoop.hdfs.protocol.ErasureCodingPolicy;
import org.apache.hadoop.hdfs.protocol.NoECPolicySetException;
import org.apache.hadoop.io.erasurecode.CodecUtil;
import org.apache.hadoop.io.erasurecode.ErasureCodeNative;
import org.apache.hadoop.io.erasurecode.rawcoder.NativeRSRawErasureCoderFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;
import org.junit.Assert;
import java.io.FileNotFoundException;
import java.io.IOException;
import static org.apache.hadoop.test.GenericTestUtils.assertExceptionContains;
import static org.junit.Assert.fail;
/**
* Test unset and change directory's erasure coding policy.
*/
public class TestUnsetAndChangeDirectoryEcPolicy {
public static final Log LOG =
LogFactory.getLog(TestUnsetAndChangeDirectoryEcPolicy.class);
private MiniDFSCluster cluster;
private Configuration conf = new Configuration();
private DistributedFileSystem fs;
private ErasureCodingPolicy ecPolicy = StripedFileTestUtil.getDefaultECPolicy();
private final short dataBlocks = (short) ecPolicy.getNumDataUnits();
private final short parityBlocks = (short) ecPolicy.getNumParityUnits();
private final int cellSize = ecPolicy.getCellSize();
private final int stripsPerBlock = 2;
private final int blockSize = stripsPerBlock * cellSize;
private final int blockGroupSize = dataBlocks * blockSize;
@Rule
public Timeout globalTimeout = new Timeout(300000);
@Before
public void setup() throws IOException {
conf.setLong(DFSConfigKeys.DFS_BLOCK_SIZE_KEY, blockSize);
conf.setInt(DFSConfigKeys.DFS_NAMENODE_REPLICATION_MAX_STREAMS_KEY, 0);
if (ErasureCodeNative.isNativeCodeLoaded()) {
conf.set(
CodecUtil.IO_ERASURECODE_CODEC_RS_RAWCODERS_KEY,
NativeRSRawErasureCoderFactory.CODER_NAME);
}
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(
dataBlocks + parityBlocks).build();
cluster.waitActive();
fs = cluster.getFileSystem();
DFSTestUtil.enableAllECPolicies(fs);
}
@After
public void tearDown() {
if (cluster != null) {
cluster.shutdown();
cluster = null;
}
}
/*
* Test unset EC policy on directory.
*/
@Test
public void testUnsetEcPolicy() throws Exception {
final int numBlocks = 1;
final int fileLen = blockGroupSize * numBlocks;
final Path dirPath = new Path("/striped");
final Path ecFilePath = new Path(dirPath, "ec_file");
final Path replicateFilePath = new Path(dirPath, "3x_file");
fs.mkdirs(dirPath);
// Test unset a directory which has no EC policy
try {
fs.unsetErasureCodingPolicy(dirPath);
fail();
} catch (NoECPolicySetException e) {
}
// Set EC policy on directory
fs.setErasureCodingPolicy(dirPath, ecPolicy.getName());
DFSTestUtil.createFile(fs, ecFilePath, fileLen, (short) 1, 0L);
fs.unsetErasureCodingPolicy(dirPath);
DFSTestUtil.createFile(fs, replicateFilePath, fileLen, (short) 1, 0L);
// ec_file should has EC policy
ErasureCodingPolicy tempEcPolicy =
fs.getErasureCodingPolicy(ecFilePath);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ecPolicy.getName()));
// rep_file should not have EC policy
tempEcPolicy = fs.getErasureCodingPolicy(replicateFilePath);
Assert.assertNull("Replicate file should not have erasure coding policy!",
tempEcPolicy);
// Directory should not return erasure coding policy
tempEcPolicy = fs.getErasureCodingPolicy(dirPath);
Assert.assertNull("Directory should no have erasure coding policy set!",
tempEcPolicy);
fs.delete(dirPath, true);
}
/*
* Test nested directory with different EC policy.
*/
@Test
public void testNestedEcPolicy() throws Exception {
final int numBlocks = 1;
final int fileLen = blockGroupSize * numBlocks;
final Path parentDir = new Path("/ec-6-3");
final Path childDir = new Path("/ec-6-3/ec-3-2");
final Path ec63FilePath = new Path(childDir, "ec_6_3_file");
final Path ec32FilePath = new Path(childDir, "ec_3_2_file");
final Path ec63FilePath2 = new Path(childDir, "ec_6_3_file_2");
final ErasureCodingPolicy ec32Policy = SystemErasureCodingPolicies
.getByID(SystemErasureCodingPolicies.RS_3_2_POLICY_ID);
fs.mkdirs(parentDir);
fs.setErasureCodingPolicy(parentDir, ecPolicy.getName());
fs.mkdirs(childDir);
// Create RS(6,3) EC policy file
DFSTestUtil.createFile(fs, ec63FilePath, fileLen, (short) 1, 0L);
// Set RS(3,2) EC policy on child directory
fs.setErasureCodingPolicy(childDir, ec32Policy.getName());
// Create RS(3,2) EC policy file
DFSTestUtil.createFile(fs, ec32FilePath, fileLen, (short) 1, 0L);
// Start to check
// ec_6_3_file should has RS-6-3 EC policy
ErasureCodingPolicy tempEcPolicy =
fs.getErasureCodingPolicy(ec63FilePath);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ecPolicy.getName()));
// ec_3_2_file should have RS-3-2 policy
tempEcPolicy = fs.getErasureCodingPolicy(ec32FilePath);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ec32Policy.getName()));
// Child directory should have RS-3-2 policy
tempEcPolicy = fs.getErasureCodingPolicy(childDir);
Assert.assertTrue(
"Directory should have erasure coding policy set!",
tempEcPolicy.getName().equals(ec32Policy.getName()));
// Unset EC policy on child directory
fs.unsetErasureCodingPolicy(childDir);
DFSTestUtil.createFile(fs, ec63FilePath2, fileLen, (short) 1, 0L);
// ec_6_3_file_2 should have RS-6-3 policy
tempEcPolicy = fs.getErasureCodingPolicy(ec63FilePath2);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ecPolicy.getName()));
// Child directory should have RS-6-3 policy now
tempEcPolicy = fs.getErasureCodingPolicy(childDir);
Assert.assertTrue(
"Directory should have erasure coding policy set!",
tempEcPolicy.getName().equals(ecPolicy.getName()));
fs.delete(parentDir, true);
}
/*
* Test unset EC policy on root directory.
*/
@Test
public void testUnsetRootDirEcPolicy() throws Exception {
final int numBlocks = 1;
final int fileLen = blockGroupSize * numBlocks;
final Path rootPath = new Path("/");
final Path ecFilePath = new Path(rootPath, "ec_file");
final Path replicateFilePath = new Path(rootPath, "rep_file");
// Test unset root path which has no EC policy
try {
fs.unsetErasureCodingPolicy(rootPath);
fail();
} catch (NoECPolicySetException e) {
}
// Set EC policy on root path
fs.setErasureCodingPolicy(rootPath, ecPolicy.getName());
DFSTestUtil.createFile(fs, ecFilePath, fileLen, (short) 1, 0L);
fs.unsetErasureCodingPolicy(rootPath);
DFSTestUtil.createFile(fs, replicateFilePath, fileLen, (short) 1, 0L);
// ec_file should has EC policy set
ErasureCodingPolicy tempEcPolicy =
fs.getErasureCodingPolicy(ecFilePath);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ecPolicy.getName()));
// rep_file should not have EC policy set
tempEcPolicy = fs.getErasureCodingPolicy(replicateFilePath);
Assert.assertNull("Replicate file should not have erasure coding policy!",
tempEcPolicy);
// Directory should not return erasure coding policy
tempEcPolicy = fs.getErasureCodingPolicy(rootPath);
Assert.assertNull("Directory should not have erasure coding policy set!",
tempEcPolicy);
fs.delete(rootPath, true);
}
/*
* Test change EC policy on root directory.
*/
@Test
public void testChangeRootDirEcPolicy() throws Exception {
final int numBlocks = 1;
final int fileLen = blockGroupSize * numBlocks;
final Path rootPath = new Path("/");
final Path ec63FilePath = new Path(rootPath, "ec_6_3_file");
final Path ec32FilePath = new Path(rootPath, "ec_3_2_file");
final ErasureCodingPolicy ec32Policy = SystemErasureCodingPolicies
.getByID(SystemErasureCodingPolicies.RS_3_2_POLICY_ID);
try {
fs.unsetErasureCodingPolicy(rootPath);
fail();
} catch (NoECPolicySetException e) {
}
fs.setErasureCodingPolicy(rootPath, ecPolicy.getName());
// Create RS(6,3) EC policy file
DFSTestUtil.createFile(fs, ec63FilePath, fileLen, (short) 1, 0L);
// Change EC policy from RS(6,3) to RS(3,2)
fs.setErasureCodingPolicy(rootPath, ec32Policy.getName());
DFSTestUtil.createFile(fs, ec32FilePath, fileLen, (short) 1, 0L);
// start to check
// ec_6_3_file should has RS-6-3 ec policy set
ErasureCodingPolicy tempEcPolicy =
fs.getErasureCodingPolicy(ec63FilePath);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ecPolicy.getName()));
// ec_3_2_file should have RS-3-2 policy
tempEcPolicy = fs.getErasureCodingPolicy(ec32FilePath);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ec32Policy.getName()));
// Root directory should have RS-3-2 policy
tempEcPolicy = fs.getErasureCodingPolicy(rootPath);
Assert.assertTrue(
"Directory should have erasure coding policy!",
tempEcPolicy.getName().equals(ec32Policy.getName()));
fs.delete(rootPath, true);
}
/*
* Test different replica factor files.
*/
@Test
public void testDifferentReplicaFactor() throws Exception {
final int numBlocks = 1;
final int fileLen = blockGroupSize * numBlocks;
final Path ecDirPath = new Path("/striped");
final Path ecFilePath = new Path(ecDirPath, "ec_file");
final Path replicateFilePath = new Path(ecDirPath, "rep_file");
final Path replicateFilePath2 = new Path(ecDirPath, "rep_file2");
fs.mkdirs(ecDirPath);
fs.setErasureCodingPolicy(ecDirPath, ecPolicy.getName());
DFSTestUtil.createFile(fs, ecFilePath, fileLen, (short) 1, 0L);
fs.unsetErasureCodingPolicy(ecDirPath);
DFSTestUtil.createFile(fs, replicateFilePath, fileLen, (short) 3, 0L);
DFSTestUtil.createFile(fs, replicateFilePath2, fileLen, (short) 2, 0L);
// ec_file should has EC policy set
ErasureCodingPolicy tempEcPolicy =
fs.getErasureCodingPolicy(ecFilePath);
Assert.assertTrue("Erasure coding policy mismatch!",
tempEcPolicy.getName().equals(ecPolicy.getName()));
// rep_file should not have EC policy set
tempEcPolicy = fs.getErasureCodingPolicy(replicateFilePath);
Assert.assertNull("Replicate file should not have erasure coding policy!",
tempEcPolicy);
tempEcPolicy = fs.getErasureCodingPolicy(replicateFilePath2);
Assert.assertNull("Replicate file should not have erasure coding policy!",
tempEcPolicy);
// Directory should not return erasure coding policy
tempEcPolicy = fs.getErasureCodingPolicy(ecDirPath);
Assert.assertNull("Directory should not have erasure coding policy set!",
tempEcPolicy);
fs.delete(ecDirPath, true);
}
/*
* Test set and unset EC policy on directory doesn't exist.
*/
@Test
public void testNonExistentDir() throws Exception {
final Path dirPath = new Path("/striped");
// Unset EC policy on non-existent directory
try {
fs.unsetErasureCodingPolicy(dirPath);
fail("FileNotFoundException should be thrown for a non-existent"
+ " file path");
} catch (FileNotFoundException e) {
assertExceptionContains("Path not found: " + dirPath, e);
}
// Set EC policy on non-existent directory
try {
fs.setErasureCodingPolicy(dirPath, ecPolicy.getName());
fail("FileNotFoundException should be thrown for a non-existent"
+ " file path");
} catch (FileNotFoundException e) {
assertExceptionContains("Path not found: " + dirPath, e);
}
}
/*
* Test set and unset EC policy on file.
*/
@Test
public void testEcPolicyOnFile() throws Exception {
final Path ecFilePath = new Path("/striped_file");
final int fileLen = blockGroupSize * 2;
DFSTestUtil.createFile(fs, ecFilePath, fileLen, (short) 1, 0L);
// Set EC policy on file
try {
fs.setErasureCodingPolicy(ecFilePath, ecPolicy.getName());
fail("IOException should be thrown for setting EC policy on file");
} catch (IOException e) {
assertExceptionContains("Attempt to set an erasure coding policy " +
"for a file " + ecFilePath, e);
}
// Unset EC policy on file
try {
fs.unsetErasureCodingPolicy(ecFilePath);
fail("IOException should be thrown for unsetting EC policy on file");
} catch (IOException e) {
assertExceptionContains("Cannot unset an erasure coding policy on a file "
+ ecFilePath, e);
}
}
/**
* Test unsetEcPolicy is persisted correctly in edit log.
*/
@Test
public void testUnsetEcPolicyInEditLog() throws IOException {
fs.getClient().setErasureCodingPolicy("/", ecPolicy.getName());
Assert.assertEquals(ecPolicy, fs.getErasureCodingPolicy(new Path("/")));
fs.getClient().unsetErasureCodingPolicy("/");
cluster.restartNameNode(true);
Assert.assertNull(fs.getErasureCodingPolicy(new Path("/")));
}
}