package org.apache.hadoop.raid.tools;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.DistributedRaidFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.RaidDFSUtil;
import org.apache.hadoop.hdfs.TestRaidDfs;
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
import org.apache.hadoop.raid.Codec;
import org.apache.hadoop.raid.ParityFilePair;
import org.apache.hadoop.raid.RaidNode;
import org.apache.hadoop.raid.RaidUtils;
import org.apache.hadoop.raid.TestDirectoryRaidDfs;
import org.apache.hadoop.raid.Utils;
import junit.framework.TestCase;
public class TestFastFileCheck extends TestCase {
final static String TEST_DIR = new File(
System.getProperty("test.build.data",
"build/contrib/raid/test/data")).getAbsolutePath();
final static String CHECKSUM_STORE_DIR = new File(TEST_DIR,
"ckm_store." + System.currentTimeMillis()).getAbsolutePath();
final static String STRIPE_STORE_DIR = new File(TEST_DIR,
"stripe_store." + System.currentTimeMillis()).getAbsolutePath();
final static String CONFIG_FILE = new File(TEST_DIR,
"test-raid.xml").getAbsolutePath();
final static long RELOAD_INTERVAL = 1000;
final static Log LOG = LogFactory.getLog(
"org.apache.hadoop.raid.tools.TestFastFileCheck");
final static Random rand = new Random();
final static int NUM_DATANODES = 3;
final long blockSize = 8192L;
final long[] fileSizes =
new long[]{blockSize + blockSize/2, // block 0, 1
3*blockSize, // block 2, 3
blockSize + blockSize/2 + 1}; // block 4, 5, 6, 7
final long[] blockSizes = new long[]{blockSize, 2*blockSize, blockSize/2};
Configuration conf;
String namenode = null;
String hftp = null;
MiniDFSCluster dfs = null;
FileSystem fileSys = null;
Path root = null;
Set<String> allExpectedMissingFiles = null;
protected void mySetup()
throws Exception {
conf = new Configuration();
if (System.getProperty("hadoop.log.dir") == null) {
String base = new File(".").getAbsolutePath();
System.setProperty("hadoop.log.dir", new Path(base).toString()
+ "/logs");
}
new File(TEST_DIR).mkdirs(); // Make sure data directory exists
conf.set("raid.config.file", CONFIG_FILE);
conf.setBoolean("raid.config.reload", true);
conf.setLong("raid.config.reload.interval", RELOAD_INTERVAL);
// the RaidNode does the raiding inline
conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
// use local block fixer
conf.set("raid.blockfix.classname",
"org.apache.hadoop.raid.LocalBlockIntegrityMonitor");
conf.set("raid.server.address", "localhost:0");
conf.setInt("fs.trash.interval", 1440);
Utils.loadAllTestCodecs(conf, 10, 1, 4, "/raid", "/raidrs",
"/raiddir", "/raiddirrs");
dfs = new MiniDFSCluster(conf, NUM_DATANODES, true, null);
dfs.waitActive();
fileSys = dfs.getFileSystem();
TestDirectoryRaidDfs.setupStripeStore(conf, fileSys);
namenode = fileSys.getUri().toString();
hftp = "hftp://localhost.localdomain:" + dfs.getNameNodePort();
FileSystem.setDefaultUri(conf, namenode);
}
private void stopCluster() {
if (null != dfs) {
dfs.shutdown();
}
}
private void doRaid(Path srcPath, Codec codec) throws IOException {
RaidNode.doRaid(conf, fileSys.getFileStatus(srcPath),
new Path(codec.parityDirectory), codec,
new RaidNode.Statistics(),
RaidUtils.NULL_PROGRESSABLE,
false, 1, 1);
}
public void testVerifySourceFile() throws Exception {
mySetup();
try {
Path srcPath = new Path("/user/dikang/raidtest/file0");
int numBlocks = 8;
TestRaidDfs.createTestFilePartialLastBlock(fileSys, srcPath,
1, numBlocks, 8192L);
assertTrue(fileSys.exists(srcPath));
Codec codec = Codec.getCodec("rs");
FileStatus stat = fileSys.getFileStatus(srcPath);
// verify good file
assertTrue(FastFileCheck.checkFile(conf, (DistributedFileSystem)fileSys,
fileSys, srcPath, null, codec,
RaidUtils.NULL_PROGRESSABLE, true));
// verify bad file
LocatedBlocks fileLoc =
RaidDFSUtil.getBlockLocations((DistributedFileSystem)fileSys,
srcPath.toUri().getPath(),
0, stat.getLen());
// corrupt file1
Random rand = new Random();
int idx = rand.nextInt(numBlocks);
TestRaidDfs.corruptBlock(srcPath,
fileLoc.getLocatedBlocks().get(idx).getBlock(),
NUM_DATANODES, true, dfs);
assertFalse(FastFileCheck.checkFile(conf, (DistributedFileSystem)fileSys,
fileSys, srcPath, null, codec,
RaidUtils.NULL_PROGRESSABLE, true));
} finally {
stopCluster();
}
}
public void testVerifyFile() throws Exception {
mySetup();
try {
Path srcPath = new Path("/user/dikang/raidtest/file0");
TestRaidDfs.createTestFilePartialLastBlock(fileSys, srcPath,
1, 8, 8192L);
assertTrue(fileSys.exists(srcPath));
Codec codec = Codec.getCodec("rs");
// generate the parity files.
doRaid(srcPath, codec);
FileStatus stat = fileSys.getFileStatus(srcPath);
// verify the GOOD_FILE
ParityFilePair pfPair = ParityFilePair.getParityFile(codec, stat, conf);
assertNotNull(pfPair);
assertTrue(FastFileCheck.checkFile(conf, (DistributedFileSystem)fileSys,
fileSys, srcPath, pfPair.getPath(), codec,
RaidUtils.NULL_PROGRESSABLE, false));
// verify the BAD_FILE
fileSys.delete(srcPath);
TestRaidDfs.createTestFilePartialLastBlock(fileSys, srcPath,
1, 8, 8192L);
fileSys.setTimes(pfPair.getPath(),
fileSys.getFileStatus(srcPath).getModificationTime(), -1);
stat = fileSys.getFileStatus(srcPath);
pfPair = ParityFilePair.getParityFile(codec, stat, conf);
assertNotNull(pfPair);
assertFalse(FastFileCheck.checkFile(conf, (DistributedFileSystem)fileSys,
fileSys, srcPath, pfPair.getPath(), codec,
RaidUtils.NULL_PROGRESSABLE, false));
} finally {
stopCluster();
}
}
}