diff --git a/hadoop-assemblies/src/main/resources/assemblies/hadoop-raid-dist.xml b/hadoop-assemblies/src/main/resources/assemblies/hadoop-raid-dist.xml
deleted file mode 100644
index a7da364e72f..00000000000
--- a/hadoop-assemblies/src/main/resources/assemblies/hadoop-raid-dist.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
- hadoop-raid-dist
-
- dir
-
- false
-
-
-
- ${basedir}/src/main/conf
- /etc/hadoop
-
- *
-
-
-
- ${basedir}/src/main/sbin
- /sbin
-
- *
-
- 0755
-
-
- ${basedir}/src/main/libexec
- /libexec
-
- *
-
- 0755
-
-
-
- ${project.build.directory}/site
- /share/doc/hadoop/raid
-
-
-
-
- /share/hadoop/${hadoop.component}/lib
- false
- runtime
- true
-
-
-
diff --git a/hadoop-dist/pom.xml b/hadoop-dist/pom.xml
index 442cdcac333..7fc6e563dbf 100644
--- a/hadoop-dist/pom.xml
+++ b/hadoop-dist/pom.xml
@@ -52,11 +52,6 @@
hadoop-yarn-apiprovided
-
- org.apache.hadoop
- hadoop-hdfs-raid
- provided
-
@@ -125,7 +120,6 @@
run cp -r $ROOT/hadoop-common-project/hadoop-common/target/hadoop-common-${project.version}/* .
run cp -r $ROOT/hadoop-hdfs-project/hadoop-hdfs/target/hadoop-hdfs-${project.version}/* .
run cp -r $ROOT/hadoop-hdfs-project/hadoop-hdfs-httpfs/target/hadoop-hdfs-httpfs-${project.version}/* .
- run cp -r $ROOT/hadoop-hdfs-project/hadoop-hdfs-raid/target/hadoop-hdfs-raid-${project.version}/* .
run cp -r $ROOT/hadoop-mapreduce-project/target/hadoop-mapreduce-${project.version}/* .
run cp -r $ROOT/hadoop-tools/hadoop-tools-dist/target/hadoop-tools-dist-${project.version}/* .
echo
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/pom.xml b/hadoop-hdfs-project/hadoop-hdfs-raid/pom.xml
deleted file mode 100644
index a7fa6eb6562..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/pom.xml
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
- 4.0.0
-
- org.apache.hadoop
- hadoop-project-dist
- 3.0.0-SNAPSHOT
- ../../hadoop-project-dist
-
- org.apache.hadoop
- hadoop-hdfs-raid
- 3.0.0-SNAPSHOT
- jar
-
- Apache Hadoop HDFS Raid
- Apache Hadoop HDFS Raid
-
-
-
- raid
- false
-
-
-
-
- junit
- junit
- test
-
-
- org.apache.hadoop
- hadoop-annotations
- provided
-
-
- org.apache.hadoop
- hadoop-minicluster
- test
-
-
- org.apache.hadoop
- hadoop-client
- provided
-
-
- org.apache.hadoop
- hadoop-archives
- provided
-
-
-
-
-
-
-
- maven-dependency-plugin
-
-
- create-mrapp-generated-classpath
- generate-test-resources
-
- build-classpath
-
-
-
- ${project.build.directory}/test-classes/mrapp-generated-classpath
-
-
-
-
-
- org.apache.rat
- apache-rat-plugin
-
-
-
-
-
-
- org.codehaus.mojo
- findbugs-maven-plugin
-
-
-
-
-
-
-
-
-
- docs
-
- false
-
-
-
-
- org.apache.maven.plugins
- maven-site-plugin
-
-
- docs
- prepare-package
-
- site
-
-
-
-
-
-
-
-
-
- dist
-
- false
-
-
-
-
- org.apache.maven.plugins
- maven-assembly-plugin
-
-
- org.apache.hadoop
- hadoop-assemblies
- ${project.version}
-
-
-
-
- dist
- prepare-package
-
- single
-
-
- ${project.artifactId}-${project.version}
- false
- false
-
- hadoop-raid-dist
-
-
-
-
-
-
-
-
-
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/conf/raid.xml b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/conf/raid.xml
deleted file mode 100644
index 3cf2dc66941..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/conf/raid.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
- srcReplication
- 3
- pick files for RAID only if their replication factor is
- greater than or equal to this value.
-
-
-
- targetReplication
- 2
- after RAIDing, decrease the replication factor of a file to
- this value.
-
-
-
- metaReplication
- 2
- the replication factor of the RAID meta file
-
-
-
- modTimePeriod
- 3600000
- time (milliseconds) after a file is modified to make it a
- candidate for RAIDing
-
-
-
-
-
-
-
- targetReplication
- 1
- after RAIDing, decrease the replication factor of a file to
- this value.
-
-
-
- metaReplication
- 2
- the replication factor of the RAID meta file
-
-
-
- modTimePeriod
- 3600000
- time (milliseconds) after a file is modified to make it a
- candidate for RAIDing
-
-
-
-
-
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/DistributedRaidFileSystem.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/DistributedRaidFileSystem.java
deleted file mode 100644
index 985774bcdcc..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/DistributedRaidFileSystem.java
+++ /dev/null
@@ -1,509 +0,0 @@
-/**
- * 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 java.io.IOException;
-import java.io.PrintStream;
-import java.net.URI;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Random;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.ChecksumException;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FSInputStream;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FilterFileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.raid.Decoder;
-import org.apache.hadoop.raid.RaidNode;
-import org.apache.hadoop.raid.ReedSolomonDecoder;
-import org.apache.hadoop.raid.XORDecoder;
-import org.apache.hadoop.raid.protocol.PolicyInfo.ErasureCodeType;
-import org.apache.hadoop.util.ReflectionUtils;
-
-/**
- * This is an implementation of the Hadoop RAID Filesystem. This FileSystem
- * wraps an instance of the DistributedFileSystem.
- * If a file is corrupted, this FileSystem uses the parity blocks to
- * regenerate the bad block.
- */
-
-public class DistributedRaidFileSystem extends FilterFileSystem {
-
- // these are alternate locations that can be used for read-only access
- DecodeInfo[] alternates;
- Configuration conf;
- int stripeLength;
-
- DistributedRaidFileSystem() throws IOException {
- }
-
- DistributedRaidFileSystem(FileSystem fs) throws IOException {
- super(fs);
- alternates = null;
- stripeLength = 0;
- }
-
- // Information required for decoding a source file
- static private class DecodeInfo {
- final Path destPath;
- final ErasureCodeType type;
- final Configuration conf;
- final int stripeLength;
- private DecodeInfo(Configuration conf, ErasureCodeType type, Path destPath) {
- this.conf = conf;
- this.type = type;
- this.destPath = destPath;
- this.stripeLength = RaidNode.getStripeLength(conf);
- }
-
- Decoder createDecoder() {
- if (this.type == ErasureCodeType.XOR) {
- return new XORDecoder(conf, stripeLength);
- } else if (this.type == ErasureCodeType.RS) {
- return new ReedSolomonDecoder(conf, stripeLength,
- RaidNode.rsParityLength(conf));
- }
- return null;
- }
- }
-
- /* Initialize a Raid FileSystem
- */
- public void initialize(URI name, Configuration conf) throws IOException {
- this.conf = conf;
-
- Class> clazz = conf.getClass("fs.raid.underlyingfs.impl",
- DistributedFileSystem.class);
- if (clazz == null) {
- throw new IOException("No FileSystem for fs.raid.underlyingfs.impl.");
- }
-
- this.fs = (FileSystem)ReflectionUtils.newInstance(clazz, null);
- super.initialize(name, conf);
-
- // find stripe length configured
- stripeLength = RaidNode.getStripeLength(conf);
- if (stripeLength == 0) {
- LOG.info("dfs.raid.stripeLength is incorrectly defined to be " +
- stripeLength + " Ignoring...");
- return;
- }
-
- // Put XOR and RS in alternates
- alternates= new DecodeInfo[2];
- Path xorPath = RaidNode.xorDestinationPath(conf, fs);
- alternates[0] = new DecodeInfo(conf, ErasureCodeType.XOR, xorPath);
- Path rsPath = RaidNode.rsDestinationPath(conf, fs);
- alternates[1] = new DecodeInfo(conf, ErasureCodeType.RS, rsPath);
- }
-
- /*
- * Returns the underlying filesystem
- */
- public FileSystem getFileSystem() throws IOException {
- return fs;
- }
-
- @Override
- public FSDataInputStream open(Path f, int bufferSize) throws IOException {
- ExtFSDataInputStream fd = new ExtFSDataInputStream(conf, this, alternates, f,
- stripeLength, bufferSize);
- return fd;
- }
-
- public void close() throws IOException {
- if (fs != null) {
- try {
- fs.close();
- } catch(IOException ie) {
- //this might already be closed, ignore
- }
- }
- super.close();
- }
-
- /**
- * Layered filesystem input stream. This input stream tries reading
- * from alternate locations if it encoumters read errors in the primary location.
- */
- private static class ExtFSDataInputStream extends FSDataInputStream {
-
- private static class UnderlyingBlock {
- // File that holds this block. Need not be the same as outer file.
- public Path path;
- // Offset within path where this block starts.
- public long actualFileOffset;
- // Offset within the outer file where this block starts.
- public long originalFileOffset;
- // Length of the block (length <= blk sz of outer file).
- public long length;
- public UnderlyingBlock(Path path, long actualFileOffset,
- long originalFileOffset, long length) {
- this.path = path;
- this.actualFileOffset = actualFileOffset;
- this.originalFileOffset = originalFileOffset;
- this.length = length;
- }
- }
-
- /**
- * Create an input stream that wraps all the reads/positions/seeking.
- */
- private static class ExtFsInputStream extends FSInputStream {
-
- // Extents of "good" underlying data that can be read.
- private UnderlyingBlock[] underlyingBlocks;
- private long currentOffset;
- private FSDataInputStream currentStream;
- private UnderlyingBlock currentBlock;
- private byte[] oneBytebuff = new byte[1];
- private int nextLocation;
- private DistributedRaidFileSystem lfs;
- private Path path;
- private FileStatus stat;
- private final DecodeInfo[] alternates;
- private final int buffersize;
- private final Configuration conf;
- private final int stripeLength;
-
- ExtFsInputStream(Configuration conf, DistributedRaidFileSystem lfs,
- DecodeInfo[] alternates, Path path, int stripeLength, int buffersize)
- throws IOException {
- this.path = path;
- this.nextLocation = 0;
- // Construct array of blocks in file.
- this.stat = lfs.getFileStatus(path);
- long numBlocks = (this.stat.getLen() % this.stat.getBlockSize() == 0) ?
- this.stat.getLen() / this.stat.getBlockSize() :
- 1 + this.stat.getLen() / this.stat.getBlockSize();
- this.underlyingBlocks = new UnderlyingBlock[(int)numBlocks];
- for (int i = 0; i < numBlocks; i++) {
- long actualFileOffset = i * stat.getBlockSize();
- long originalFileOffset = i * stat.getBlockSize();
- long length = Math.min(
- stat.getBlockSize(), stat.getLen() - originalFileOffset);
- this.underlyingBlocks[i] = new UnderlyingBlock(
- path, actualFileOffset, originalFileOffset, length);
- }
- this.currentOffset = 0;
- this.currentBlock = null;
- this.alternates = alternates;
- this.buffersize = buffersize;
- this.conf = conf;
- this.lfs = lfs;
- this.stripeLength = stripeLength;
- // Open a stream to the first block.
- openCurrentStream();
- }
-
- private void closeCurrentStream() throws IOException {
- if (currentStream != null) {
- currentStream.close();
- currentStream = null;
- }
- }
-
- /**
- * Open a stream to the file containing the current block
- * and seek to the appropriate offset
- */
- private void openCurrentStream() throws IOException {
- int blockIdx = (int)(currentOffset/stat.getBlockSize());
- UnderlyingBlock block = underlyingBlocks[blockIdx];
- // If the current path is the same as we want.
- if (currentBlock == block ||
- currentBlock != null && currentBlock.path == block.path) {
- // If we have a valid stream, nothing to do.
- if (currentStream != null) {
- currentBlock = block;
- return;
- }
- } else {
- closeCurrentStream();
- }
- currentBlock = block;
- currentStream = lfs.fs.open(currentBlock.path, buffersize);
- long offset = block.actualFileOffset +
- (currentOffset - block.originalFileOffset);
- currentStream.seek(offset);
- }
-
- /**
- * Returns the number of bytes available in the current block.
- */
- private int blockAvailable() {
- return (int) (currentBlock.length -
- (currentOffset - currentBlock.originalFileOffset));
- }
-
- @Override
- public synchronized int available() throws IOException {
- // Application should not assume that any bytes are buffered here.
- nextLocation = 0;
- return Math.min(blockAvailable(), currentStream.available());
- }
-
- @Override
- public synchronized void close() throws IOException {
- closeCurrentStream();
- super.close();
- }
-
- @Override
- public boolean markSupported() { return false; }
-
- @Override
- public void mark(int readLimit) {
- // Mark and reset are not supported.
- nextLocation = 0;
- }
-
- @Override
- public void reset() throws IOException {
- // Mark and reset are not supported.
- nextLocation = 0;
- }
-
- @Override
- public synchronized int read() throws IOException {
- int value = read(oneBytebuff);
- if (value < 0) {
- return value;
- } else {
- return oneBytebuff[0];
- }
- }
-
- @Override
- public synchronized int read(byte[] b) throws IOException {
- int value = read(b, 0, b.length);
- nextLocation = 0;
- return value;
- }
-
- @Override
- public synchronized int read(byte[] b, int offset, int len)
- throws IOException {
- while (true) {
- openCurrentStream();
- try{
- int limit = Math.min(blockAvailable(), len);
- int value = currentStream.read(b, offset, limit);
- currentOffset += value;
- nextLocation = 0;
- return value;
- } catch (BlockMissingException e) {
- setAlternateLocations(e, currentOffset);
- } catch (ChecksumException e) {
- setAlternateLocations(e, currentOffset);
- }
- }
- }
-
- @Override
- public synchronized int read(long position, byte[] b, int offset, int len)
- throws IOException {
- long oldPos = currentOffset;
- seek(position);
- try {
- return read(b, offset, len);
- } finally {
- seek(oldPos);
- }
- }
-
- @Override
- public synchronized long skip(long n) throws IOException {
- long skipped = 0;
- while (skipped < n) {
- int val = read();
- if (val < 0) {
- break;
- }
- skipped++;
- }
- nextLocation = 0;
- return skipped;
- }
-
- @Override
- public synchronized long getPos() throws IOException {
- nextLocation = 0;
- return currentOffset;
- }
-
- @Override
- public synchronized void seek(long pos) throws IOException {
- if (pos != currentOffset) {
- closeCurrentStream();
- currentOffset = pos;
- openCurrentStream();
- }
- nextLocation = 0;
- }
-
- @Override
- public boolean seekToNewSource(long targetPos) throws IOException {
- seek(targetPos);
- boolean value = currentStream.seekToNewSource(currentStream.getPos());
- nextLocation = 0;
- return value;
- }
-
- /**
- * position readable again.
- */
- @Override
- public void readFully(long pos, byte[] b, int offset, int length)
- throws IOException {
- long oldPos = currentOffset;
- seek(pos);
- try {
- while (true) {
- // This loop retries reading until successful. Unrecoverable errors
- // cause exceptions.
- // currentOffset is changed by read().
- try {
- while (length > 0) {
- int n = read(b, offset, length);
- if (n < 0) {
- throw new IOException("Premature EOF");
- }
- offset += n;
- length -= n;
- }
- nextLocation = 0;
- return;
- } catch (BlockMissingException e) {
- setAlternateLocations(e, currentOffset);
- } catch (ChecksumException e) {
- setAlternateLocations(e, currentOffset);
- }
- }
- } finally {
- seek(oldPos);
- }
- }
-
- @Override
- public void readFully(long pos, byte[] b) throws IOException {
- readFully(pos, b, 0, b.length);
- nextLocation = 0;
- }
-
- /**
- * Extract good block from RAID
- * @throws IOException if all alternate locations are exhausted
- */
- private void setAlternateLocations(IOException curexp, long offset)
- throws IOException {
- while (alternates != null && nextLocation < alternates.length) {
- try {
- int idx = nextLocation++;
- // Start offset of block.
- long corruptOffset =
- (offset / stat.getBlockSize()) * stat.getBlockSize();
- // Make sure we use DFS and not DistributedRaidFileSystem for unRaid.
- Configuration clientConf = new Configuration(conf);
- Class> clazz = conf.getClass("fs.raid.underlyingfs.impl",
- DistributedFileSystem.class);
- clientConf.set("fs.hdfs.impl", clazz.getName());
- // Disable caching so that a previously cached RaidDfs is not used.
- clientConf.setBoolean("fs.hdfs.impl.disable.cache", true);
- Path npath = RaidNode.unRaidCorruptBlock(clientConf, path,
- alternates[idx].destPath,
- alternates[idx].createDecoder(),
- stripeLength, corruptOffset);
- if (npath == null)
- continue;
- try {
- String outdir = conf.get("fs.raid.recoverylogdir");
- if (outdir != null) {
- DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
- java.util.Date date = new java.util.Date();
- String fname = path.getName() + dateFormat.format(date) +
- (new Random()).nextInt() + ".txt";
- Path outputunraid = new Path(outdir, fname);
- FileSystem fs = outputunraid.getFileSystem(conf);
- FSDataOutputStream dout = fs.create(outputunraid);
- PrintStream ps = new PrintStream(dout);
- ps.println("Recovery attempt log");
- ps.println("Source path : " + path );
- ps.println("Alternate path : " + alternates[idx].destPath);
- ps.println("Stripe lentgh : " + stripeLength);
- ps.println("Corrupt offset : " + corruptOffset);
- String output = (npath==null) ? "UNSUCCESSFUL" : npath.toString();
- ps.println("Output from unRaid : " + output);
- ps.close();
- }
- } catch (Exception exc) {
- LOG.info("Error while creating recovery log: " + exc);
- }
-
- closeCurrentStream();
- LOG.info("Using block at offset " + corruptOffset + " from " +
- npath);
- currentBlock.path = npath;
- currentBlock.actualFileOffset = 0; // Single block in file.
- // Dont change currentOffset, in case the user had done a seek?
- openCurrentStream();
-
- return;
- } catch (Exception e) {
- LOG.info("Error in using alternate path " + path + ". " + e +
- " Ignoring...");
- }
- }
- throw curexp;
- }
-
- /**
- * The name of the file system that is immediately below the
- * DistributedRaidFileSystem. This is specified by the
- * configuration parameter called fs.raid.underlyingfs.impl.
- * If this parameter is not specified in the configuration, then
- * the default class DistributedFileSystem is returned.
- * @param conf the configuration object
- * @return the filesystem object immediately below DistributedRaidFileSystem
- * @throws IOException if all alternate locations are exhausted
- */
- private FileSystem getUnderlyingFileSystem(Configuration conf) {
- Class> clazz = conf.getClass("fs.raid.underlyingfs.impl", DistributedFileSystem.class);
- FileSystem fs = (FileSystem)ReflectionUtils.newInstance(clazz, conf);
- return fs;
- }
- }
-
- /**
- * constructor for ext input stream.
- * @param fs the underlying filesystem
- * @param p the path in the underlying file system
- * @param buffersize the size of IO
- * @throws IOException
- */
- public ExtFSDataInputStream(Configuration conf, DistributedRaidFileSystem lfs,
- DecodeInfo[] alternates, Path p, int stripeLength, int buffersize) throws IOException {
- super(new ExtFsInputStream(conf, lfs, alternates, p, stripeLength, buffersize));
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/RaidDFSUtil.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/RaidDFSUtil.java
deleted file mode 100644
index 58dfa34fe69..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/RaidDFSUtil.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * 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 java.io.IOException;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.HashSet;
-import java.util.Set;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.RemoteIterator;
-import org.apache.hadoop.hdfs.protocol.LocatedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.hdfs.tools.DFSck;
-import org.apache.hadoop.util.ToolRunner;
-
-public abstract class RaidDFSUtil {
- /**
- * Returns the corrupt blocks in a file.
- */
- public static List corruptBlocksInFile(
- DistributedFileSystem dfs, String path, long offset, long length)
- throws IOException {
- List corrupt = new LinkedList();
- LocatedBlocks locatedBlocks =
- getBlockLocations(dfs, path, offset, length);
- for (LocatedBlock b: locatedBlocks.getLocatedBlocks()) {
- if (b.isCorrupt() ||
- (b.getLocations().length == 0 && b.getBlockSize() > 0)) {
- corrupt.add(b);
- }
- }
- return corrupt;
- }
-
- public static LocatedBlocks getBlockLocations(
- DistributedFileSystem dfs, String path, long offset, long length)
- throws IOException {
- return dfs.getClient().namenode.getBlockLocations(path, offset, length);
- }
-
- /**
- * Make successive calls to listCorruptFiles to obtain all
- * corrupt files.
- */
- public static String[] getCorruptFiles(DistributedFileSystem dfs)
- throws IOException {
- Set corruptFiles = new HashSet();
- RemoteIterator cfb = dfs.listCorruptFileBlocks(new Path("/"));
- while (cfb.hasNext()) {
- corruptFiles.add(cfb.next().toUri().getPath());
- }
-
- return corruptFiles.toArray(new String[corruptFiles.size()]);
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockPlacementPolicyRaid.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockPlacementPolicyRaid.java
deleted file mode 100644
index de0bee60645..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockPlacementPolicyRaid.java
+++ /dev/null
@@ -1,632 +0,0 @@
-/**
- * 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.server.blockmanagement;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.LinkedHashMap;
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Comparator;
-
-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.Block;
-import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlock;
-import org.apache.hadoop.hdfs.server.namenode.*;
-import org.apache.hadoop.net.NetworkTopology;
-import org.apache.hadoop.net.Node;
-import org.apache.hadoop.raid.RaidNode;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-
-/**
- * This BlockPlacementPolicy spreads out the group of blocks which used by RAID
- * for recovering each other. This is important for the availability
- * of the blocks. This class can be used by multiple threads. It has to be
- * thread safe.
- */
-public class BlockPlacementPolicyRaid extends BlockPlacementPolicy {
- public static final Log LOG =
- LogFactory.getLog(BlockPlacementPolicyRaid.class);
- Configuration conf;
- private int stripeLength;
- private int xorParityLength;
- private int rsParityLength;
- private String xorPrefix = null;
- private String rsPrefix = null;
- private String raidTempPrefix = null;
- private String raidrsTempPrefix = null;
- private String raidHarTempPrefix = null;
- private String raidrsHarTempPrefix = null;
- private FSNamesystem namesystem = null;
- private BlockPlacementPolicyDefault defaultPolicy;
-
- CachedLocatedBlocks cachedLocatedBlocks;
- CachedFullPathNames cachedFullPathNames;
-
- /** {@inheritDoc} */
- @Override
- public void initialize(Configuration conf, FSClusterStats stats,
- NetworkTopology clusterMap) {
- this.conf = conf;
- this.stripeLength = RaidNode.getStripeLength(conf);
- this.rsParityLength = RaidNode.rsParityLength(conf);
- this.xorParityLength = 1;
- try {
- this.xorPrefix = RaidNode.xorDestinationPath(conf).toUri().getPath();
- this.rsPrefix = RaidNode.rsDestinationPath(conf).toUri().getPath();
- } catch (IOException e) {
- }
- if (this.xorPrefix == null) {
- this.xorPrefix = RaidNode.DEFAULT_RAID_LOCATION;
- }
- if (this.rsPrefix == null) {
- this.rsPrefix = RaidNode.DEFAULT_RAIDRS_LOCATION;
- }
- // Throws ClassCastException if we cannot cast here.
- this.namesystem = (FSNamesystem) stats;
- this.cachedLocatedBlocks = new CachedLocatedBlocks(namesystem);
- this.cachedFullPathNames = new CachedFullPathNames(namesystem);
- this.raidTempPrefix = RaidNode.xorTempPrefix(conf);
- this.raidrsTempPrefix = RaidNode.rsTempPrefix(conf);
- this.raidHarTempPrefix = RaidNode.xorHarTempPrefix(conf);
- this.raidrsHarTempPrefix = RaidNode.rsHarTempPrefix(conf);
- defaultPolicy = new BlockPlacementPolicyDefault(conf, stats, clusterMap);
- }
-
- @Override
- DatanodeDescriptor[] chooseTarget(String srcPath, int numOfReplicas,
- DatanodeDescriptor writer, List chosenNodes,
- long blocksize) {
- return chooseTarget(srcPath, numOfReplicas, writer, chosenNodes,
- null, blocksize);
- }
-
- @Override
- public DatanodeDescriptor[] chooseTarget(String srcPath, int numOfReplicas,
- DatanodeDescriptor writer, List chosenNodes,
- boolean returnChosenNodes,
- HashMap excludedNodes, long blocksize) {
- try {
- FileType type = getFileType(srcPath);
- if (type == FileType.NOT_RAID) {
- return defaultPolicy.chooseTarget(
- srcPath, numOfReplicas, writer, chosenNodes, blocksize);
- }
- if (excludedNodes == null) {
- excludedNodes = new HashMap();
- }
- addExcludedNodes(srcPath, type, excludedNodes);
- DatanodeDescriptor[] result =
- defaultPolicy.chooseTarget(numOfReplicas, writer,
- chosenNodes, returnChosenNodes, excludedNodes, blocksize);
- // Add the added block locations in the block locations cache.
- // So the rest of the blocks know about these locations.
- cachedLocatedBlocks.get(srcPath).
- add(new LocatedBlock(new ExtendedBlock(), result));
- return result;
- } catch (Exception e) {
- LOG.debug("Error happend when choosing datanode to write:" +
- StringUtils.stringifyException(e));
- return defaultPolicy.chooseTarget(srcPath, numOfReplicas, writer,
- chosenNodes, blocksize);
- }
- }
-
- @Override
- public int verifyBlockPlacement(String srcPath, LocatedBlock lBlk,
- int minRacks) {
- return defaultPolicy.verifyBlockPlacement(srcPath, lBlk, minRacks);
- }
-
- /** {@inheritDoc} */
- @Override
- public DatanodeDescriptor chooseReplicaToDelete(BlockCollection bc,
- Block block, short replicationFactor,
- Collection first,
- Collection second) {
-
- DatanodeDescriptor chosenNode = null;
- try {
- String path = cachedFullPathNames.get(bc);
- FileType type = getFileType(path);
- if (type == FileType.NOT_RAID) {
- return defaultPolicy.chooseReplicaToDelete(
- bc, block, replicationFactor, first, second);
- }
- List companionBlocks =
- getCompanionBlocks(path, type, block);
- if (companionBlocks == null || companionBlocks.size() == 0) {
- // Use the default method if it is not a valid raided or parity file
- return defaultPolicy.chooseReplicaToDelete(
- bc, block, replicationFactor, first, second);
- }
- // Delete from the first collection first
- // This ensures the number of unique rack of this block is not reduced
- Collection all = new HashSet();
- all.addAll(first);
- all.addAll(second);
- chosenNode = chooseReplicaToDelete(companionBlocks, all);
- if (chosenNode != null) {
- return chosenNode;
- }
- return defaultPolicy.chooseReplicaToDelete(
- bc, block, replicationFactor, first, second);
- } catch (Exception e) {
- LOG.debug("Error happend when choosing replica to delete" +
- StringUtils.stringifyException(e));
- return defaultPolicy.chooseReplicaToDelete(
- bc, block, replicationFactor, first, second);
- }
- }
-
- /**
- * Obtain the excluded nodes for the current block that is being written
- */
- void addExcludedNodes(String file, FileType type, HashMap excluded)
- throws IOException {
- Collection blocks = getCompanionBlocks(file, type, null);
- if (blocks == null) {
- return;
- }
- for (LocatedBlock b : blocks) {
- for (Node n : b.getLocations()) {
- excluded.put(n, n);
- }
- }
- }
-
- private DatanodeDescriptor chooseReplicaToDelete(
- Collection companionBlocks,
- Collection dataNodes) throws IOException {
-
- if (dataNodes.isEmpty()) {
- return null;
- }
- // Count the number of replicas on each node and rack
- final Map nodeCompanionBlockCount =
- countCompanionBlocks(companionBlocks, false);
- final Map rackCompanionBlockCount =
- countCompanionBlocks(companionBlocks, true);
-
- NodeComparator comparator =
- new NodeComparator(nodeCompanionBlockCount, rackCompanionBlockCount);
- return Collections.max(dataNodes, comparator);
- }
-
- /**
- * Count how many companion blocks are on each datanode or the each rack
- * @param companionBlocks a collection of all the companion blocks
- * @param doRackCount count the companion blocks on the racks of datanodes
- * @param result the map from node name to the number of companion blocks
- */
- static Map countCompanionBlocks(
- Collection companionBlocks, boolean doRackCount) {
- Map result = new HashMap();
- for (LocatedBlock block : companionBlocks) {
- for (DatanodeInfo d : block.getLocations()) {
- String name = doRackCount ? d.getParent().getName() : d.getName();
- if (result.containsKey(name)) {
- int count = result.get(name) + 1;
- result.put(name, count);
- } else {
- result.put(name, 1);
- }
- }
- }
- return result;
- }
-
- /**
- * Compares the datanodes based on the number of companion blocks on the same
- * node and rack. If even, compare the remaining space on the datanodes.
- */
- class NodeComparator implements Comparator {
- private Map nodeBlockCount;
- private Map rackBlockCount;
- private NodeComparator(Map nodeBlockCount,
- Map rackBlockCount) {
- this.nodeBlockCount = nodeBlockCount;
- this.rackBlockCount = rackBlockCount;
- }
- @Override
- public int compare(DatanodeDescriptor d1, DatanodeDescriptor d2) {
- int res = compareBlockCount(d1, d2, nodeBlockCount);
- if (res != 0) {
- return res;
- }
- res = compareBlockCount(d1.getParent(), d2.getParent(), rackBlockCount);
- if (res != 0) {
- return res;
- }
- if (d1.getRemaining() > d2.getRemaining()) {
- return -1;
- }
- if (d1.getRemaining() < d2.getRemaining()) {
- return 1;
- }
- return 0;
- }
- private int compareBlockCount(Node node1, Node node2,
- Map blockCount) {
- Integer count1 = blockCount.get(node1.getName());
- Integer count2 = blockCount.get(node2.getName());
- count1 = count1 == null ? 0 : count1;
- count2 = count2 == null ? 0 : count2;
- if (count1 > count2) {
- return 1;
- }
- if (count1 < count2) {
- return -1;
- }
- return 0;
- }
- }
-
- /**
- * Obtain the companion blocks of the give block
- * Companion blocks are defined as the blocks that can help recover each
- * others by using raid decoder.
- * @param path The path of the file contains the block
- * @param type The type of this file
- * @param block The given block
- * null if it is the block which is currently being written to
- * @return the block locations of companion blocks
- */
- List getCompanionBlocks(String path, FileType type,
- Block block) throws IOException {
- switch (type) {
- case NOT_RAID:
- return new ArrayList();
- case XOR_HAR_TEMP_PARITY:
- return getCompanionBlocksForHarParityBlock(
- path, xorParityLength, block);
- case RS_HAR_TEMP_PARITY:
- return getCompanionBlocksForHarParityBlock(
- path, rsParityLength, block);
- case XOR_TEMP_PARITY:
- return getCompanionBlocksForParityBlock(
- getSourceFile(path, raidTempPrefix), path, xorParityLength, block);
- case RS_TEMP_PARITY:
- return getCompanionBlocksForParityBlock(
- getSourceFile(path, raidrsTempPrefix), path, rsParityLength, block);
- case XOR_PARITY:
- return getCompanionBlocksForParityBlock(getSourceFile(path, xorPrefix),
- path, xorParityLength, block);
- case RS_PARITY:
- return getCompanionBlocksForParityBlock(getSourceFile(path, rsPrefix),
- path, rsParityLength, block);
- case XOR_SOURCE:
- return getCompanionBlocksForSourceBlock(
- path, getParityFile(path), xorParityLength, block);
- case RS_SOURCE:
- return getCompanionBlocksForSourceBlock(
- path, getParityFile(path), xorParityLength, block);
- }
- return new ArrayList();
- }
-
- private List getCompanionBlocksForHarParityBlock(
- String parity, int parityLength, Block block)
- throws IOException {
- int blockIndex = getBlockIndex(parity, block);
- // consider only parity file in this case because source file block
- // location is not easy to obtain
- List parityBlocks = cachedLocatedBlocks.get(parity);
- List result = new ArrayList();
- synchronized (parityBlocks) {
- int start = Math.max(0, blockIndex - parityLength + 1);
- int end = Math.min(parityBlocks.size(), blockIndex + parityLength);
- result.addAll(parityBlocks.subList(start, end));
- }
- return result;
- }
-
- private List getCompanionBlocksForParityBlock(
- String src, String parity, int parityLength, Block block)
- throws IOException {
- int blockIndex = getBlockIndex(parity, block);
- List result = new ArrayList();
- List parityBlocks = cachedLocatedBlocks.get(parity);
- int stripeIndex = blockIndex / parityLength;
- synchronized (parityBlocks) {
- int parityStart = stripeIndex * parityLength;
- int parityEnd = Math.min(parityStart + parityLength,
- parityBlocks.size());
- // for parity, always consider the neighbor blocks as companion blocks
- if (parityStart < parityBlocks.size()) {
- result.addAll(parityBlocks.subList(parityStart, parityEnd));
- }
- }
-
- if (src == null) {
- return result;
- }
- List sourceBlocks = cachedLocatedBlocks.get(src);
- synchronized (sourceBlocks) {
- int sourceStart = stripeIndex * stripeLength;
- int sourceEnd = Math.min(sourceStart + stripeLength,
- sourceBlocks.size());
- if (sourceStart < sourceBlocks.size()) {
- result.addAll(sourceBlocks.subList(sourceStart, sourceEnd));
- }
- }
- return result;
- }
-
- private List getCompanionBlocksForSourceBlock(
- String src, String parity, int parityLength, Block block)
- throws IOException {
- int blockIndex = getBlockIndex(src, block);
- List result = new ArrayList();
- List sourceBlocks = cachedLocatedBlocks.get(src);
- int stripeIndex = blockIndex / stripeLength;
- synchronized (sourceBlocks) {
- int sourceStart = stripeIndex * stripeLength;
- int sourceEnd = Math.min(sourceStart + stripeLength,
- sourceBlocks.size());
- if (sourceStart < sourceBlocks.size()) {
- result.addAll(sourceBlocks.subList(sourceStart, sourceEnd));
- }
- }
- if (parity == null) {
- return result;
- }
- List parityBlocks = cachedLocatedBlocks.get(parity);
- synchronized (parityBlocks) {
- int parityStart = stripeIndex * parityLength;
- int parityEnd = Math.min(parityStart + parityLength,
- parityBlocks.size());
- if (parityStart < parityBlocks.size()) {
- result.addAll(parityBlocks.subList(parityStart, parityEnd));
- }
- }
- return result;
- }
-
- private int getBlockIndex(String file, Block block) throws IOException {
- List blocks = cachedLocatedBlocks.get(file);
- synchronized (blocks) {
- // null indicates that this block is currently added. Return size()
- // as the index in this case
- if (block == null) {
- return blocks.size();
- }
- for (int i = 0; i < blocks.size(); i++) {
- if (blocks.get(i).getBlock().getLocalBlock().equals(block)) {
- return i;
- }
- }
- }
- throw new IOException("Cannot locate " + block + " in file " + file);
- }
-
- /**
- * Cache results for getFullPathName()
- */
- static class CachedFullPathNames {
- FSNamesystem namesystem;
- CachedFullPathNames(FSNamesystem namesystem) {
- this.namesystem = namesystem;
- }
- private Cache cacheInternal =
- new Cache() {
- @Override
- public String getDirectly(INodeWithHashCode inode) throws IOException {
- namesystem.readLock();
- try {
- return inode.getFullPathName();
- } finally {
- namesystem.readUnlock();
- }
- }
- };
-
- static private class INodeWithHashCode {
- BlockCollection bc;
- INodeWithHashCode(BlockCollection bc) {
- this.bc= bc;
- }
- @Override
- public boolean equals(Object obj) {
- return bc== obj;
- }
- @Override
- public int hashCode() {
- return System.identityHashCode(bc);
- }
- String getFullPathName() {
- return bc.getName();
- }
- }
-
- public String get(BlockCollection bc) throws IOException {
- return cacheInternal.get(new INodeWithHashCode(bc));
- }
- }
-
- /**
- * Cache results for FSNamesystem.getBlockLocations()
- */
- static class CachedLocatedBlocks extends Cache> {
- FSNamesystem namesystem;
- CachedLocatedBlocks(FSNamesystem namesystem) {
- this.namesystem = namesystem;
- }
- @Override
- public List getDirectly(String file) throws IOException {
- long len = NameNodeRaidUtil.getFileInfo(namesystem, file, true).getLen();
- List result = NameNodeRaidUtil.getBlockLocations(namesystem,
- file, 0L, len, false, false).getLocatedBlocks();
- if (result == null || result.isEmpty()) {
- result = new ArrayList();
- }
- return Collections.synchronizedList(result);
- }
- }
-
- static abstract class Cache {
- private Map cache;
- private static final long CACHE_TIMEOUT = 300000L; // 5 minutes
- // The timeout is long but the consequence of stale value is not serious
- Cache() {
- Map map = new LinkedHashMap() {
- private static final long serialVersionUID = 1L;
- final private int MAX_ENTRIES = 50000;
- @Override
- protected boolean removeEldestEntry(
- Map.Entry eldest) {
- return size() > MAX_ENTRIES;
- }
- };
- this.cache = Collections.synchronizedMap(map);
- }
-
- // Note that this method may hold FSNamesystem.readLock() and it may
- // be called inside FSNamesystem.writeLock(). If we make this method
- // synchronized, it will deadlock.
- abstract protected V getDirectly(K key) throws IOException;
-
- public V get(K key) throws IOException {
- // The method is not synchronized so we may get some stale value here but
- // it's OK.
- ValueWithTime result = cache.get(key);
- long now = Time.now();
- if (result != null &&
- now - result.cachedTime < CACHE_TIMEOUT) {
- return result.value;
- }
- result = new ValueWithTime();
- result.value = getDirectly(key);
- result.cachedTime = now;
- cache.put(key, result);
- return result.value;
- }
- private class ValueWithTime {
- V value = null;
- long cachedTime = 0L;
- }
- }
-
- /**
- * Get path for the corresponding source file for a valid parity
- * file. Returns null if it does not exists
- * @param parity the toUri path of the parity file
- * @return the toUri path of the source file
- */
- String getSourceFile(String parity, String prefix) throws IOException {
- if (isHarFile(parity)) {
- return null;
- }
- // remove the prefix
- String src = parity.substring(prefix.length());
- if (NameNodeRaidUtil.getFileInfo(namesystem, src, true) == null) {
- return null;
- }
- return src;
- }
-
- /**
- * Get path for the corresponding parity file for a source file.
- * Returns null if it does not exists
- * @param src the toUri path of the source file
- * @return the toUri path of the parity file
- */
- String getParityFile(String src) throws IOException {
- String xorParity = getParityFile(xorPrefix, src);
- if (xorParity != null) {
- return xorParity;
- }
- String rsParity = getParityFile(rsPrefix, src);
- if (rsParity != null) {
- return rsParity;
- }
- return null;
- }
-
- /**
- * Get path for the parity file. Returns null if it does not exists
- * @param parityPrefix usuall "/raid/" or "/raidrs/"
- * @return the toUri path of the parity file
- */
- private String getParityFile(String parityPrefix, String src)
- throws IOException {
- String parity = parityPrefix + src;
- if (NameNodeRaidUtil.getFileInfo(namesystem, parity, true) == null) {
- return null;
- }
- return parity;
- }
-
- private boolean isHarFile(String path) {
- return path.lastIndexOf(RaidNode.HAR_SUFFIX) != -1;
- }
-
- enum FileType {
- NOT_RAID,
- XOR_HAR_TEMP_PARITY,
- XOR_TEMP_PARITY,
- XOR_PARITY,
- XOR_SOURCE,
- RS_HAR_TEMP_PARITY,
- RS_TEMP_PARITY,
- RS_PARITY,
- RS_SOURCE,
- }
-
- FileType getFileType(String path) throws IOException {
- if (path.startsWith(raidHarTempPrefix + Path.SEPARATOR)) {
- return FileType.XOR_HAR_TEMP_PARITY;
- }
- if (path.startsWith(raidrsHarTempPrefix + Path.SEPARATOR)) {
- return FileType.RS_HAR_TEMP_PARITY;
- }
- if (path.startsWith(raidTempPrefix + Path.SEPARATOR)) {
- return FileType.XOR_TEMP_PARITY;
- }
- if (path.startsWith(raidrsTempPrefix + Path.SEPARATOR)) {
- return FileType.RS_TEMP_PARITY;
- }
- if (path.startsWith(xorPrefix + Path.SEPARATOR)) {
- return FileType.XOR_PARITY;
- }
- if (path.startsWith(rsPrefix + Path.SEPARATOR)) {
- return FileType.RS_PARITY;
- }
- String parity = getParityFile(path);
- if (parity == null) {
- return FileType.NOT_RAID;
- }
- if (parity.startsWith(xorPrefix + Path.SEPARATOR)) {
- return FileType.XOR_SOURCE;
- }
- if (parity.startsWith(rsPrefix + Path.SEPARATOR)) {
- return FileType.RS_SOURCE;
- }
- return FileType.NOT_RAID;
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/datanode/RaidBlockSender.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/datanode/RaidBlockSender.java
deleted file mode 100644
index 7eb6e16c55a..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/datanode/RaidBlockSender.java
+++ /dev/null
@@ -1,505 +0,0 @@
-/**
- * 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.server.datanode;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.util.Arrays;
-
-import org.apache.commons.logging.Log;
-import org.apache.hadoop.fs.ChecksumException;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.HdfsConstants;
-import org.apache.hadoop.hdfs.protocol.datatransfer.PacketHeader;
-import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsDatasetSpi;
-import org.apache.hadoop.hdfs.util.DataTransferThrottler;
-import org.apache.hadoop.io.IOUtils;
-import org.apache.hadoop.io.nativeio.NativeIO;
-import org.apache.hadoop.net.SocketOutputStream;
-import org.apache.hadoop.util.DataChecksum;
-import org.apache.hadoop.util.StringUtils;
-
-/**
- * Reads a block from the disk and sends it to a recipient.
- */
-public class RaidBlockSender implements java.io.Closeable {
- public static final Log LOG = DataNode.LOG;
- static final Log ClientTraceLog = DataNode.ClientTraceLog;
-
- private ExtendedBlock block; // the block to read from
-
- /** The visible length of a replica. */
- private final long replicaVisibleLength;
-
- private InputStream blockIn; // data stream
- private long blockInPosition = -1; // updated while using transferTo().
- private DataInputStream checksumIn; // checksum datastream
- private DataChecksum checksum; // checksum stream
- private long offset; // starting position to read
- /** Initial position to read */
- private long initialOffset;
- private long endOffset; // ending position
- private int chunkSize; // chunk size
- private int checksumSize; // checksum size
- private boolean corruptChecksumOk; // if need to verify checksum
- private boolean chunkOffsetOK; // if need to send chunk offset
- private long seqno; // sequence number of packet
-
- private boolean transferToAllowed = true;
- private boolean blockReadFully; //set when the whole block is read
- private boolean verifyChecksum; //if true, check is verified while reading
- private final String clientTraceFmt; // format of client trace log message
-
- /**
- * Minimum buffer used while sending data to clients. Used only if
- * transferTo() is enabled. 64KB is not that large. It could be larger, but
- * not sure if there will be much more improvement.
- */
- private static final int MIN_BUFFER_WITH_TRANSFERTO = 64*1024;
- private static final int TRANSFERTO_BUFFER_SIZE = Math.max(
- HdfsConstants.IO_FILE_BUFFER_SIZE, MIN_BUFFER_WITH_TRANSFERTO);
- private volatile ChunkChecksum lastChunkChecksum = null;
-
-
- public RaidBlockSender(ExtendedBlock block, long blockLength, long startOffset, long length,
- boolean corruptChecksumOk, boolean chunkOffsetOK,
- boolean verifyChecksum, boolean transferToAllowed,
- DataInputStream metadataIn, InputStreamFactory streamFactory
- ) throws IOException {
- this(block, blockLength, startOffset, length,
- corruptChecksumOk, chunkOffsetOK,
- verifyChecksum, transferToAllowed,
- metadataIn, streamFactory, null);
- }
-
- public RaidBlockSender(ExtendedBlock block, long blockLength, long startOffset, long length,
- boolean corruptChecksumOk, boolean chunkOffsetOK,
- boolean verifyChecksum, boolean transferToAllowed,
- DataInputStream metadataIn, InputStreamFactory streamFactory,
- String clientTraceFmt) throws IOException {
- try {
- this.block = block;
- this.chunkOffsetOK = chunkOffsetOK;
- this.corruptChecksumOk = corruptChecksumOk;
- this.verifyChecksum = verifyChecksum;
- this.replicaVisibleLength = blockLength;
- this.transferToAllowed = transferToAllowed;
- this.clientTraceFmt = clientTraceFmt;
-
- if ( !corruptChecksumOk || metadataIn != null) {
- this.checksumIn = metadataIn;
-
- // read and handle the common header here. For now just a version
- BlockMetadataHeader header = BlockMetadataHeader.readHeader(checksumIn);
- short version = header.getVersion();
-
- if (version != BlockMetadataHeader.VERSION) {
- LOG.warn("Wrong version (" + version + ") for metadata file for "
- + block + " ignoring ...");
- }
- checksum = header.getChecksum();
- } else {
- LOG.warn("Could not find metadata file for " + block);
- // This only decides the buffer size. Use BUFFER_SIZE?
- checksum = DataChecksum.newDataChecksum(DataChecksum.CHECKSUM_NULL,
- 16 * 1024);
- }
-
- /* If bytesPerChecksum is very large, then the metadata file
- * is mostly corrupted. For now just truncate bytesPerchecksum to
- * blockLength.
- */
- int size = checksum.getBytesPerChecksum();
- if (size > 10*1024*1024 && size > replicaVisibleLength) {
- checksum = DataChecksum.newDataChecksum(checksum.getChecksumType(),
- Math.max((int)replicaVisibleLength, 10*1024*1024));
- size = checksum.getBytesPerChecksum();
- }
- chunkSize = size;
- checksumSize = checksum.getChecksumSize();
-
- if (length < 0) {
- length = replicaVisibleLength;
- }
-
- endOffset = blockLength;
-
- if (startOffset < 0 || startOffset > endOffset
- || (length + startOffset) > endOffset) {
- String msg = " Offset " + startOffset + " and length " + length
- + " don't match block " + block + " ( blockLen " + endOffset + " )";
- LOG.warn("sendBlock() : " + msg);
- throw new IOException(msg);
- }
-
- offset = (startOffset - (startOffset % chunkSize));
- if (length >= 0) {
- // Make sure endOffset points to end of a checksumed chunk.
- long tmpLen = startOffset + length;
- if (tmpLen % chunkSize != 0) {
- tmpLen += (chunkSize - tmpLen % chunkSize);
- }
- if (tmpLen < endOffset) {
- // will use on-disk checksum here since the end is a stable chunk
- endOffset = tmpLen;
- }
- }
-
- // seek to the right offsets
- if (offset > 0) {
- long checksumSkip = (offset / chunkSize) * checksumSize;
- // note blockInStream is seeked when created below
- if (checksumSkip > 0) {
- // Should we use seek() for checksum file as well?
- IOUtils.skipFully(checksumIn, checksumSkip);
- }
- }
- seqno = 0;
-
- blockIn = streamFactory.createStream(offset);
- } catch (IOException ioe) {
- IOUtils.closeStream(this);
- IOUtils.closeStream(blockIn);
- throw ioe;
- }
- }
-
- /**
- * close opened files.
- */
- public void close() throws IOException {
- IOException ioe = null;
- // close checksum file
- if(checksumIn!=null) {
- try {
- checksumIn.close();
- } catch (IOException e) {
- ioe = e;
- }
- checksumIn = null;
- }
- // close data file
- if(blockIn!=null) {
- try {
- blockIn.close();
- } catch (IOException e) {
- ioe = e;
- }
- blockIn = null;
- }
- // throw IOException if there is any
- if(ioe!= null) {
- throw ioe;
- }
- }
-
- /**
- * Converts an IOExcpetion (not subclasses) to SocketException.
- * This is typically done to indicate to upper layers that the error
- * was a socket error rather than often more serious exceptions like
- * disk errors.
- */
- private static IOException ioeToSocketException(IOException ioe) {
- if (ioe.getClass().equals(IOException.class)) {
- // "se" could be a new class in stead of SocketException.
- IOException se = new SocketException("Original Exception : " + ioe);
- se.initCause(ioe);
- /* Change the stacktrace so that original trace is not truncated
- * when printed.*/
- se.setStackTrace(ioe.getStackTrace());
- return se;
- }
- // otherwise just return the same exception.
- return ioe;
- }
-
- /**
- * @param datalen Length of data
- * @return number of chunks for data of given size
- */
- private int numberOfChunks(long datalen) {
- return (int) ((datalen + chunkSize - 1)/chunkSize);
- }
-
- /**
- * Write packet header into {@code pkt}
- */
- private void writePacketHeader(ByteBuffer pkt, int dataLen, int packetLen) {
- pkt.clear();
- PacketHeader header = new PacketHeader(packetLen, offset, seqno,
- (dataLen == 0), dataLen, false);
- header.putInBuffer(pkt);
- }
-
- /**
- * Read checksum into given buffer
- * @param buf buffer to read the checksum into
- * @param checksumOffset offset at which to write the checksum into buf
- * @param checksumLen length of checksum to write
- * @throws IOException on error
- */
- private void readChecksum(byte[] buf, final int checksumOffset,
- final int checksumLen) throws IOException {
- if (checksumSize <= 0 && checksumIn == null) {
- return;
- }
- try {
- checksumIn.readFully(buf, checksumOffset, checksumLen);
- } catch (IOException e) {
- LOG.warn(" Could not read or failed to veirfy checksum for data"
- + " at offset " + offset + " for block " + block, e);
- IOUtils.closeStream(checksumIn);
- checksumIn = null;
- if (corruptChecksumOk) {
- if (checksumOffset < checksumLen) {
- // Just fill the array with zeros.
- Arrays.fill(buf, checksumOffset, checksumLen, (byte) 0);
- }
- } else {
- throw e;
- }
- }
- }
-
- /**
- * Sends a packet with up to maxChunks chunks of data.
- *
- * @param pkt buffer used for writing packet data
- * @param maxChunks maximum number of chunks to send
- * @param out stream to send data to
- * @param transferTo use transferTo to send data
- * @param throttler used for throttling data transfer bandwidth
- */
- private int sendPacket(ByteBuffer pkt, int maxChunks, OutputStream out,
- boolean transferTo, DataTransferThrottler throttler) throws IOException {
- int dataLen = (int) Math.min(endOffset - offset,
- (chunkSize * (long) maxChunks));
-
- int numChunks = numberOfChunks(dataLen); // Number of chunks be sent in the packet
- int checksumDataLen = numChunks * checksumSize;
- int packetLen = dataLen + checksumDataLen + 4;
- boolean lastDataPacket = offset + dataLen == endOffset && dataLen > 0;
-
- writePacketHeader(pkt, dataLen, packetLen);
-
- int checksumOff = pkt.position();
- byte[] buf = pkt.array();
-
- if (checksumSize > 0 && checksumIn != null) {
- readChecksum(buf, checksumOff, checksumDataLen);
-
- // write in progress that we need to use to get last checksum
- if (lastDataPacket && lastChunkChecksum != null) {
- int start = checksumOff + checksumDataLen - checksumSize;
- byte[] updatedChecksum = lastChunkChecksum.getChecksum();
-
- if (updatedChecksum != null) {
- System.arraycopy(updatedChecksum, 0, buf, start, checksumSize);
- }
- }
- }
-
- int dataOff = checksumOff + checksumDataLen;
- if (!transferTo) { // normal transfer
- IOUtils.readFully(blockIn, buf, dataOff, dataLen);
-
- if (verifyChecksum) {
- verifyChecksum(buf, dataOff, dataLen, numChunks, checksumOff);
- }
- }
-
- try {
- if (transferTo) {
- SocketOutputStream sockOut = (SocketOutputStream)out;
- sockOut.write(buf, 0, dataOff); // First write checksum
-
- // no need to flush. since we know out is not a buffered stream.
- sockOut.transferToFully(((FileInputStream)blockIn).getChannel(),
- blockInPosition, dataLen);
- blockInPosition += dataLen;
- } else {
- // normal transfer
- out.write(buf, 0, dataOff + dataLen);
- }
- } catch (IOException e) {
- /* Exception while writing to the client. Connection closure from
- * the other end is mostly the case and we do not care much about
- * it. But other things can go wrong, especially in transferTo(),
- * which we do not want to ignore.
- *
- * The message parsing below should not be considered as a good
- * coding example. NEVER do it to drive a program logic. NEVER.
- * It was done here because the NIO throws an IOException for EPIPE.
- */
- String ioem = e.getMessage();
- if (!ioem.startsWith("Broken pipe") && !ioem.startsWith("Connection reset")) {
- LOG.error("BlockSender.sendChunks() exception: ", e);
- }
- throw ioeToSocketException(e);
- }
-
- if (throttler != null) { // rebalancing so throttle
- throttler.throttle(packetLen);
- }
-
- return dataLen;
- }
-
- /**
- * Compute checksum for chunks and verify the checksum that is read from
- * the metadata file is correct.
- *
- * @param buf buffer that has checksum and data
- * @param dataOffset position where data is written in the buf
- * @param datalen length of data
- * @param numChunks number of chunks corresponding to data
- * @param checksumOffset offset where checksum is written in the buf
- * @throws ChecksumException on failed checksum verification
- */
- public void verifyChecksum(final byte[] buf, final int dataOffset,
- final int datalen, final int numChunks, final int checksumOffset)
- throws ChecksumException {
- int dOff = dataOffset;
- int cOff = checksumOffset;
- int dLeft = datalen;
-
- for (int i = 0; i < numChunks; i++) {
- checksum.reset();
- int dLen = Math.min(dLeft, chunkSize);
- checksum.update(buf, dOff, dLen);
- if (!checksum.compare(buf, cOff)) {
- long failedPos = offset + datalen - dLeft;
- throw new ChecksumException("Checksum failed at " + failedPos,
- failedPos);
- }
- dLeft -= dLen;
- dOff += dLen;
- cOff += checksumSize;
- }
- }
-
-
- /**
- * sendBlock() is used to read block and its metadata and stream the data to
- * either a client or to another datanode.
- *
- * @param out stream to which the block is written to
- * @param baseStream optional. if non-null, out is assumed to
- * be a wrapper over this stream. This enables optimizations for
- * sending the data, e.g.
- * {@link SocketOutputStream#transferToFully(FileChannel,
- * long, int)}.
- * @return total bytes reads, including crc.
- */
- public long sendBlock(DataOutputStream out, OutputStream baseStream)
- throws IOException {
- if (out == null) {
- throw new IOException( "out stream is null" );
- }
- initialOffset = offset;
- long totalRead = 0;
- OutputStream streamForSendChunks = out;
-
- final long startTime = ClientTraceLog.isInfoEnabled() ? System.nanoTime() : 0;
- try {
- int maxChunksPerPacket;
- int pktSize = PacketHeader.PKT_HEADER_LEN;
- boolean transferTo = transferToAllowed && !verifyChecksum
- && baseStream instanceof SocketOutputStream
- && blockIn instanceof FileInputStream;
- if (transferTo) {
- FileChannel fileChannel = ((FileInputStream)blockIn).getChannel();
- blockInPosition = fileChannel.position();
- streamForSendChunks = baseStream;
- maxChunksPerPacket = numberOfChunks(TRANSFERTO_BUFFER_SIZE);
-
- // Smaller packet size to only hold checksum when doing transferTo
- pktSize += checksumSize * maxChunksPerPacket;
- } else {
- maxChunksPerPacket = Math.max(1,
- numberOfChunks(HdfsConstants.IO_FILE_BUFFER_SIZE));
- // Packet size includes both checksum and data
- pktSize += (chunkSize + checksumSize) * maxChunksPerPacket;
- }
-
- ByteBuffer pktBuf = ByteBuffer.allocate(pktSize);
-
- while (endOffset > offset) {
- long len = sendPacket(pktBuf, maxChunksPerPacket, streamForSendChunks,
- transferTo, null);
- offset += len;
- totalRead += len + (numberOfChunks(len) * checksumSize);
- seqno++;
- }
- try {
- // send an empty packet to mark the end of the block
- sendPacket(pktBuf, maxChunksPerPacket, streamForSendChunks, transferTo,
- null);
- out.flush();
- } catch (IOException e) { //socket error
- throw ioeToSocketException(e);
- }
- blockReadFully = true;
- } finally {
- if (clientTraceFmt != null) {
- final long endTime = System.nanoTime();
- ClientTraceLog.info(String.format(clientTraceFmt, totalRead,
- initialOffset, endTime - startTime));
- }
- close();
- }
- return totalRead;
- }
-
- boolean isBlockReadFully() {
- return blockReadFully;
- }
-
- public static interface InputStreamFactory {
- public InputStream createStream(long offset) throws IOException;
- }
-
- /**
- * @return the checksum type that will be used with this block transfer.
- */
- public DataChecksum getChecksum() {
- return checksum;
- }
-
- private static class BlockInputStreamFactory implements InputStreamFactory {
- private final ExtendedBlock block;
- private final FsDatasetSpi> data;
-
- private BlockInputStreamFactory(ExtendedBlock block, FsDatasetSpi> data) {
- this.block = block;
- this.data = data;
- }
-
- @Override
- public InputStream createStream(long offset) throws IOException {
- return data.getBlockInputStream(block, offset);
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRaidUtil.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRaidUtil.java
deleted file mode 100644
index 92586961564..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRaidUtil.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * 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.server.namenode;
-
-import java.io.*;
-
-import org.apache.hadoop.classification.*;
-import org.apache.hadoop.fs.*;
-import org.apache.hadoop.hdfs.protocol.*;
-import org.apache.hadoop.ipc.StandbyException;
-import org.apache.hadoop.security.AccessControlException;
-
-/** Utilities used by RAID for accessing NameNode. */
-@InterfaceAudience.Private
-@InterfaceStability.Unstable
-public class NameNodeRaidUtil {
- /** Accessing FSDirectory.getFileInfo(..) */
- public static HdfsFileStatus getFileInfo(final FSDirectory dir,
- final String src, final boolean resolveLink
- ) throws UnresolvedLinkException {
- return dir.getFileInfo(src, resolveLink);
- }
-
- /** Accessing FSNamesystem.getFileInfo(..)
- * @throws StandbyException */
- public static HdfsFileStatus getFileInfo(final FSNamesystem namesystem,
- final String src, final boolean resolveLink
- ) throws AccessControlException, UnresolvedLinkException, StandbyException {
- return namesystem.getFileInfo(src, resolveLink);
- }
-
- /** Accessing FSNamesystem.getBlockLocations(..) */
- public static LocatedBlocks getBlockLocations(final FSNamesystem namesystem,
- final String src, final long offset, final long length,
- final boolean doAccessTime, final boolean needBlockToken
- ) throws FileNotFoundException, UnresolvedLinkException, IOException {
- return namesystem.getBlockLocations(src, offset, length,
- doAccessTime, needBlockToken, true);
- }
-}
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/BlockFixer.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/BlockFixer.java
deleted file mode 100644
index dd2fb96c2ba..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/BlockFixer.java
+++ /dev/null
@@ -1,840 +0,0 @@
-/**
- * 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.raid;
-
-import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_CLIENT_SOCKET_TIMEOUT_KEY;
-import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_SOCKET_WRITE_TIMEOUT_KEY;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.channels.SocketChannel;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-import org.apache.hadoop.util.DataChecksum;
-import org.apache.hadoop.hdfs.DistributedFileSystem;
-import org.apache.hadoop.hdfs.protocol.datatransfer.*;
-import org.apache.hadoop.hdfs.protocol.Block;
-import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.FSConstants;
-import org.apache.hadoop.hdfs.protocol.HdfsConstants;
-import org.apache.hadoop.hdfs.protocol.HdfsConstants.DatanodeReportType;
-import org.apache.hadoop.hdfs.protocol.LocatedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.hdfs.server.common.HdfsServerConstants;
-import org.apache.hadoop.hdfs.server.datanode.BlockMetadataHeader;
-import org.apache.hadoop.hdfs.server.datanode.DataNode;
-import org.apache.hadoop.hdfs.server.datanode.RaidBlockSender;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.conf.Configured;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-import org.apache.hadoop.io.Text;
-import org.apache.hadoop.util.Progressable;
-import org.apache.hadoop.net.NetUtils;
-
-import org.apache.hadoop.raid.RaidNode;
-import org.apache.hadoop.raid.RaidUtils;
-
-
-/**
- * contains the core functionality of the block fixer
- *
- * configuration options:
- * raid.blockfix.classname - the class name of the block fixer
- * implementation to use
- *
- * raid.blockfix.interval - interval between checks for corrupt files
- *
- * raid.blockfix.history.interval - interval before fixing same file again
- *
- * raid.blockfix.read.timeout - read time out
- *
- * raid.blockfix.write.timeout - write time out
- */
-public abstract class BlockFixer extends Configured implements Runnable {
-
- public static final String BLOCKFIX_CLASSNAME = "raid.blockfix.classname";
- public static final String BLOCKFIX_INTERVAL = "raid.blockfix.interval";
- public static final String BLOCKFIX_HISTORY_INTERVAL =
- "raid.blockfix.history.interval";
- public static final String BLOCKFIX_READ_TIMEOUT =
- "raid.blockfix.read.timeout";
- public static final String BLOCKFIX_WRITE_TIMEOUT =
- "raid.blockfix.write.timeout";
-
- public static final long DEFAULT_BLOCKFIX_INTERVAL = 60 * 1000; // 1 min
- public static final long DEFAULT_BLOCKFIX_HISTORY_INTERVAL =
- 60 * 60 * 1000; // 60 mins
-
- public static BlockFixer createBlockFixer(Configuration conf)
- throws ClassNotFoundException {
- try {
- // default to distributed block fixer
- Class> blockFixerClass =
- conf.getClass(BLOCKFIX_CLASSNAME, DistBlockFixer.class);
- if (!BlockFixer.class.isAssignableFrom(blockFixerClass)) {
- throw new ClassNotFoundException("not an implementation of blockfixer");
- }
- Constructor> constructor =
- blockFixerClass.getConstructor(new Class[] {Configuration.class} );
- return (BlockFixer) constructor.newInstance(conf);
- } catch (NoSuchMethodException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- } catch (InstantiationException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- } catch (IllegalAccessException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- } catch (InvocationTargetException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- }
- }
-
- private long numFilesFixed = 0;
-
- public volatile boolean running = true;
-
- // interval between checks for corrupt files
- protected long blockFixInterval;
-
- // interval before fixing same file again
- protected long historyInterval;
-
- public BlockFixer(Configuration conf) {
- super(conf);
- blockFixInterval =
- getConf().getLong(BLOCKFIX_INTERVAL, DEFAULT_BLOCKFIX_INTERVAL);
- historyInterval =
- getConf().getLong(BLOCKFIX_HISTORY_INTERVAL,
- DEFAULT_BLOCKFIX_HISTORY_INTERVAL);
-
- }
-
- @Override
- public abstract void run();
-
- /**
- * returns the number of files that have been fixed by this block fixer
- */
- public synchronized long filesFixed() {
- return numFilesFixed;
- }
-
- /**
- * increments the number of files that have been fixed by this block fixer
- */
- protected synchronized void incrFilesFixed() {
- numFilesFixed++;
- }
-
- /**
- * increments the number of files that have been fixed by this block fixer
- */
- protected synchronized void incrFilesFixed(long incr) {
- if (incr < 0) {
- throw new IllegalArgumentException("cannot increment by negative value " +
- incr);
- }
-
- numFilesFixed += incr;
- }
-
- static boolean isSourceFile(Path p, String[] destPrefixes) {
- String pathStr = p.toUri().getPath();
- for (String destPrefix: destPrefixes) {
- if (pathStr.startsWith(destPrefix)) {
- return false;
- }
- }
- return true;
- }
-
- void filterUnfixableSourceFiles(Iterator it) throws IOException {
- String xorPrefix = RaidNode.xorDestinationPath(getConf()).toUri().getPath();
- if (!xorPrefix.endsWith(Path.SEPARATOR)) {
- xorPrefix += Path.SEPARATOR;
- }
- String rsPrefix = RaidNode.rsDestinationPath(getConf()).toUri().getPath();
- if (!rsPrefix.endsWith(Path.SEPARATOR)) {
- rsPrefix += Path.SEPARATOR;
- }
- String[] destPrefixes = new String[]{xorPrefix, rsPrefix};
- while (it.hasNext()) {
- Path p = it.next();
- if (isSourceFile(p, destPrefixes) &&
- RaidNode.xorParityForSource(p, getConf()) == null &&
- RaidNode.rsParityForSource(p, getConf()) == null) {
- it.remove();
- }
- }
- }
-
- /**
- * this class implements the actual fixing functionality
- * we keep this in a separate class so that
- * the distributed block fixer can use it
- */
- static class BlockFixerHelper extends Configured {
-
- public static final Log LOG = LogFactory.getLog(BlockFixer.
- BlockFixerHelper.class);
-
- private String xorPrefix;
- private String rsPrefix;
- private XOREncoder xorEncoder;
- private XORDecoder xorDecoder;
- private ReedSolomonEncoder rsEncoder;
- private ReedSolomonDecoder rsDecoder;
-
- public BlockFixerHelper(Configuration conf) throws IOException {
- super(conf);
-
- xorPrefix = RaidNode.xorDestinationPath(getConf()).toUri().getPath();
- if (!xorPrefix.endsWith(Path.SEPARATOR)) {
- xorPrefix += Path.SEPARATOR;
- }
- rsPrefix = RaidNode.rsDestinationPath(getConf()).toUri().getPath();
- if (!rsPrefix.endsWith(Path.SEPARATOR)) {
- rsPrefix += Path.SEPARATOR;
- }
- int stripeLength = RaidNode.getStripeLength(getConf());
- xorEncoder = new XOREncoder(getConf(), stripeLength);
- xorDecoder = new XORDecoder(getConf(), stripeLength);
- int parityLength = RaidNode.rsParityLength(getConf());
- rsEncoder = new ReedSolomonEncoder(getConf(), stripeLength, parityLength);
- rsDecoder = new ReedSolomonDecoder(getConf(), stripeLength, parityLength);
-
- }
-
- /**
- * checks whether file is xor parity file
- */
- boolean isXorParityFile(Path p) {
- String pathStr = p.toUri().getPath();
- if (pathStr.contains(RaidNode.HAR_SUFFIX)) {
- return false;
- }
- return pathStr.startsWith(xorPrefix);
- }
-
- /**
- * checks whether file is rs parity file
- */
- boolean isRsParityFile(Path p) {
- String pathStr = p.toUri().getPath();
- if (pathStr.contains(RaidNode.HAR_SUFFIX)) {
- return false;
- }
- return pathStr.startsWith(rsPrefix);
- }
-
- /**
- * Fix a file, do not report progess.
- *
- * @return true if file has been fixed, false if no fixing
- * was necessary or possible.
- */
- boolean fixFile(Path srcPath) throws IOException {
- return fixFile(srcPath, new RaidUtils.DummyProgressable());
- }
-
- /**
- * Fix a file, report progess.
- *
- * @return true if file has been fixed, false if no fixing
- * was necessary or possible.
- */
- boolean fixFile(Path srcPath, Progressable progress) throws IOException {
-
- if (RaidNode.isParityHarPartFile(srcPath)) {
- return processCorruptParityHarPartFile(srcPath, progress);
- }
-
- // The corrupted file is a XOR parity file
- if (isXorParityFile(srcPath)) {
- return processCorruptParityFile(srcPath, xorEncoder, progress);
- }
-
- // The corrupted file is a ReedSolomon parity file
- if (isRsParityFile(srcPath)) {
- return processCorruptParityFile(srcPath, rsEncoder, progress);
- }
-
- // The corrupted file is a source file
- RaidNode.ParityFilePair ppair =
- RaidNode.xorParityForSource(srcPath, getConf());
- Decoder decoder = null;
- if (ppair != null) {
- decoder = xorDecoder;
- } else {
- ppair = RaidNode.rsParityForSource(srcPath, getConf());
- if (ppair != null) {
- decoder = rsDecoder;
- }
- }
-
- // If we have a parity file, process the file and fix it.
- if (ppair != null) {
- return processCorruptFile(srcPath, ppair, decoder, progress);
- }
-
- // there was nothing to do
- return false;
- }
-
- /**
- * Sorts source files ahead of parity files.
- */
- void sortCorruptFiles(List files) {
- // TODO: We should first fix the files that lose more blocks
- Comparator comp = new Comparator() {
- public int compare(Path p1, Path p2) {
- if (isXorParityFile(p2) || isRsParityFile(p2)) {
- // If p2 is a parity file, p1 is smaller.
- return -1;
- }
- if (isXorParityFile(p1) || isRsParityFile(p1)) {
- // If p1 is a parity file, p2 is smaller.
- return 1;
- }
- // If both are source files, they are equal.
- return 0;
- }
- };
- Collections.sort(files, comp);
- }
-
- /**
- * Returns a DistributedFileSystem hosting the path supplied.
- */
- protected DistributedFileSystem getDFS(Path p) throws IOException {
- return (DistributedFileSystem) p.getFileSystem(getConf());
- }
-
- /**
- * Reads through a corrupt source file fixing corrupt blocks on the way.
- * @param srcPath Path identifying the corrupt file.
- * @throws IOException
- * @return true if file has been fixed, false if no fixing
- * was necessary or possible.
- */
- boolean processCorruptFile(Path srcPath, RaidNode.ParityFilePair parityPair,
- Decoder decoder, Progressable progress)
- throws IOException {
- LOG.info("Processing corrupt file " + srcPath);
-
- DistributedFileSystem srcFs = getDFS(srcPath);
- FileStatus srcStat = srcFs.getFileStatus(srcPath);
- long blockSize = srcStat.getBlockSize();
- long srcFileSize = srcStat.getLen();
- String uriPath = srcPath.toUri().getPath();
-
- int numBlocksFixed = 0;
- List corrupt =
- RaidDFSUtil.corruptBlocksInFile(srcFs, uriPath, 0, srcFileSize);
- if (corrupt.size() == 0) {
- return false;
- }
- for (LocatedBlock lb: corrupt) {
- ExtendedBlock corruptBlock = lb.getBlock();
- long corruptOffset = lb.getStartOffset();
-
- LOG.info("Found corrupt block " + corruptBlock +
- ", offset " + corruptOffset);
-
- final long blockContentsSize =
- Math.min(blockSize, srcFileSize - corruptOffset);
- File localBlockFile =
- File.createTempFile(corruptBlock.getBlockName(), ".tmp");
- localBlockFile.deleteOnExit();
-
- try {
- decoder.recoverBlockToFile(srcFs, srcPath, parityPair.getFileSystem(),
- parityPair.getPath(), blockSize,
- corruptOffset, localBlockFile,
- blockContentsSize);
-
- // We have a the contents of the block, send them.
- DatanodeInfo datanode = chooseDatanode(lb.getLocations());
- computeMetadataAndSendFixedBlock(datanode, localBlockFile,
- lb, blockContentsSize);
- numBlocksFixed++;
- } finally {
- localBlockFile.delete();
- }
- progress.progress();
- }
- LOG.info("Fixed " + numBlocksFixed + " blocks in " + srcPath);
- return true;
- }
-
- /**
- * Fixes corrupt blocks in a parity file.
- * This function uses the corresponding source file to regenerate parity
- * file blocks.
- * @return true if file has been fixed, false if no fixing
- * was necessary or possible.
- */
- boolean processCorruptParityFile(Path parityPath, Encoder encoder,
- Progressable progress)
- throws IOException {
- LOG.info("Processing corrupt file " + parityPath);
- Path srcPath = sourcePathFromParityPath(parityPath);
- if (srcPath == null) {
- LOG.warn("Unusable parity file " + parityPath);
- return false;
- }
-
- DistributedFileSystem parityFs = getDFS(parityPath);
- FileStatus parityStat = parityFs.getFileStatus(parityPath);
- long blockSize = parityStat.getBlockSize();
- long parityFileSize = parityStat.getLen();
- FileStatus srcStat = getDFS(srcPath).getFileStatus(srcPath);
- long srcFileSize = srcStat.getLen();
-
- // Check timestamp.
- if (srcStat.getModificationTime() != parityStat.getModificationTime()) {
- LOG.info("Mismatching timestamp for " + srcPath + " and " + parityPath +
- ", moving on...");
- return false;
- }
-
- String uriPath = parityPath.toUri().getPath();
- int numBlocksFixed = 0;
- List corrupt =
- RaidDFSUtil.corruptBlocksInFile(parityFs, uriPath, 0, parityFileSize);
- if (corrupt.size() == 0) {
- return false;
- }
- for (LocatedBlock lb: corrupt) {
- ExtendedBlock corruptBlock = lb.getBlock();
- long corruptOffset = lb.getStartOffset();
-
- LOG.info("Found corrupt block " + corruptBlock +
- ", offset " + corruptOffset);
-
- File localBlockFile =
- File.createTempFile(corruptBlock.getBlockName(), ".tmp");
- localBlockFile.deleteOnExit();
-
- try {
- encoder.recoverParityBlockToFile(parityFs, srcPath, srcFileSize,
- blockSize, parityPath,
- corruptOffset, localBlockFile);
- // We have a the contents of the block, send them.
- DatanodeInfo datanode = chooseDatanode(lb.getLocations());
- computeMetadataAndSendFixedBlock(datanode, localBlockFile, lb,
- blockSize);
-
- numBlocksFixed++;
- } finally {
- localBlockFile.delete();
- }
- progress.progress();
- }
- LOG.info("Fixed " + numBlocksFixed + " blocks in " + parityPath);
- return true;
- }
-
- /**
- * Reads through a parity HAR part file, fixing corrupt blocks on the way.
- * A HAR block can contain many file blocks, as long as the HAR part file
- * block size is a multiple of the file block size.
- * @return true if file has been fixed, false if no fixing
- * was necessary or possible.
- */
- boolean processCorruptParityHarPartFile(Path partFile,
- Progressable progress)
- throws IOException {
- LOG.info("Processing corrupt file " + partFile);
- // Get some basic information.
- DistributedFileSystem dfs = getDFS(partFile);
- FileStatus partFileStat = dfs.getFileStatus(partFile);
- long partFileSize = partFileStat.getLen();
- long partFileBlockSize = partFileStat.getBlockSize();
- LOG.info(partFile + " has block size " + partFileBlockSize);
-
- // Find the path to the index file.
- // Parity file HARs are only one level deep, so the index files is at the
- // same level as the part file.
- String harDirectory = partFile.toUri().getPath(); // Temporarily.
- harDirectory =
- harDirectory.substring(0, harDirectory.lastIndexOf(Path.SEPARATOR));
- Path indexFile = new Path(harDirectory + "/" + HarIndex.indexFileName);
- FileStatus indexStat = dfs.getFileStatus(indexFile);
- // Parses through the HAR index file.
- HarIndex harIndex = new HarIndex(dfs.open(indexFile), indexStat.getLen());
-
- String uriPath = partFile.toUri().getPath();
- int numBlocksFixed = 0;
- List corrupt =
- RaidDFSUtil.corruptBlocksInFile(dfs, uriPath, 0, partFileSize);
- if (corrupt.size() == 0) {
- return false;
- }
- for (LocatedBlock lb: corrupt) {
- ExtendedBlock corruptBlock = lb.getBlock();
- long corruptOffset = lb.getStartOffset();
-
- File localBlockFile =
- File.createTempFile(corruptBlock.getBlockName(), ".tmp");
- localBlockFile.deleteOnExit();
- processCorruptParityHarPartBlock(dfs, partFile, corruptBlock,
- corruptOffset, partFileStat, harIndex,
- localBlockFile, progress);
- // Now we have recovered the part file block locally, send it.
- try {
- DatanodeInfo datanode = chooseDatanode(lb.getLocations());
- computeMetadataAndSendFixedBlock(datanode, localBlockFile,
- lb, localBlockFile.length());
- numBlocksFixed++;
- } finally {
- localBlockFile.delete();
- }
- progress.progress();
- }
- LOG.info("Fixed " + numBlocksFixed + " blocks in " + partFile);
- return true;
- }
-
- /**
- * This fixes a single part file block by recovering in sequence each
- * parity block in the part file block.
- */
- private void processCorruptParityHarPartBlock(FileSystem dfs, Path partFile,
- ExtendedBlock corruptBlock,
- long corruptOffset,
- FileStatus partFileStat,
- HarIndex harIndex,
- File localBlockFile,
- Progressable progress)
- throws IOException {
- String partName = partFile.toUri().getPath(); // Temporarily.
- partName = partName.substring(1 + partName.lastIndexOf(Path.SEPARATOR));
-
- OutputStream out = new FileOutputStream(localBlockFile);
-
- try {
- // A HAR part file block could map to several parity files. We need to
- // use all of them to recover this block.
- final long corruptEnd = Math.min(corruptOffset +
- partFileStat.getBlockSize(),
- partFileStat.getLen());
- for (long offset = corruptOffset; offset < corruptEnd; ) {
- HarIndex.IndexEntry entry = harIndex.findEntry(partName, offset);
- if (entry == null) {
- String msg = "Corrupt index file has no matching index entry for " +
- partName + ":" + offset;
- LOG.warn(msg);
- throw new IOException(msg);
- }
- Path parityFile = new Path(entry.fileName);
- Encoder encoder;
- if (isXorParityFile(parityFile)) {
- encoder = xorEncoder;
- } else if (isRsParityFile(parityFile)) {
- encoder = rsEncoder;
- } else {
- String msg = "Could not figure out parity file correctly";
- LOG.warn(msg);
- throw new IOException(msg);
- }
- Path srcFile = sourcePathFromParityPath(parityFile);
- FileStatus srcStat = dfs.getFileStatus(srcFile);
- if (srcStat.getModificationTime() != entry.mtime) {
- String msg = "Modification times of " + parityFile + " and " +
- srcFile + " do not match.";
- LOG.warn(msg);
- throw new IOException(msg);
- }
- long corruptOffsetInParity = offset - entry.startOffset;
- LOG.info(partFile + ":" + offset + " maps to " +
- parityFile + ":" + corruptOffsetInParity +
- " and will be recovered from " + srcFile);
- encoder.recoverParityBlockToStream(dfs, srcFile, srcStat.getLen(),
- srcStat.getBlockSize(), parityFile,
- corruptOffsetInParity, out);
- // Finished recovery of one parity block. Since a parity block has the
- // same size as a source block, we can move offset by source block size.
- offset += srcStat.getBlockSize();
- LOG.info("Recovered " + srcStat.getBlockSize() + " part file bytes ");
- if (offset > corruptEnd) {
- String msg =
- "Recovered block spills across part file blocks. Cannot continue.";
- throw new IOException(msg);
- }
- progress.progress();
- }
- } finally {
- out.close();
- }
- }
-
- /**
- * Choose a datanode (hostname:portnumber). The datanode is chosen at
- * random from the live datanodes.
- * @param locationsToAvoid locations to avoid.
- * @return A datanode
- * @throws IOException
- */
- private DatanodeInfo chooseDatanode(DatanodeInfo[] locationsToAvoid)
- throws IOException {
- DistributedFileSystem dfs = getDFS(new Path("/"));
- DatanodeInfo[] live =
- dfs.getClient().datanodeReport(DatanodeReportType.LIVE);
- LOG.info("Choosing a datanode from " + live.length +
- " live nodes while avoiding " + locationsToAvoid.length);
- Random rand = new Random();
- DatanodeInfo chosen = null;
- int maxAttempts = 1000;
- for (int i = 0; i < maxAttempts && chosen == null; i++) {
- int idx = rand.nextInt(live.length);
- chosen = live[idx];
- for (DatanodeInfo avoid: locationsToAvoid) {
- if (chosen.getName().equals(avoid.getName())) {
- LOG.info("Avoiding " + avoid.getName());
- chosen = null;
- break;
- }
- }
- }
- if (chosen == null) {
- throw new IOException("Could not choose datanode");
- }
- LOG.info("Choosing datanode " + chosen.getName());
- return chosen;
- }
-
- /**
- * Reads data from the data stream provided and computes metadata.
- */
- static DataInputStream computeMetadata(Configuration conf,
- InputStream dataStream)
- throws IOException {
- ByteArrayOutputStream mdOutBase = new ByteArrayOutputStream(1024*1024);
- DataOutputStream mdOut = new DataOutputStream(mdOutBase);
-
- // First, write out the version.
- mdOut.writeShort(BlockMetadataHeader.VERSION);
-
- // Create a summer and write out its header.
- int bytesPerChecksum = conf.getInt("dfs.bytes-per-checksum", 512);
- DataChecksum sum =
- DataChecksum.newDataChecksum(DataChecksum.CHECKSUM_CRC32,
- bytesPerChecksum);
- sum.writeHeader(mdOut);
-
- // Buffer to read in a chunk of data.
- byte[] buf = new byte[bytesPerChecksum];
- // Buffer to store the checksum bytes.
- byte[] chk = new byte[sum.getChecksumSize()];
-
- // Read data till we reach the end of the input stream.
- int bytesSinceFlush = 0;
- while (true) {
- // Read some bytes.
- int bytesRead = dataStream.read(buf, bytesSinceFlush,
- bytesPerChecksum-bytesSinceFlush);
- if (bytesRead == -1) {
- if (bytesSinceFlush > 0) {
- boolean reset = true;
- sum.writeValue(chk, 0, reset); // This also resets the sum.
- // Write the checksum to the stream.
- mdOut.write(chk, 0, chk.length);
- bytesSinceFlush = 0;
- }
- break;
- }
- // Update the checksum.
- sum.update(buf, bytesSinceFlush, bytesRead);
- bytesSinceFlush += bytesRead;
-
- // Flush the checksum if necessary.
- if (bytesSinceFlush == bytesPerChecksum) {
- boolean reset = true;
- sum.writeValue(chk, 0, reset); // This also resets the sum.
- // Write the checksum to the stream.
- mdOut.write(chk, 0, chk.length);
- bytesSinceFlush = 0;
- }
- }
-
- byte[] mdBytes = mdOutBase.toByteArray();
- return new DataInputStream(new ByteArrayInputStream(mdBytes));
- }
-
- private void computeMetadataAndSendFixedBlock(DatanodeInfo datanode,
- File localBlockFile,
- LocatedBlock block,
- long blockSize)
- throws IOException {
-
- LOG.info("Computing metdata");
- InputStream blockContents = null;
- DataInputStream blockMetadata = null;
- try {
- blockContents = new FileInputStream(localBlockFile);
- blockMetadata = computeMetadata(getConf(), blockContents);
- blockContents.close();
- // Reopen
- blockContents = new FileInputStream(localBlockFile);
- sendFixedBlock(datanode, blockContents, blockMetadata, block,
- blockSize);
- } finally {
- if (blockContents != null) {
- blockContents.close();
- blockContents = null;
- }
- if (blockMetadata != null) {
- blockMetadata.close();
- blockMetadata = null;
- }
- }
- }
-
- /**
- * Send a generated block to a datanode.
- * @param datanode Chosen datanode name in host:port form.
- * @param blockContents Stream with the block contents.
- * @param corruptBlock Block identifying the block to be sent.
- * @param blockSize size of the block.
- * @throws IOException
- */
- private void sendFixedBlock(DatanodeInfo datanode,
- final InputStream blockContents,
- DataInputStream metadataIn,
- LocatedBlock block, long blockSize)
- throws IOException {
- InetSocketAddress target = NetUtils.createSocketAddr(datanode.getName());
- Socket sock = SocketChannel.open().socket();
-
- int readTimeout =
- getConf().getInt(BLOCKFIX_READ_TIMEOUT,
- HdfsServerConstants.READ_TIMEOUT);
- NetUtils.connect(sock, target, readTimeout);
- sock.setSoTimeout(readTimeout);
-
- int writeTimeout = getConf().getInt(BLOCKFIX_WRITE_TIMEOUT,
- HdfsServerConstants.WRITE_TIMEOUT);
-
- OutputStream baseStream = NetUtils.getOutputStream(sock, writeTimeout);
- DataOutputStream out =
- new DataOutputStream(new BufferedOutputStream(baseStream,
- HdfsConstants.
- SMALL_BUFFER_SIZE));
-
- boolean corruptChecksumOk = false;
- boolean chunkOffsetOK = false;
- boolean verifyChecksum = true;
- boolean transferToAllowed = false;
-
- try {
- LOG.info("Sending block " + block.getBlock() +
- " from " + sock.getLocalSocketAddress().toString() +
- " to " + sock.getRemoteSocketAddress().toString() +
- " " + blockSize + " bytes");
- RaidBlockSender blockSender =
- new RaidBlockSender(block.getBlock(), blockSize, 0, blockSize,
- corruptChecksumOk, chunkOffsetOK, verifyChecksum,
- transferToAllowed, metadataIn,
- new RaidBlockSender.InputStreamFactory() {
- @Override
- public InputStream
- createStream(long offset) throws IOException {
- // we are passing 0 as the offset above,
- // so we can safely ignore
- // the offset passed
- return blockContents;
- }
- });
-
- DatanodeInfo[] nodes = new DatanodeInfo[]{datanode};
- DataChecksum checksum = blockSender.getChecksum();
- new Sender(out).writeBlock(block.getBlock(), block.getBlockToken(), "",
- nodes, null, BlockConstructionStage.PIPELINE_SETUP_CREATE,
- 1, 0L, blockSize, 0L, DataChecksum.newDataChecksum(
- checksum.getChecksumType(), checksum.getBytesPerChecksum()));
- blockSender.sendBlock(out, baseStream);
-
- LOG.info("Sent block " + block.getBlock() + " to " + datanode.getName());
- } finally {
- out.close();
- }
- }
-
- /**
- * returns the source file corresponding to a parity file
- */
- Path sourcePathFromParityPath(Path parityPath) {
- String parityPathStr = parityPath.toUri().getPath();
- if (parityPathStr.startsWith(xorPrefix)) {
- // Remove the prefix to get the source file.
- String src = parityPathStr.replaceFirst(xorPrefix, "/");
- return new Path(src);
- } else if (parityPathStr.startsWith(rsPrefix)) {
- // Remove the prefix to get the source file.
- String src = parityPathStr.replaceFirst(rsPrefix, "/");
- return new Path(src);
- }
- return null;
- }
-
- /**
- * Returns the corrupt blocks in a file.
- */
- List corruptBlocksInFile(DistributedFileSystem fs,
- String uriPath, FileStatus stat)
- throws IOException {
- List corrupt = new LinkedList();
- LocatedBlocks locatedBlocks =
- RaidDFSUtil.getBlockLocations(fs, uriPath, 0, stat.getLen());
- for (LocatedBlock b: locatedBlocks.getLocatedBlocks()) {
- if (b.isCorrupt() ||
- (b.getLocations().length == 0 && b.getBlockSize() > 0)) {
- corrupt.add(b);
- }
- }
- return corrupt;
- }
- }
-
-}
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ConfigManager.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ConfigManager.java
deleted file mode 100644
index 0ae288dcb43..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ConfigManager.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Text;
-import org.xml.sax.SAXException;
-
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.raid.protocol.PolicyList;
-
-/**
- * Maintains the configuration xml file that is read into memory.
- */
-class ConfigManager {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.ConfigManager");
-
- /** Time to wait between checks of the config file */
- public static final long RELOAD_INTERVAL = 10 * 1000;
-
- /** Time to wait between successive runs of all policies */
- public static final long RESCAN_INTERVAL = 3600 * 1000;
-
- public static final long HAR_PARTFILE_SIZE = 10 * 1024 * 1024 * 1024l;
-
- public static final int DISTRAID_MAX_JOBS = 10;
-
- public static final int DISTRAID_MAX_FILES = 10000;
-
- /**
- * Time to wait after the config file has been modified before reloading it
- * (this is done to prevent loading a file that hasn't been fully written).
- */
- public static final long RELOAD_WAIT = 5 * 1000;
-
- private Configuration conf; // Hadoop configuration
- private String configFileName; // Path to config XML file
-
- private long lastReloadAttempt; // Last time we tried to reload the config file
- private long lastSuccessfulReload; // Last time we successfully reloaded config
- private boolean lastReloadAttemptFailed = false;
- private long reloadInterval = RELOAD_INTERVAL;
- private long periodicity; // time between runs of all policies
- private long harPartfileSize;
- private int maxJobsPerPolicy; // Max no. of jobs running simultaneously for
- // a job.
- private int maxFilesPerJob; // Max no. of files raided by a job.
-
- // Reload the configuration
- private boolean doReload;
- private Thread reloadThread;
- private volatile boolean running = false;
-
- // Collection of all configured policies.
- Collection allPolicies = new ArrayList();
-
- public ConfigManager(Configuration conf) throws IOException, SAXException,
- RaidConfigurationException, ClassNotFoundException, ParserConfigurationException {
- this.conf = conf;
- this.configFileName = conf.get("raid.config.file");
- this.doReload = conf.getBoolean("raid.config.reload", true);
- this.reloadInterval = conf.getLong("raid.config.reload.interval", RELOAD_INTERVAL);
- this.periodicity = conf.getLong("raid.policy.rescan.interval", RESCAN_INTERVAL);
- this.harPartfileSize = conf.getLong("raid.har.partfile.size", HAR_PARTFILE_SIZE);
- this.maxJobsPerPolicy = conf.getInt("raid.distraid.max.jobs",
- DISTRAID_MAX_JOBS);
- this.maxFilesPerJob = conf.getInt("raid.distraid.max.files",
- DISTRAID_MAX_FILES);
- if (configFileName == null) {
- String msg = "No raid.config.file given in conf - " +
- "the Hadoop Raid utility cannot run. Aborting....";
- LOG.warn(msg);
- throw new IOException(msg);
- }
- reloadConfigs();
- lastSuccessfulReload = RaidNode.now();
- lastReloadAttempt = RaidNode.now();
- running = true;
- }
-
- /**
- * Reload config file if it hasn't been loaded in a while
- * Returns true if the file was reloaded.
- */
- public synchronized boolean reloadConfigsIfNecessary() {
- long time = RaidNode.now();
- if (time > lastReloadAttempt + reloadInterval) {
- lastReloadAttempt = time;
- try {
- File file = new File(configFileName);
- long lastModified = file.lastModified();
- if (lastModified > lastSuccessfulReload &&
- time > lastModified + RELOAD_WAIT) {
- reloadConfigs();
- lastSuccessfulReload = time;
- lastReloadAttemptFailed = false;
- return true;
- }
- } catch (Exception e) {
- if (!lastReloadAttemptFailed) {
- LOG.error("Failed to reload config file - " +
- "will use existing configuration.", e);
- }
- lastReloadAttemptFailed = true;
- }
- }
- return false;
- }
-
- /**
- * Updates the in-memory data structures from the config file. This file is
- * expected to be in the following whitespace-separated format:
- *
-
-
-
- hdfs://dfsname.myhost.com:9000/archive/
- RaidScanMonthly
-
- targetReplication
- 2
- after RAIDing, decrease the replication factor of the file to
- this value.
-
-
-
- metaReplication
- 2
- the replication factor of the RAID meta file
-
-
-
- stripeLength
- 10
- the number of blocks to RAID together
-
-
-
-
-
- *
- * Blank lines and lines starting with # are ignored.
- *
- * @throws IOException if the config file cannot be read.
- * @throws RaidConfigurationException if configuration entries are invalid.
- * @throws ClassNotFoundException if user-defined policy classes cannot be loaded
- * @throws ParserConfigurationException if XML parser is misconfigured.
- * @throws SAXException if config file is malformed.
- * @returns A new set of policy categories.
- */
- void reloadConfigs() throws IOException, ParserConfigurationException,
- SAXException, ClassNotFoundException, RaidConfigurationException {
-
- if (configFileName == null) {
- return;
- }
-
- File file = new File(configFileName);
- if (!file.exists()) {
- throw new RaidConfigurationException("Configuration file " + configFileName +
- " does not exist.");
- }
-
- // Create some temporary hashmaps to hold the new allocs, and we only save
- // them in our fields if we have parsed the entire allocs file successfully.
- List all = new ArrayList();
- long periodicityValue = periodicity;
-
-
- // Read and parse the configuration file.
- // allow include files in configuration file
- DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
- docBuilderFactory.setIgnoringComments(true);
- docBuilderFactory.setNamespaceAware(true);
- try {
- docBuilderFactory.setXIncludeAware(true);
- } catch (UnsupportedOperationException e) {
- LOG.error("Failed to set setXIncludeAware(true) for raid parser "
- + docBuilderFactory + ":" + e, e);
- }
- LOG.error("Reloading config file " + file);
-
- DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
- Document doc = builder.parse(file);
- Element root = doc.getDocumentElement();
- if (!"configuration".equalsIgnoreCase(root.getTagName()))
- throw new RaidConfigurationException("Bad configuration file: " +
- "top-level element not ");
- NodeList elements = root.getChildNodes();
-
- Map existingPolicies =
- new HashMap();
- // loop through all the configured source paths.
- for (int i = 0; i < elements.getLength(); i++) {
- Node node = elements.item(i);
- if (!(node instanceof Element)) {
- continue;
- }
- Element element = (Element)node;
- String elementTagName = element.getTagName();
- if ("srcPath".equalsIgnoreCase(elementTagName)) {
- String srcPathPrefix = element.getAttribute("prefix");
-
- PolicyList policyList = null;
- if (srcPathPrefix != null && srcPathPrefix.length() != 0) {
- // Empty srcPath will have no effect but policies will be processed
- // This allow us to define some "abstract" policies
- policyList = new PolicyList();
- all.add(policyList);
- policyList.setSrcPath(conf, srcPathPrefix);
- }
-
- // loop through all the policies for this source path
- NodeList policies = element.getChildNodes();
- for (int j = 0; j < policies.getLength(); j++) {
- Node node1 = policies.item(j);
- if (!(node1 instanceof Element)) {
- continue;
- }
- Element policy = (Element)node1;
- if (!"policy".equalsIgnoreCase(policy.getTagName())) {
- throw new RaidConfigurationException("Bad configuration file: " +
- "Expecting for srcPath " + srcPathPrefix);
- }
- String policyName = policy.getAttribute("name");
- PolicyInfo curr = new PolicyInfo(policyName, conf);
- if (srcPathPrefix != null && srcPathPrefix.length() > 0) {
- curr.setSrcPath(srcPathPrefix);
- }
- // loop through all the properties of this policy
- NodeList properties = policy.getChildNodes();
- PolicyInfo parent = null;
- for (int k = 0; k < properties.getLength(); k++) {
- Node node2 = properties.item(k);
- if (!(node2 instanceof Element)) {
- continue;
- }
- Element property = (Element)node2;
- String propertyName = property.getTagName();
- if ("erasureCode".equalsIgnoreCase(propertyName)) {
- String text = ((Text)property.getFirstChild()).getData().trim();
- LOG.info(policyName + ".erasureCode = " + text);
- curr.setErasureCode(text);
- } else if ("description".equalsIgnoreCase(propertyName)) {
- String text = ((Text)property.getFirstChild()).getData().trim();
- curr.setDescription(text);
- } else if ("parentPolicy".equalsIgnoreCase(propertyName)) {
- String text = ((Text)property.getFirstChild()).getData().trim();
- parent = existingPolicies.get(text);
- } else if ("property".equalsIgnoreCase(propertyName)) {
- NodeList nl = property.getChildNodes();
- String pname=null,pvalue=null;
- for (int l = 0; l < nl.getLength(); l++){
- Node node3 = nl.item(l);
- if (!(node3 instanceof Element)) {
- continue;
- }
- Element item = (Element) node3;
- String itemName = item.getTagName();
- if ("name".equalsIgnoreCase(itemName)){
- pname = ((Text)item.getFirstChild()).getData().trim();
- } else if ("value".equalsIgnoreCase(itemName)){
- pvalue = ((Text)item.getFirstChild()).getData().trim();
- }
- }
- if (pname != null && pvalue != null) {
- LOG.info(policyName + "." + pname + " = " + pvalue);
- curr.setProperty(pname,pvalue);
- }
- } else {
- LOG.warn("Found bad property " + propertyName +
- " for srcPath" + srcPathPrefix +
- " policy name " + policyName +
- ". Ignoring.");
- }
- } // done with all properties of this policy
-
- PolicyInfo pinfo;
- if (parent != null) {
- pinfo = new PolicyInfo(policyName, conf);
- pinfo.copyFrom(parent);
- pinfo.copyFrom(curr);
- } else {
- pinfo = curr;
- }
- if (policyList != null) {
- policyList.add(pinfo);
- }
- existingPolicies.put(policyName, pinfo);
-
- } // done with all policies for this srcpath
- }
- } // done with all srcPaths
- setAllPolicies(all);
- periodicity = periodicityValue;
- return;
- }
-
-
- public synchronized long getPeriodicity() {
- return periodicity;
- }
-
- public synchronized long getHarPartfileSize() {
- return harPartfileSize;
- }
-
- public synchronized int getMaxJobsPerPolicy() {
- return maxJobsPerPolicy;
- }
-
- public synchronized int getMaxFilesPerJob() {
- return maxFilesPerJob;
- }
-
- /**
- * Get a collection of all policies
- */
- public synchronized Collection getAllPolicies() {
- return new ArrayList(allPolicies);
- }
-
- /**
- * Set a collection of all policies
- */
- protected synchronized void setAllPolicies(Collection value) {
- this.allPolicies = value;
- }
-
- /**
- * Start a background thread to reload the config file
- */
- void startReload() {
- if (doReload) {
- reloadThread = new UpdateThread();
- reloadThread.start();
- }
- }
-
- /**
- * Stop the background thread that reload the config file
- */
- void stopReload() throws InterruptedException {
- if (reloadThread != null) {
- running = false;
- reloadThread.interrupt();
- reloadThread.join();
- reloadThread = null;
- }
- }
-
- /**
- * A thread which reloads the config file.
- */
- private class UpdateThread extends Thread {
- private UpdateThread() {
- super("Raid update thread");
- }
-
- public void run() {
- while (running) {
- try {
- Thread.sleep(reloadInterval);
- reloadConfigsIfNecessary();
- } catch (InterruptedException e) {
- // do nothing
- } catch (Exception e) {
- LOG.error("Failed to reload config file ", e);
- }
- }
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/Decoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/Decoder.java
deleted file mode 100644
index 65060085c6f..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/Decoder.java
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Random;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hdfs.BlockMissingException;
-import org.apache.hadoop.fs.ChecksumException;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.Path;
-
-/**
- * Represents a generic decoder that can be used to read a file with
- * corrupt blocks by using the parity file.
- * This is an abstract class, concrete subclasses need to implement
- * fixErasedBlock.
- */
-public abstract class Decoder {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.Decoder");
- protected Configuration conf;
- protected int stripeSize;
- protected int paritySize;
- protected Random rand;
- protected int bufSize;
- protected byte[][] readBufs;
- protected byte[][] writeBufs;
-
- Decoder(Configuration conf, int stripeSize, int paritySize) {
- this.conf = conf;
- this.stripeSize = stripeSize;
- this.paritySize = paritySize;
- this.rand = new Random();
- this.bufSize = conf.getInt("raid.decoder.bufsize", 1024 * 1024);
- this.readBufs = new byte[stripeSize + paritySize][];
- this.writeBufs = new byte[paritySize][];
- allocateBuffers();
- }
-
- private void allocateBuffers() {
- for (int i = 0; i < stripeSize + paritySize; i++) {
- readBufs[i] = new byte[bufSize];
- }
- for (int i = 0; i < paritySize; i++) {
- writeBufs[i] = new byte[bufSize];
- }
- }
-
- private void configureBuffers(long blockSize) {
- if ((long)bufSize > blockSize) {
- bufSize = (int)blockSize;
- allocateBuffers();
- } else if (blockSize % bufSize != 0) {
- bufSize = (int)(blockSize / 256L); // heuristic.
- if (bufSize == 0) {
- bufSize = 1024;
- }
- bufSize = Math.min(bufSize, 1024 * 1024);
- allocateBuffers();
- }
- }
-
- /**
- * The interface to generate a decoded file using the good portion of the
- * source file and the parity file.
- * @param fs The filesystem containing the source file.
- * @param srcFile The damaged source file.
- * @param parityFs The filesystem containing the parity file. This could be
- * different from fs in case the parity file is part of a HAR archive.
- * @param parityFile The parity file.
- * @param errorOffset Known location of error in the source file. There could
- * be additional errors in the source file that are discovered during
- * the decode process.
- * @param decodedFile The decoded file. This will have the exact same contents
- * as the source file on success.
- */
- public void decodeFile(
- FileSystem fs, Path srcFile, FileSystem parityFs, Path parityFile,
- long errorOffset, Path decodedFile) throws IOException {
-
- LOG.info("Create " + decodedFile + " for error at " +
- srcFile + ":" + errorOffset);
- FileStatus srcStat = fs.getFileStatus(srcFile);
- long blockSize = srcStat.getBlockSize();
- configureBuffers(blockSize);
- // Move the offset to the start of the block.
- errorOffset = (errorOffset / blockSize) * blockSize;
-
- // Create the decoded file.
- FSDataOutputStream out = fs.create(
- decodedFile, false, conf.getInt("io.file.buffer.size", 64 * 1024),
- srcStat.getReplication(), srcStat.getBlockSize());
-
- // Open the source file.
- FSDataInputStream in = fs.open(
- srcFile, conf.getInt("io.file.buffer.size", 64 * 1024));
-
- // Start copying data block-by-block.
- for (long offset = 0; offset < srcStat.getLen(); offset += blockSize) {
- long limit = Math.min(blockSize, srcStat.getLen() - offset);
- long bytesAlreadyCopied = 0;
- if (offset != errorOffset) {
- try {
- in = fs.open(
- srcFile, conf.getInt("io.file.buffer.size", 64 * 1024));
- in.seek(offset);
- RaidUtils.copyBytes(in, out, readBufs[0], limit);
- assert(out.getPos() == offset +limit);
- LOG.info("Copied till " + out.getPos() + " from " + srcFile);
- continue;
- } catch (BlockMissingException e) {
- LOG.warn("Encountered BME at " + srcFile + ":" + offset);
- bytesAlreadyCopied = out.getPos() - offset;
- } catch (ChecksumException e) {
- LOG.warn("Encountered CE at " + srcFile + ":" + offset);
- bytesAlreadyCopied = out.getPos() - offset;
- }
- }
- // If we are here offset == errorOffset or we got an exception.
- // Recover the block starting at offset.
- fixErasedBlock(fs, srcFile, parityFs, parityFile, blockSize, offset,
- bytesAlreadyCopied, limit, out);
- }
- out.close();
-
- try {
- fs.setOwner(decodedFile, srcStat.getOwner(), srcStat.getGroup());
- fs.setPermission(decodedFile, srcStat.getPermission());
- fs.setTimes(decodedFile, srcStat.getModificationTime(),
- srcStat.getAccessTime());
- } catch (Exception exc) {
- LOG.warn("Didn't manage to copy meta information because of " + exc +
- " Ignoring...");
- }
-
- }
-
- /**
- * Recovers a corrupt block to local file.
- *
- * @param srcFs The filesystem containing the source file.
- * @param srcPath The damaged source file.
- * @param parityFs The filesystem containing the parity file. This could be
- * different from fs in case the parity file is part of a HAR archive.
- * @param parityPath The parity file.
- * @param blockSize The block size of the file.
- * @param blockOffset Known location of error in the source file. There could
- * be additional errors in the source file that are discovered during
- * the decode process.
- * @param localBlockFile The file to write the block to.
- * @param limit The maximum number of bytes to be written out.
- * This is to prevent writing beyond the end of the file.
- */
- public void recoverBlockToFile(
- FileSystem srcFs, Path srcPath, FileSystem parityFs, Path parityPath,
- long blockSize, long blockOffset, File localBlockFile, long limit)
- throws IOException {
- OutputStream out = new FileOutputStream(localBlockFile);
- fixErasedBlock(srcFs, srcPath, parityFs, parityPath,
- blockSize, blockOffset, 0, limit, out);
- out.close();
- }
-
- /**
- * Implementation-specific mechanism of writing a fixed block.
- * @param fs The filesystem containing the source file.
- * @param srcFile The damaged source file.
- * @param parityFs The filesystem containing the parity file. This could be
- * different from fs in case the parity file is part of a HAR archive.
- * @param parityFile The parity file.
- * @param blockSize The maximum size of a block.
- * @param errorOffset Known location of error in the source file. There could
- * be additional errors in the source file that are discovered during
- * the decode process.
- * @param bytesToSkip After the block is generated, these many bytes should be
- * skipped before writing to the output. This is needed because the
- * output may have a portion of the block written from the source file
- * before a new corruption is discovered in the block.
- * @param limit The maximum number of bytes to be written out, including
- * bytesToSkip. This is to prevent writing beyond the end of the file.
- * @param out The output.
- */
- protected abstract void fixErasedBlock(
- FileSystem fs, Path srcFile, FileSystem parityFs, Path parityFile,
- long blockSize, long errorOffset, long bytesToSkip, long limit,
- OutputStream out) throws IOException;
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DirectoryTraversal.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DirectoryTraversal.java
deleted file mode 100644
index c1ff9bccc4f..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DirectoryTraversal.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Stack;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.Semaphore;
-
-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.util.StringUtils;
-
-/**
- * Implements depth-first traversal using a Stack object. The traversal
- * can be stopped at any time and the state of traversal is saved.
- */
-public class DirectoryTraversal {
- public static final Log LOG =
- LogFactory.getLog("org.apache.hadoop.raid.DirectoryTraversal");
-
- private FileSystem fs;
- private List paths;
- private int pathIdx = 0; // Next path to process.
- private Stack stack = new Stack();
- private ExecutorService executor;
-
- private int numThreads;
-
- /**
- * A FileFilter object can be used to choose files during directory traversal.
- */
- public interface FileFilter {
- /**
- * @return a boolean value indicating if the file passes the filter.
- */
- boolean check(FileStatus f) throws IOException;
- }
-
- /**
- * Represents a directory node in directory traversal.
- */
- static class Node {
- private FileStatus path; // Path that this node represents.
- private FileStatus[] elements; // Elements in the node.
- private int idx = 0;
-
- public Node(FileStatus path, FileStatus[] elements) {
- this.path = path;
- this.elements = elements;
- }
-
- public boolean hasNext() {
- return idx < elements.length;
- }
-
- public FileStatus next() {
- return elements[idx++];
- }
-
- public FileStatus path() {
- return this.path;
- }
- }
-
- /**
- * Constructor.
- * @param fs The filesystem to use.
- * @param startPaths A list of paths that need to be traversed
- */
- public DirectoryTraversal(FileSystem fs, List startPaths) {
- this(fs, startPaths, 1);
- }
-
- public DirectoryTraversal(
- FileSystem fs, List startPaths, int numThreads) {
- this.fs = fs;
- paths = startPaths;
- pathIdx = 0;
- this.numThreads = numThreads;
- executor = Executors.newFixedThreadPool(numThreads);
- }
-
- public List getFilteredFiles(FileFilter filter, int limit) {
- List filtered = new ArrayList();
- if (limit == 0)
- return filtered;
-
- // We need this semaphore to block when the number of running workitems
- // is equal to the number of threads. FixedThreadPool limits the number
- // of threads, but not the queue size. This way we will limit the memory
- // usage.
- Semaphore slots = new Semaphore(numThreads);
-
- while (true) {
- FilterFileWorkItem work = null;
- try {
- slots.acquire();
- synchronized(filtered) {
- if (filtered.size() >= limit) {
- slots.release();
- break;
- }
- }
- Node next = getNextDirectoryNode();
- if (next == null) {
- slots.release();
- break;
- }
- work = new FilterFileWorkItem(filter, next, filtered, slots);
- } catch (InterruptedException ie) {
- slots.release();
- break;
- } catch (IOException e) {
- slots.release();
- break;
- }
- executor.execute(work);
- }
-
- try {
- // Wait for all submitted items to finish.
- slots.acquire(numThreads);
- // If this traversal is finished, shutdown the executor.
- if (doneTraversal()) {
- executor.shutdown();
- executor.awaitTermination(1, TimeUnit.HOURS);
- }
- } catch (InterruptedException ie) {
- }
-
- return filtered;
- }
-
- class FilterFileWorkItem implements Runnable {
- FileFilter filter;
- Node dir;
- List filtered;
- Semaphore slots;
-
- FilterFileWorkItem(FileFilter filter, Node dir, List filtered,
- Semaphore slots) {
- this.slots = slots;
- this.filter = filter;
- this.dir = dir;
- this.filtered = filtered;
- }
-
- @SuppressWarnings("deprecation")
- public void run() {
- try {
- LOG.info("Initiating file filtering for " + dir.path.getPath());
- for (FileStatus f: dir.elements) {
- if (!f.isFile()) {
- continue;
- }
- if (filter.check(f)) {
- synchronized(filtered) {
- filtered.add(f);
- }
- }
- }
- } catch (Exception e) {
- LOG.error("Error in directory traversal: "
- + StringUtils.stringifyException(e));
- } finally {
- slots.release();
- }
- }
- }
-
- /**
- * Return the next file.
- * @throws IOException
- */
- public FileStatus getNextFile() throws IOException {
- // Check if traversal is done.
- while (!doneTraversal()) {
- // If traversal is not done, check if the stack is not empty.
- while (!stack.isEmpty()) {
- // If the stack is not empty, look at the top node.
- Node node = stack.peek();
- // Check if the top node has an element.
- if (node.hasNext()) {
- FileStatus element = node.next();
- // Is the next element a directory.
- if (!element.isDir()) {
- // It is a file, return it.
- return element;
- }
- // Next element is a directory, push it on to the stack and
- // continue
- try {
- pushNewNode(element);
- } catch (FileNotFoundException e) {
- // Ignore and move to the next element.
- }
- continue;
- } else {
- // Top node has no next element, pop it and continue.
- stack.pop();
- continue;
- }
- }
- // If the stack is empty, do we have more paths?
- while (!paths.isEmpty()) {
- FileStatus next = paths.remove(0);
- pathIdx++;
- if (!next.isDir()) {
- return next;
- }
- try {
- pushNewNode(next);
- } catch (FileNotFoundException e) {
- continue;
- }
- break;
- }
- }
- return null;
- }
-
- /**
- * Gets the next directory in the tree. The algorithm returns deeper directories
- * first.
- * @return A FileStatus representing the directory.
- * @throws IOException
- */
- public FileStatus getNextDirectory() throws IOException {
- Node dirNode = getNextDirectoryNode();
- if (dirNode != null) {
- return dirNode.path;
- }
- return null;
- }
-
- private Node getNextDirectoryNode() throws IOException {
-
- // Check if traversal is done.
- while (!doneTraversal()) {
- // If traversal is not done, check if the stack is not empty.
- while (!stack.isEmpty()) {
- // If the stack is not empty, look at the top node.
- Node node = stack.peek();
- // Check if the top node has an element.
- if (node.hasNext()) {
- FileStatus element = node.next();
- // Is the next element a directory.
- if (element.isDir()) {
- // Next element is a directory, push it on to the stack and
- // continue
- try {
- pushNewNode(element);
- } catch (FileNotFoundException e) {
- // Ignore and move to the next element.
- }
- continue;
- }
- } else {
- stack.pop();
- return node;
- }
- }
- // If the stack is empty, do we have more paths?
- while (!paths.isEmpty()) {
- FileStatus next = paths.remove(0);
- pathIdx++;
- if (next.isDir()) {
- try {
- pushNewNode(next);
- } catch (FileNotFoundException e) {
- continue;
- }
- break;
- }
- }
- }
- return null;
- }
-
- private void pushNewNode(FileStatus stat) throws IOException {
- if (!stat.isDir()) {
- return;
- }
- Path p = stat.getPath();
- FileStatus[] elements = fs.listStatus(p);
- Node newNode = new Node(stat, (elements == null? new FileStatus[0]: elements));
- stack.push(newNode);
- }
-
- public boolean doneTraversal() {
- return paths.isEmpty() && stack.isEmpty();
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistBlockFixer.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistBlockFixer.java
deleted file mode 100644
index 9779e31924e..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistBlockFixer.java
+++ /dev/null
@@ -1,660 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.InputStreamReader;
-import java.io.BufferedReader;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Date;
-import java.text.SimpleDateFormat;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.Path;
-
-import org.apache.hadoop.hdfs.DistributedFileSystem;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-
-import org.apache.hadoop.conf.Configuration;
-
-import org.apache.hadoop.io.SequenceFile;
-import org.apache.hadoop.io.Text;
-import org.apache.hadoop.io.WritableComparable;
-import org.apache.hadoop.io.LongWritable;
-import org.apache.hadoop.io.Writable;
-
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-
-import org.apache.hadoop.mapreduce.Mapper;
-import org.apache.hadoop.mapreduce.InputFormat;
-import org.apache.hadoop.mapreduce.Job;
-import org.apache.hadoop.mapreduce.JobContext;
-import org.apache.hadoop.mapreduce.InputSplit;
-
-import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
-import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
-import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat;
-import org.apache.hadoop.mapreduce.lib.input.FileSplit;
-import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
-import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
-
-/**
- * distributed block fixer, uses map reduce jobs to fix corrupt files
- *
- * configuration options
- * raid.blockfix.filespertask - number of corrupt files to fix in a single
- * map reduce task (i.e., at one mapper node)
- *
- * raid.blockfix.maxpendingfiles - maximum number of files to fix
- * simultaneously
- */
-public class DistBlockFixer extends BlockFixer {
- // volatile should be sufficient since only the block fixer thread
- // updates numJobsRunning (other threads may read)
- private volatile int numJobsRunning = 0;
-
- private static final String WORK_DIR_PREFIX = "blockfixer";
- private static final String IN_FILE_SUFFIX = ".in";
- private static final String PART_PREFIX = "part-";
-
- private static final String BLOCKFIX_FILES_PER_TASK =
- "raid.blockfix.filespertask";
- private static final String BLOCKFIX_MAX_PENDING_FILES =
- "raid.blockfix.maxpendingfiles";
-
- // default number of files to fix in a task
- private static final long DEFAULT_BLOCKFIX_FILES_PER_TASK = 10L;
-
- // default number of files to fix simultaneously
- private static final long DEFAULT_BLOCKFIX_MAX_PENDING_FILES = 1000L;
-
- protected static final Log LOG = LogFactory.getLog(DistBlockFixer.class);
-
- // number of files to fix in a task
- private long filesPerTask;
-
- // number of files to fix simultaneously
- final private long maxPendingFiles;
-
- // number of files being fixed right now
- private long pendingFiles;
-
- private long lastCheckTime;
-
- private final SimpleDateFormat dateFormat =
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
- private Map fileIndex =
- new HashMap();
- private Map> jobIndex =
- new HashMap>();
-
- static enum Counter {
- FILES_SUCCEEDED, FILES_FAILED, FILES_NOACTION
- }
-
- public DistBlockFixer(Configuration conf) {
- super(conf);
- filesPerTask = DistBlockFixer.filesPerTask(getConf());
- maxPendingFiles = DistBlockFixer.maxPendingFiles(getConf());
- pendingFiles = 0L;
-
- // start off due for the first iteration
- lastCheckTime = Time.now() - blockFixInterval;
- }
-
- /**
- * determines how many files to fix in a single task
- */
- protected static long filesPerTask(Configuration conf) {
- return conf.getLong(BLOCKFIX_FILES_PER_TASK,
- DEFAULT_BLOCKFIX_FILES_PER_TASK);
-
- }
- /**
- * determines how many files to fix simultaneously
- */
- protected static long maxPendingFiles(Configuration conf) {
- return conf.getLong(BLOCKFIX_MAX_PENDING_FILES,
- DEFAULT_BLOCKFIX_MAX_PENDING_FILES);
- }
-
- /**
- * runs the block fixer periodically
- */
- public void run() {
- while (running) {
- // check if it is time to run the block fixer
- long now = Time.now();
- if (now >= lastCheckTime + blockFixInterval) {
- lastCheckTime = now;
- try {
- checkAndFixBlocks(now);
- } catch (InterruptedException ignore) {
- LOG.info("interrupted");
- } catch (Exception e) {
- // log exceptions and keep running
- LOG.error(StringUtils.stringifyException(e));
- } catch (Error e) {
- LOG.error(StringUtils.stringifyException(e));
- throw e;
- }
- }
-
- // try to sleep for the remainder of the interval
- long sleepPeriod = (lastCheckTime - Time.now()) +
- blockFixInterval;
-
- if ((sleepPeriod > 0L) && running) {
- try {
- Thread.sleep(sleepPeriod);
- } catch (InterruptedException ignore) {
- LOG.info("interrupted");
- }
- }
- }
- }
-
- /**
- * checks for corrupt blocks and fixes them (if any)
- */
- private void checkAndFixBlocks(long startTime)
- throws IOException, InterruptedException, ClassNotFoundException {
- checkJobs();
-
- if (pendingFiles >= maxPendingFiles) {
- return;
- }
-
- List corruptFiles = getCorruptFiles();
- filterUnfixableSourceFiles(corruptFiles.iterator());
-
- String startTimeStr = dateFormat.format(new Date(startTime));
-
- LOG.info("found " + corruptFiles.size() + " corrupt files");
-
- if (corruptFiles.size() > 0) {
- String jobName = "blockfixer." + startTime;
- startJob(jobName, corruptFiles);
- }
- }
-
- /**
- * Handle a failed job.
- */
- private void failJob(Job job) throws IOException {
- // assume no files have been fixed
- LOG.error("DistBlockFixer job " + job.getJobID() + "(" + job.getJobName() +
- ") finished (failed)");
- for (CorruptFileInfo fileInfo: jobIndex.get(job)) {
- fileInfo.fail();
- }
- numJobsRunning--;
- }
-
- /**
- * Handle a successful job.
- */
- private void succeedJob(Job job, long filesSucceeded, long filesFailed)
- throws IOException {
- LOG.info("DistBlockFixer job " + job.getJobID() + "(" + job.getJobName() +
- ") finished (succeeded)");
-
- if (filesFailed == 0) {
- // no files have failed
- for (CorruptFileInfo fileInfo: jobIndex.get(job)) {
- fileInfo.succeed();
- }
- } else {
- // we have to look at the output to check which files have failed
- Set failedFiles = getFailedFiles(job);
-
- for (CorruptFileInfo fileInfo: jobIndex.get(job)) {
- if (failedFiles.contains(fileInfo.getFile().toString())) {
- fileInfo.fail();
- } else {
- // call succeed for files that have succeeded or for which no action
- // was taken
- fileInfo.succeed();
- }
- }
- }
- // report succeeded files to metrics
- incrFilesFixed(filesSucceeded);
- numJobsRunning--;
- }
-
- /**
- * checks if jobs have completed and updates job and file index
- * returns a list of failed files for restarting
- */
- private void checkJobs() throws IOException {
- Iterator jobIter = jobIndex.keySet().iterator();
- while(jobIter.hasNext()) {
- Job job = jobIter.next();
-
- try {
- if (job.isComplete()) {
- long filesSucceeded =
- job.getCounters().findCounter(Counter.FILES_SUCCEEDED).getValue();
- long filesFailed =
- job.getCounters().findCounter(Counter.FILES_FAILED).getValue();
- long filesNoAction =
- job.getCounters().findCounter(Counter.FILES_NOACTION).getValue();
- int files = jobIndex.get(job).size();
- if (job.isSuccessful() &&
- (filesSucceeded + filesFailed + filesNoAction ==
- ((long) files))) {
- // job has processed all files
- succeedJob(job, filesSucceeded, filesFailed);
- } else {
- failJob(job);
- }
- jobIter.remove();
- } else {
- LOG.info("job " + job.getJobName() + " still running");
- }
- } catch (Exception e) {
- LOG.error(StringUtils.stringifyException(e));
- failJob(job);
- try {
- job.killJob();
- } catch (Exception ee) {
- LOG.error(StringUtils.stringifyException(ee));
- }
- jobIter.remove();
- }
- }
- purgeFileIndex();
- }
-
- /**
- * determines which files have failed for a given job
- */
- private Set getFailedFiles(Job job) throws IOException {
- Set failedFiles = new HashSet();
-
- Path outDir = SequenceFileOutputFormat.getOutputPath(job);
- FileSystem fs = outDir.getFileSystem(getConf());
- if (!fs.getFileStatus(outDir).isDir()) {
- throw new IOException(outDir.toString() + " is not a directory");
- }
-
- FileStatus[] files = fs.listStatus(outDir);
-
- for (FileStatus f: files) {
- Path fPath = f.getPath();
- if ((!f.isDir()) && (fPath.getName().startsWith(PART_PREFIX))) {
- LOG.info("opening " + fPath.toString());
- SequenceFile.Reader reader =
- new SequenceFile.Reader(fs, fPath, getConf());
-
- Text key = new Text();
- Text value = new Text();
- while (reader.next(key, value)) {
- failedFiles.add(key.toString());
- }
- reader.close();
- }
- }
- return failedFiles;
- }
-
-
- /**
- * purge expired jobs from the file index
- */
- private void purgeFileIndex() {
- Iterator fileIter = fileIndex.keySet().iterator();
- while(fileIter.hasNext()) {
- String file = fileIter.next();
- if (fileIndex.get(file).isExpired()) {
- fileIter.remove();
- }
- }
-
- }
-
- /**
- * creates and submits a job, updates file index and job index
- */
- private Job startJob(String jobName, List corruptFiles)
- throws IOException, InterruptedException, ClassNotFoundException {
- Path inDir = new Path(WORK_DIR_PREFIX + "/in/" + jobName);
- Path outDir = new Path(WORK_DIR_PREFIX + "/out/" + jobName);
- List filesInJob = createInputFile(jobName, inDir, corruptFiles);
-
- Configuration jobConf = new Configuration(getConf());
- Job job = new Job(jobConf, jobName);
- job.setJarByClass(getClass());
- job.setMapperClass(DistBlockFixerMapper.class);
- job.setNumReduceTasks(0);
- job.setInputFormatClass(DistBlockFixerInputFormat.class);
- job.setOutputFormatClass(SequenceFileOutputFormat.class);
- job.setOutputKeyClass(Text.class);
- job.setOutputValueClass(Text.class);
-
- DistBlockFixerInputFormat.setInputPaths(job, inDir);
- SequenceFileOutputFormat.setOutputPath(job, outDir);
-
- job.submit();
- LOG.info("DistBlockFixer job " + job.getJobID() + "(" + job.getJobName() +
- ") started");
-
- // submit the job before inserting it into the index
- // this way, if submit fails, we won't have added anything to the index
- insertJob(job, filesInJob);
- return job;
- }
-
- /**
- * inserts new job into file index and job index
- */
- private void insertJob(Job job, List corruptFiles) {
- List fileInfos = new LinkedList();
-
- for (Path file: corruptFiles) {
- CorruptFileInfo fileInfo = new CorruptFileInfo(file, job);
- fileInfos.add(fileInfo);
- fileIndex.put(file.toString(), fileInfo);
- }
-
- jobIndex.put(job, fileInfos);
- numJobsRunning++;
- }
-
- /**
- * creates the input file (containing the names of the files to be fixed
- */
- private List createInputFile(String jobName, Path inDir,
- List corruptFiles)
- throws IOException {
-
- Path file = new Path(inDir, jobName + IN_FILE_SUFFIX);
- FileSystem fs = file.getFileSystem(getConf());
- SequenceFile.Writer fileOut = SequenceFile.createWriter(fs, getConf(), file,
- LongWritable.class,
- Text.class);
- long index = 0L;
-
- List filesAdded = new LinkedList();
-
- for (Path corruptFile: corruptFiles) {
- if (pendingFiles >= maxPendingFiles) {
- break;
- }
-
- String corruptFileName = corruptFile.toString();
- fileOut.append(new LongWritable(index++), new Text(corruptFileName));
- filesAdded.add(corruptFile);
- pendingFiles++;
-
- if (index % filesPerTask == 0) {
- fileOut.sync(); // create sync point to make sure we can split here
- }
- }
-
- fileOut.close();
- return filesAdded;
- }
-
- /**
- * gets a list of corrupt files from the name node
- * and filters out files that are currently being fixed or
- * that were recently fixed
- */
- private List getCorruptFiles() throws IOException {
- DistributedFileSystem dfs = (DistributedFileSystem)
- (new Path("/")).getFileSystem(getConf());
-
- String[] files = RaidDFSUtil.getCorruptFiles(dfs);
- List corruptFiles = new LinkedList();
-
- for (String f: files) {
- Path p = new Path(f);
- // filter out files that are being fixed or that were recently fixed
- if (!fileIndex.containsKey(p.toString())) {
- corruptFiles.add(p);
- }
- }
- RaidUtils.filterTrash(getConf(), corruptFiles);
-
- return corruptFiles;
- }
-
- /**
- * returns the number of map reduce jobs running
- */
- public int jobsRunning() {
- return numJobsRunning;
- }
-
- /**
- * hold information about a corrupt file that is being fixed
- */
- class CorruptFileInfo {
-
- private Path file;
- private Job job;
- private boolean done;
- private long time;
-
- public CorruptFileInfo(Path file, Job job) {
- this.file = file;
- this.job = job;
- this.done = false;
- this.time = 0;
- }
-
- public boolean isDone() {
- return done;
- }
-
- public boolean isExpired() {
- return done && ((Time.now() - time) > historyInterval);
- }
-
- public Path getFile() {
- return file;
- }
-
- /**
- * updates file index to record a failed attempt at fixing a file,
- * immediately removes the entry from the file index
- * (instead of letting it expire)
- * so that we can retry right away
- */
- public void fail() {
- // remove this file from the index
- CorruptFileInfo removed = fileIndex.remove(file.toString());
- if (removed == null) {
- LOG.error("trying to remove file not in file index: " +
- file.toString());
- } else {
- LOG.error("fixing " + file.toString() + " failed");
- }
- pendingFiles--;
- }
-
- /**
- * marks a file as fixed successfully
- * and sets time stamp for expiry after specified interval
- */
- public void succeed() {
- // leave the file in the index,
- // will be pruged later
- job = null;
- done = true;
- time = Time.now();
- LOG.info("fixing " + file.toString() + " succeeded");
- pendingFiles--;
- }
- }
-
- static class DistBlockFixerInputFormat
- extends SequenceFileInputFormat {
-
- protected static final Log LOG =
- LogFactory.getLog(DistBlockFixerMapper.class);
-
- /**
- * splits the input files into tasks handled by a single node
- * we have to read the input files to do this based on a number of
- * items in a sequence
- */
- @Override
- public List getSplits(JobContext job)
- throws IOException {
- long filesPerTask = DistBlockFixer.filesPerTask(job.getConfiguration());
-
- Path[] inPaths = getInputPaths(job);
-
- List splits = new LinkedList();
-
- long fileCounter = 0;
-
- for (Path inPath: inPaths) {
-
- FileSystem fs = inPath.getFileSystem(job.getConfiguration());
-
- if (!fs.getFileStatus(inPath).isDir()) {
- throw new IOException(inPath.toString() + " is not a directory");
- }
-
- FileStatus[] inFiles = fs.listStatus(inPath);
-
- for (FileStatus inFileStatus: inFiles) {
- Path inFile = inFileStatus.getPath();
-
- if (!inFileStatus.isDir() &&
- (inFile.getName().equals(job.getJobName() + IN_FILE_SUFFIX))) {
-
- fileCounter++;
- SequenceFile.Reader inFileReader =
- new SequenceFile.Reader(fs, inFile, job.getConfiguration());
-
- long startPos = inFileReader.getPosition();
- long counter = 0;
-
- // create an input split every filesPerTask items in the sequence
- LongWritable key = new LongWritable();
- Text value = new Text();
- try {
- while (inFileReader.next(key, value)) {
- if (counter % filesPerTask == filesPerTask - 1L) {
- splits.add(new FileSplit(inFile, startPos,
- inFileReader.getPosition() -
- startPos,
- null));
- startPos = inFileReader.getPosition();
- }
- counter++;
- }
-
- // create input split for remaining items if necessary
- // this includes the case where no splits were created by the loop
- if (startPos != inFileReader.getPosition()) {
- splits.add(new FileSplit(inFile, startPos,
- inFileReader.getPosition() - startPos,
- null));
- }
- } finally {
- inFileReader.close();
- }
- }
- }
- }
-
- LOG.info("created " + splits.size() + " input splits from " +
- fileCounter + " files");
-
- return splits;
- }
-
- /**
- * indicates that input file can be split
- */
- @Override
- public boolean isSplitable (JobContext job, Path file) {
- return true;
- }
- }
-
-
- /**
- * mapper for fixing stripes with corrupt blocks
- */
- static class DistBlockFixerMapper
- extends Mapper {
-
- protected static final Log LOG =
- LogFactory.getLog(DistBlockFixerMapper.class);
-
- /**
- * fix a stripe
- */
- @Override
- public void map(LongWritable key, Text fileText, Context context)
- throws IOException, InterruptedException {
-
- BlockFixerHelper helper =
- new BlockFixerHelper(context.getConfiguration());
-
- String fileStr = fileText.toString();
- LOG.info("fixing " + fileStr);
-
- Path file = new Path(fileStr);
- boolean success = false;
-
- try {
- boolean fixed = helper.fixFile(file, context);
-
- if (fixed) {
- context.getCounter(Counter.FILES_SUCCEEDED).increment(1L);
- } else {
- context.getCounter(Counter.FILES_NOACTION).increment(1L);
- }
- } catch (Exception e) {
- LOG.error(StringUtils.stringifyException(e));
-
- // report file as failed
- context.getCounter(Counter.FILES_FAILED).increment(1L);
- String outkey = fileStr;
- String outval = "failed";
- context.write(new Text(outkey), new Text(outval));
- }
-
- context.progress();
- }
- }
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistRaid.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistRaid.java
deleted file mode 100644
index 5c6e5cc79dc..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistRaid.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-import java.util.Date;
-import java.text.SimpleDateFormat;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.conf.Configured;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.io.SequenceFile;
-import org.apache.hadoop.io.Text;
-import org.apache.hadoop.io.SequenceFile.Writer;
-import org.apache.hadoop.io.SequenceFile.Reader;
-
-import org.apache.hadoop.mapreduce.JobContext;
-import org.apache.hadoop.mapreduce.JobID;
-import org.apache.hadoop.mapreduce.Mapper;
-import org.apache.hadoop.mapreduce.Job;
-import org.apache.hadoop.mapreduce.InputSplit;
-import org.apache.hadoop.mapreduce.lib.input.SequenceFileInputFormat;
-import org.apache.hadoop.mapreduce.lib.input.FileSplit;
-import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
-import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
-import org.apache.hadoop.raid.RaidNode.Statistics;
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.util.StringUtils;
-
-public class DistRaid extends Configured {
-
- protected static final Log LOG = LogFactory.getLog(DistRaid.class);
-
- static final String NAME = "distRaid";
- static final String JOB_DIR_LABEL = NAME + ".job.dir";
- static final int OP_LIST_BLOCK_SIZE = 32 * 1024 * 1024; // block size of control file
- static final short OP_LIST_REPLICATION = 10; // replication factor of control file
-
- public static final String OPS_PER_TASK = "raid.distraid.opspertask";
- private static final int DEFAULT_OPS_PER_TASK = 100;
- private static final int SYNC_FILE_MAX = 10;
- private static final SimpleDateFormat dateForm = new SimpleDateFormat("yyyy-MM-dd HH:mm");
-
- static enum Counter {
- FILES_SUCCEEDED, FILES_FAILED, PROCESSED_BLOCKS, PROCESSED_SIZE, META_BLOCKS, META_SIZE
- }
-
- public DistRaid(Configuration conf) {
- super(conf);
- }
-
- private static final Random RANDOM = new Random();
-
- protected static String getRandomId() {
- return Integer.toString(RANDOM.nextInt(Integer.MAX_VALUE), 36);
- }
-
- /**
- *
- * helper class which holds the policy and paths
- *
- */
- public static class RaidPolicyPathPair {
- public PolicyInfo policy;
- public List srcPaths;
-
- RaidPolicyPathPair(PolicyInfo policy, List srcPaths) {
- this.policy = policy;
- this.srcPaths = srcPaths;
- }
- }
-
- List raidPolicyPathPairList = new ArrayList();
-
- private Job runningJob;
- private String lastReport = null;
-
- /** Responsible for generating splits of the src file list. */
- static class DistRaidInputFormat extends
- SequenceFileInputFormat {
- /**
- * Produce splits such that each is no greater than the quotient of the
- * total size and the number of splits requested.
- *
- * @param job
- * The handle to the Configuration object
- * @param numSplits
- * Number of splits requested
- */
- public List getSplits(JobContext job) throws IOException {
- Configuration conf = job.getConfiguration();
-
- // We create only one input file. So just get the first file in the first
- // input directory.
- Path inDir = getInputPaths(job)[0];
- FileSystem fs = inDir.getFileSystem(conf);
- FileStatus[] inputFiles = fs.listStatus(inDir);
- Path inputFile = inputFiles[0].getPath();
-
- List splits = new ArrayList();
- SequenceFile.Reader in =
- new SequenceFile.Reader(conf, Reader.file(inputFile));
- long prev = 0L;
- final int opsPerTask = conf.getInt(OPS_PER_TASK, DEFAULT_OPS_PER_TASK);
- try {
- Text key = new Text();
- PolicyInfo value = new PolicyInfo();
- int count = 0; // count src
- while (in.next(key, value)) {
- long curr = in.getPosition();
- long delta = curr - prev;
- if (++count > opsPerTask) {
- count = 0;
- splits.add(new FileSplit(inputFile, prev, delta, (String[]) null));
- prev = curr;
- }
- }
- } finally {
- in.close();
- }
- long remaining = fs.getFileStatus(inputFile).getLen() - prev;
- if (remaining != 0) {
- splits.add(new FileSplit(inputFile, prev, remaining, (String[]) null));
- }
- return splits;
- }
- }
-
- /** The mapper for raiding files. */
- static class DistRaidMapper extends Mapper {
- private boolean ignoreFailures = false;
-
- private int failcount = 0;
- private int succeedcount = 0;
- private Statistics st = new Statistics();
-
- private String getCountString() {
- return "Succeeded: " + succeedcount + " Failed: " + failcount;
- }
-
- /** Run a FileOperation
- * @throws IOException
- * @throws InterruptedException */
- public void map(Text key, PolicyInfo policy, Context context)
- throws IOException, InterruptedException {
- try {
- Configuration jobConf = context.getConfiguration();
- LOG.info("Raiding file=" + key.toString() + " policy=" + policy);
- Path p = new Path(key.toString());
- FileStatus fs = p.getFileSystem(jobConf).getFileStatus(p);
- st.clear();
- RaidNode.doRaid(jobConf, policy, fs, st, context);
-
- ++succeedcount;
-
- context.getCounter(Counter.PROCESSED_BLOCKS).increment(st.numProcessedBlocks);
- context.getCounter(Counter.PROCESSED_SIZE).increment(st.processedSize);
- context.getCounter(Counter.META_BLOCKS).increment(st.numMetaBlocks);
- context.getCounter(Counter.META_SIZE).increment(st.metaSize);
- context.getCounter(Counter.FILES_SUCCEEDED).increment(1);
- } catch (IOException e) {
- ++failcount;
- context.getCounter(Counter.FILES_FAILED).increment(1);
-
- String s = "FAIL: " + policy + ", " + key + " "
- + StringUtils.stringifyException(e);
- context.write(new Text(key), new Text(s));
- LOG.error(s);
- } finally {
- context.setStatus(getCountString());
- }
- }
-
- /** {@inheritDoc} */
- public void close() throws IOException {
- if (failcount == 0 || ignoreFailures) {
- return;
- }
- throw new IOException(getCountString());
- }
- }
-
- /**
- * Set options specified in raid.scheduleroption.
- * The string should be formatted as key:value[,key:value]*
- */
- static void setSchedulerOption(Configuration conf) {
- String schedulerOption = conf.get("raid.scheduleroption");
- if (schedulerOption != null) {
- // Parse the scheduler option to get key:value pairs.
- String[] keyValues = schedulerOption.trim().split(",");
- for (String keyValue: keyValues) {
- String[] fields = keyValue.trim().split(":");
- String key = fields[0].trim();
- String value = fields[1].trim();
- conf.set(key, value);
- }
- }
- }
-
- /**
- * Creates a new Job object.
- * @param conf
- * @return a Job object
- * @throws IOException
- */
- static Job createJob(Configuration jobConf) throws IOException {
- String jobName = NAME + " " + dateForm.format(new Date(RaidNode.now()));
-
- setSchedulerOption(jobConf);
-
- Job job = Job.getInstance(jobConf, jobName);
- job.setSpeculativeExecution(false);
- job.setJarByClass(DistRaid.class);
- job.setInputFormatClass(DistRaidInputFormat.class);
- job.setOutputKeyClass(Text.class);
- job.setOutputValueClass(Text.class);
-
- job.setMapperClass(DistRaidMapper.class);
- job.setNumReduceTasks(0);
-
- return job;
- }
-
- /** Add paths to be raided */
- public void addRaidPaths(PolicyInfo info, List paths) {
- raidPolicyPathPairList.add(new RaidPolicyPathPair(info, paths));
- }
-
- /** Invokes a map-reduce job do parallel raiding.
- * @return true if the job was started, false otherwise
- * @throws InterruptedException
- */
- public boolean startDistRaid() throws IOException {
- assert(raidPolicyPathPairList.size() > 0);
- Job job = createJob(getConf());
- createInputFile(job);
- try {
- job.submit();
- this.runningJob = job;
- LOG.info("Job Started: " + runningJob.getJobID());
- return true;
- } catch (ClassNotFoundException e) {
- throw new IOException(e);
- } catch (InterruptedException e) {
- return false;
- }
- }
-
- /** Checks if the map-reduce job has completed.
- *
- * @return true if the job completed, false otherwise.
- * @throws IOException
- */
- public boolean checkComplete() throws IOException {
- JobID jobID = runningJob.getJobID();
- LOG.info("Checking job " + jobID);
- try {
- if (runningJob.isComplete()) {
- // delete job directory
- Configuration jobConf = runningJob.getConfiguration();
- final String jobdir = jobConf.get(JOB_DIR_LABEL);
- if (jobdir != null) {
- final Path jobpath = new Path(jobdir);
- jobpath.getFileSystem(jobConf).delete(jobpath, true);
- }
- if (runningJob.isSuccessful()) {
- LOG.info("Job Complete(Succeeded): " + jobID);
- } else {
- LOG.error("Job Complete(Failed): " + jobID);
- }
- raidPolicyPathPairList.clear();
- return true;
- } else {
- String report = (" job " + jobID +
- " map " + StringUtils.formatPercent(runningJob.mapProgress(), 0)+
- " reduce " + StringUtils.formatPercent(runningJob.reduceProgress(), 0));
- if (!report.equals(lastReport)) {
- LOG.info(report);
- lastReport = report;
- }
- return false;
- }
- } catch (InterruptedException e) {
- return false;
- }
- }
-
- public boolean successful() throws IOException {
- try {
- return runningJob.isSuccessful();
- } catch (InterruptedException e) {
- return false;
- }
- }
-
- /**
- * set up input file which has the list of input files.
- *
- * @return boolean
- * @throws IOException
- */
- private void createInputFile(Job job) throws IOException {
- Configuration jobConf = job.getConfiguration();
- Path jobDir = new Path(JOB_DIR_LABEL + getRandomId());
- Path inDir = new Path(jobDir, "in");
- Path outDir = new Path(jobDir, "out");
- FileInputFormat.setInputPaths(job, inDir);
- FileOutputFormat.setOutputPath(job, outDir);
- Path opList = new Path(inDir, NAME);
-
- Configuration tmp = new Configuration(jobConf);
- // The control file should have small size blocks. This helps
- // in spreading out the load from mappers that will be spawned.
- tmp.setInt("dfs.blocks.size", OP_LIST_BLOCK_SIZE);
- FileSystem fs = opList.getFileSystem(tmp);
-
- int opCount = 0, synCount = 0;
- SequenceFile.Writer opWriter = null;
- try {
- opWriter = SequenceFile.createWriter(
- jobConf, Writer.file(opList), Writer.keyClass(Text.class),
- Writer.valueClass(PolicyInfo.class),
- Writer.compression(SequenceFile.CompressionType.NONE));
- for (RaidPolicyPathPair p : raidPolicyPathPairList) {
- // If a large set of files are Raided for the first time, files
- // in the same directory that tend to have the same size will end up
- // with the same map. This shuffle mixes things up, allowing a better
- // mix of files.
- java.util.Collections.shuffle(p.srcPaths);
- for (FileStatus st : p.srcPaths) {
- opWriter.append(new Text(st.getPath().toString()), p.policy);
- opCount++;
- if (++synCount > SYNC_FILE_MAX) {
- opWriter.sync();
- synCount = 0;
- }
- }
- }
-
- } finally {
- if (opWriter != null) {
- opWriter.close();
- }
- // increase replication for control file
- fs.setReplication(opList, OP_LIST_REPLICATION);
- }
- raidPolicyPathPairList.clear();
- LOG.info("Number of files=" + opCount);
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistRaidNode.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistRaidNode.java
deleted file mode 100644
index 43be2a725d6..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/DistRaidNode.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.apache.hadoop.conf.Configuration;
-
-import org.apache.hadoop.util.Daemon;
-
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.FileStatus;
-
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-
-/**
- * Implementation of {@link RaidNode} that uses map reduce jobs to raid files.
- */
-public class DistRaidNode extends RaidNode {
-
- public static final Log LOG = LogFactory.getLog(DistRaidNode.class);
-
- /** Daemon thread to monitor raid job progress */
- JobMonitor jobMonitor = null;
- Daemon jobMonitorThread = null;
-
- public DistRaidNode(Configuration conf) throws IOException {
- super(conf);
- this.jobMonitor = new JobMonitor(conf);
- this.jobMonitorThread = new Daemon(this.jobMonitor);
- this.jobMonitorThread.start();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void join() {
- super.join();
- try {
- if (jobMonitorThread != null) jobMonitorThread.join();
- } catch (InterruptedException ie) {
- // do nothing
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void stop() {
- if (stopRequested) {
- return;
- }
- super.stop();
- if (jobMonitor != null) jobMonitor.running = false;
- if (jobMonitorThread != null) jobMonitorThread.interrupt();
- }
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- void raidFiles(PolicyInfo info, List paths) throws IOException {
- // We already checked that no job for this policy is running
- // So we can start a new job.
- DistRaid dr = new DistRaid(conf);
- //add paths for distributed raiding
- dr.addRaidPaths(info, paths);
- boolean started = dr.startDistRaid();
- if (started) {
- jobMonitor.monitorJob(info.getName(), dr);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- int getRunningJobsForPolicy(String policyName) {
- return jobMonitor.runningJobsCount(policyName);
- }
-
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/Encoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/Encoder.java
deleted file mode 100644
index b87bad4f807..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/Encoder.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Random;
-
-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.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Progressable;
-
-/**
- * Represents a generic encoder that can generate a parity file for a source
- * file.
- * This is an abstract class, concrete subclasses need to implement
- * encodeFileImpl.
- */
-public abstract class Encoder {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.Encoder");
- protected Configuration conf;
- protected int stripeSize;
- protected int paritySize;
- protected Random rand;
- protected int bufSize;
- protected byte[][] readBufs;
- protected byte[][] writeBufs;
-
- /**
- * A class that acts as a sink for data, similar to /dev/null.
- */
- static class NullOutputStream extends OutputStream {
- public void write(byte[] b) throws IOException {}
- public void write(int b) throws IOException {}
- public void write(byte[] b, int off, int len) throws IOException {}
- }
-
- Encoder(
- Configuration conf, int stripeSize, int paritySize) {
- this.conf = conf;
- this.stripeSize = stripeSize;
- this.paritySize = paritySize;
- this.rand = new Random();
- this.bufSize = conf.getInt("raid.encoder.bufsize", 1024 * 1024);
- this.readBufs = new byte[stripeSize][];
- this.writeBufs = new byte[paritySize][];
- allocateBuffers();
- }
-
- private void allocateBuffers() {
- for (int i = 0; i < stripeSize; i++) {
- readBufs[i] = new byte[bufSize];
- }
- for (int i = 0; i < paritySize; i++) {
- writeBufs[i] = new byte[bufSize];
- }
- }
-
- private void configureBuffers(long blockSize) {
- if ((long)bufSize > blockSize) {
- bufSize = (int)blockSize;
- allocateBuffers();
- } else if (blockSize % bufSize != 0) {
- bufSize = (int)(blockSize / 256L); // heuristic.
- if (bufSize == 0) {
- bufSize = 1024;
- }
- bufSize = Math.min(bufSize, 1024 * 1024);
- allocateBuffers();
- }
- }
-
- /**
- * The interface to use to generate a parity file.
- * This method can be called multiple times with the same Encoder object,
- * thus allowing reuse of the buffers allocated by the Encoder object.
- *
- * @param fs The filesystem containing the source file.
- * @param srcFile The source file.
- * @param parityFile The parity file to be generated.
- */
- public void encodeFile(
- FileSystem fs, Path srcFile, FileSystem parityFs, Path parityFile,
- short parityRepl, Progressable reporter) throws IOException {
- FileStatus srcStat = fs.getFileStatus(srcFile);
- long srcSize = srcStat.getLen();
- long blockSize = srcStat.getBlockSize();
-
- configureBuffers(blockSize);
-
- // Create a tmp file to which we will write first.
- Path tmpDir = getParityTempPath();
- if (!parityFs.mkdirs(tmpDir)) {
- throw new IOException("Could not create tmp dir " + tmpDir);
- }
- Path parityTmp = new Path(tmpDir,
- parityFile.getName() + rand.nextLong());
- FSDataOutputStream out = parityFs.create(
- parityTmp,
- true,
- conf.getInt("io.file.buffer.size", 64 * 1024),
- parityRepl,
- blockSize);
-
- try {
- encodeFileToStream(fs, srcFile, srcSize, blockSize, out, reporter);
- out.close();
- out = null;
- LOG.info("Wrote temp parity file " + parityTmp);
-
- // delete destination if exists
- if (parityFs.exists(parityFile)){
- parityFs.delete(parityFile, false);
- }
- parityFs.mkdirs(parityFile.getParent());
- if (!parityFs.rename(parityTmp, parityFile)) {
- String msg = "Unable to rename file " + parityTmp + " to " + parityFile;
- throw new IOException (msg);
- }
- LOG.info("Wrote parity file " + parityFile);
- } finally {
- if (out != null) {
- out.close();
- }
- parityFs.delete(parityTmp, false);
- }
- }
-
- /**
- * Recovers a corrupt block in a parity file to a local file.
- *
- * The encoder generates paritySize parity blocks for a source file stripe.
- * Since we want only one of the parity blocks, this function creates
- * null outputs for the blocks to be discarded.
- *
- * @param fs The filesystem in which both srcFile and parityFile reside.
- * @param srcFile The source file.
- * @param srcSize The size of the source file.
- * @param blockSize The block size for the source/parity files.
- * @param corruptOffset The location of corruption in the parity file.
- * @param localBlockFile The destination for the reovered block.
- */
- public void recoverParityBlockToFile(
- FileSystem fs,
- Path srcFile, long srcSize, long blockSize,
- Path parityFile, long corruptOffset,
- File localBlockFile) throws IOException {
- OutputStream out = new FileOutputStream(localBlockFile);
- try {
- recoverParityBlockToStream(fs, srcFile, srcSize, blockSize, parityFile,
- corruptOffset, out);
- } finally {
- out.close();
- }
- }
-
- /**
- * Recovers a corrupt block in a parity file to a local file.
- *
- * The encoder generates paritySize parity blocks for a source file stripe.
- * Since we want only one of the parity blocks, this function creates
- * null outputs for the blocks to be discarded.
- *
- * @param fs The filesystem in which both srcFile and parityFile reside.
- * @param srcFile The source file.
- * @param srcSize The size of the source file.
- * @param blockSize The block size for the source/parity files.
- * @param corruptOffset The location of corruption in the parity file.
- * @param out The destination for the reovered block.
- */
- public void recoverParityBlockToStream(
- FileSystem fs,
- Path srcFile, long srcSize, long blockSize,
- Path parityFile, long corruptOffset,
- OutputStream out) throws IOException {
- LOG.info("Recovering parity block" + parityFile + ":" + corruptOffset);
- // Get the start offset of the corrupt block.
- corruptOffset = (corruptOffset / blockSize) * blockSize;
- // Output streams to each block in the parity file stripe.
- OutputStream[] outs = new OutputStream[paritySize];
- long indexOfCorruptBlockInParityStripe =
- (corruptOffset / blockSize) % paritySize;
- LOG.info("Index of corrupt block in parity stripe: " +
- indexOfCorruptBlockInParityStripe);
- // Create a real output stream for the block we want to recover,
- // and create null streams for the rest.
- for (int i = 0; i < paritySize; i++) {
- if (indexOfCorruptBlockInParityStripe == i) {
- outs[i] = out;
- } else {
- outs[i] = new NullOutputStream();
- }
- }
- // Get the stripe index and start offset of stripe.
- long stripeIdx = corruptOffset / (paritySize * blockSize);
- long stripeStart = stripeIdx * blockSize * stripeSize;
-
- // Get input streams to each block in the source file stripe.
- InputStream[] blocks = stripeInputs(fs, srcFile, stripeStart,
- srcSize, blockSize);
- LOG.info("Starting recovery by using source stripe " +
- srcFile + ":" + stripeStart);
- // Read the data from the blocks and write to the parity file.
- encodeStripe(blocks, stripeStart, blockSize, outs,
- new RaidUtils.DummyProgressable());
- }
-
- /**
- * Recovers a corrupt block in a parity file to an output stream.
- *
- * The encoder generates paritySize parity blocks for a source file stripe.
- * Since there is only one output provided, some blocks are written out to
- * files before being written out to the output.
- *
- * @param fs The filesystem in which both srcFile and parityFile reside.
- * @param srcFile The source file.
- * @param srcSize The size of the source file.
- * @param blockSize The block size for the source/parity files.
- * @param out The destination for the reovered block.
- */
- private void encodeFileToStream(FileSystem fs, Path srcFile, long srcSize,
- long blockSize, OutputStream out, Progressable reporter) throws IOException {
- OutputStream[] tmpOuts = new OutputStream[paritySize];
- // One parity block can be written directly to out, rest to local files.
- tmpOuts[0] = out;
- File[] tmpFiles = new File[paritySize - 1];
- for (int i = 0; i < paritySize - 1; i++) {
- tmpFiles[i] = File.createTempFile("parity", "_" + i);
- LOG.info("Created tmp file " + tmpFiles[i]);
- tmpFiles[i].deleteOnExit();
- }
- try {
- // Loop over stripes in the file.
- for (long stripeStart = 0; stripeStart < srcSize;
- stripeStart += blockSize * stripeSize) {
- reporter.progress();
- LOG.info("Starting encoding of stripe " + srcFile + ":" + stripeStart);
- // Create input streams for blocks in the stripe.
- InputStream[] blocks = stripeInputs(fs, srcFile, stripeStart,
- srcSize, blockSize);
- // Create output streams to the temp files.
- for (int i = 0; i < paritySize - 1; i++) {
- tmpOuts[i + 1] = new FileOutputStream(tmpFiles[i]);
- }
- // Call the implementation of encoding.
- encodeStripe(blocks, stripeStart, blockSize, tmpOuts, reporter);
- // Close output streams to the temp files and write the temp files
- // to the output provided.
- for (int i = 0; i < paritySize - 1; i++) {
- tmpOuts[i + 1].close();
- tmpOuts[i + 1] = null;
- InputStream in = new FileInputStream(tmpFiles[i]);
- RaidUtils.copyBytes(in, out, writeBufs[i], blockSize);
- reporter.progress();
- }
- }
- } finally {
- for (int i = 0; i < paritySize - 1; i++) {
- if (tmpOuts[i + 1] != null) {
- tmpOuts[i + 1].close();
- }
- tmpFiles[i].delete();
- LOG.info("Deleted tmp file " + tmpFiles[i]);
- }
- }
- }
-
- /**
- * Return input streams for each block in a source file's stripe.
- * @param fs The filesystem where the file resides.
- * @param srcFile The source file.
- * @param stripeStartOffset The start offset of the stripe.
- * @param srcSize The size of the source file.
- * @param blockSize The block size for the source file.
- */
- protected InputStream[] stripeInputs(
- FileSystem fs,
- Path srcFile,
- long stripeStartOffset,
- long srcSize,
- long blockSize
- ) throws IOException {
- InputStream[] blocks = new InputStream[stripeSize];
- for (int i = 0; i < stripeSize; i++) {
- long seekOffset = stripeStartOffset + i * blockSize;
- if (seekOffset < srcSize) {
- FSDataInputStream in = fs.open(
- srcFile, conf.getInt("io.file.buffer.size", 64 * 1024));
- in.seek(seekOffset);
- LOG.info("Opening stream at " + srcFile + ":" + seekOffset);
- blocks[i] = in;
- } else {
- LOG.info("Using zeros at offset " + seekOffset);
- // We have no src data at this offset.
- blocks[i] = new RaidUtils.ZeroInputStream(
- seekOffset + blockSize);
- }
- }
- return blocks;
- }
-
- /**
- * The implementation of generating parity data for a stripe.
- *
- * @param blocks The streams to blocks in the stripe.
- * @param stripeStartOffset The start offset of the stripe
- * @param blockSize The maximum size of a block.
- * @param outs output streams to the parity blocks.
- * @param reporter progress indicator.
- */
- protected abstract void encodeStripe(
- InputStream[] blocks,
- long stripeStartOffset,
- long blockSize,
- OutputStream[] outs,
- Progressable reporter) throws IOException;
-
- /**
- * Return the temp path for the parity file
- */
- protected abstract Path getParityTempPath();
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ErasureCode.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ErasureCode.java
deleted file mode 100644
index 0747394f440..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ErasureCode.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * 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.raid;
-
-public interface ErasureCode {
- /**
- * Encodes the given message.
- * @param message The data of the message. The data is present in the least
- * significant bits of each int. The number of data bits is
- * symbolSize(). The number of elements of message is
- * stripeSize().
- * @param parity (out) The information is present in the least
- * significant bits of each int. The number of parity bits is
- * symbolSize(). The number of elements in the code is
- * paritySize().
- */
- public void encode(int[] message, int[] parity);
-
- /**
- * Generates missing portions of data.
- * @param data The message and parity. The parity should be placed in the
- * first part of the array. In each integer, the relevant portion
- * is present in the least significant bits of each int.
- * The number of elements in data is stripeSize() + paritySize().
- * @param erasedLocations The indexes in data which are not available.
- * @param erasedValues (out)The decoded values corresponding to erasedLocations.
- */
- public void decode(int[] data, int[] erasedLocations, int[] erasedValues);
-
- /**
- * The number of elements in the message.
- */
- public int stripeSize();
-
- /**
- * The number of elements in the code.
- */
- public int paritySize();
-
- /**
- * Number of bits for each symbol.
- */
- public int symbolSize();
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/GaloisField.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/GaloisField.java
deleted file mode 100644
index a10f5d79eaf..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/GaloisField.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/**
- * 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.raid;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Implementation of Galois field arithmetics with 2^p elements.
- * The input must be unsigned integers.
- */
-public class GaloisField {
-
- private final int[] logTable;
- private final int[] powTable;
- private final int[][] mulTable;
- private final int[][] divTable;
- private final int fieldSize;
- private final int primitivePeriod;
- private final int primitivePolynomial;
-
- // Field size 256 is good for byte based system
- private static final int DEFAULT_FIELD_SIZE = 256;
- // primitive polynomial 1 + X^2 + X^3 + X^4 + X^8
- private static final int DEFAULT_PRIMITIVE_POLYNOMIAL = 285;
-
- static private final Map instances =
- new HashMap();
-
- /**
- * Get the object performs Galois field arithmetics
- * @param fieldSize size of the field
- * @param primitivePolynomial a primitive polynomial corresponds to the size
- */
- public static GaloisField getInstance(int fieldSize,
- int primitivePolynomial) {
- int key = ((fieldSize << 16) & 0xFFFF0000) + (primitivePolynomial & 0x0000FFFF);
- GaloisField gf;
- synchronized (instances) {
- gf = instances.get(key);
- if (gf == null) {
- gf = new GaloisField(fieldSize, primitivePolynomial);
- instances.put(key, gf);
- }
- }
- return gf;
- }
-
- /**
- * Get the object performs Galois field arithmetics with default setting
- */
- public static GaloisField getInstance() {
- return getInstance(DEFAULT_FIELD_SIZE, DEFAULT_PRIMITIVE_POLYNOMIAL);
- }
-
- private GaloisField(int fieldSize, int primitivePolynomial) {
- assert fieldSize > 0;
- assert primitivePolynomial > 0;
-
- this.fieldSize = fieldSize;
- this.primitivePeriod = fieldSize - 1;
- this.primitivePolynomial = primitivePolynomial;
- logTable = new int[fieldSize];
- powTable = new int[fieldSize];
- mulTable = new int[fieldSize][fieldSize];
- divTable = new int[fieldSize][fieldSize];
- int value = 1;
- for (int pow = 0; pow < fieldSize - 1; pow++) {
- powTable[pow] = value;
- logTable[value] = pow;
- value = value * 2;
- if (value >= fieldSize) {
- value = value ^ primitivePolynomial;
- }
- }
- // building multiplication table
- for (int i = 0; i < fieldSize; i++) {
- for (int j = 0; j < fieldSize; j++) {
- if (i == 0 || j == 0) {
- mulTable[i][j] = 0;
- continue;
- }
- int z = logTable[i] + logTable[j];
- z = z >= primitivePeriod ? z - primitivePeriod : z;
- z = powTable[z];
- mulTable[i][j] = z;
- }
- }
- // building division table
- for (int i = 0; i < fieldSize; i++) {
- for (int j = 1; j < fieldSize; j++) {
- if (i == 0) {
- divTable[i][j] = 0;
- continue;
- }
- int z = logTable[i] - logTable[j];
- z = z < 0 ? z + primitivePeriod : z;
- z = powTable[z];
- divTable[i][j] = z;
- }
- }
- }
-
- /**
- * Return number of elements in the field
- * @return number of elements in the field
- */
- public int getFieldSize() {
- return fieldSize;
- }
-
- /**
- * Return the primitive polynomial in GF(2)
- * @return primitive polynomial as a integer
- */
- public int getPrimitivePolynomial() {
- return primitivePolynomial;
- }
-
- /**
- * Compute the sum of two fields
- * @param x input field
- * @param y input field
- * @return result of addition
- */
- public int add(int x, int y) {
- assert(x >= 0 && x < getFieldSize() && y >= 0 && y < getFieldSize());
- return x ^ y;
- }
-
- /**
- * Compute the multiplication of two fields
- * @param x input field
- * @param y input field
- * @return result of multiplication
- */
- public int multiply(int x, int y) {
- assert(x >= 0 && x < getFieldSize() && y >= 0 && y < getFieldSize());
- return mulTable[x][y];
- }
-
- /**
- * Compute the division of two fields
- * @param x input field
- * @param y input field
- * @return x/y
- */
- public int divide(int x, int y) {
- assert(x >= 0 && x < getFieldSize() && y > 0 && y < getFieldSize());
- return divTable[x][y];
- }
-
- /**
- * Compute power n of a field
- * @param x input field
- * @param n power
- * @return x^n
- */
- public int power(int x, int n) {
- assert(x >= 0 && x < getFieldSize());
- if (n == 0) {
- return 1;
- }
- if (x == 0) {
- return 0;
- }
- x = logTable[x] * n;
- if (x < primitivePeriod) {
- return powTable[x];
- }
- x = x % primitivePeriod;
- return powTable[x];
- }
-
- /**
- * Given a Vandermonde matrix V[i][j]=x[j]^i and vector y, solve for z such
- * that Vz=y. The output z will be placed in y.
- * @param x the vector which describe the Vandermonde matrix
- * @param y right-hand side of the Vandermonde system equation.
- * will be replaced the output in this vector
- */
- public void solveVandermondeSystem(int[] x, int[] y) {
- solveVandermondeSystem(x, y, x.length);
- }
-
- /**
- * Given a Vandermonde matrix V[i][j]=x[j]^i and vector y, solve for z such
- * that Vz=y. The output z will be placed in y.
- * @param x the vector which describe the Vandermonde matrix
- * @param y right-hand side of the Vandermonde system equation.
- * will be replaced the output in this vector
- * @param len consider x and y only from 0...len-1
- */
- public void solveVandermondeSystem(int[] x, int[] y, int len) {
- assert(y.length <= len);
- for (int i = 0; i < len - 1; i++) {
- for (int j = len - 1; j > i; j--) {
- y[j] = y[j] ^ mulTable[x[i]][y[j - 1]];
- }
- }
- for (int i = len - 1; i >= 0; i--) {
- for (int j = i + 1; j < len; j++) {
- y[j] = divTable[y[j]][x[j] ^ x[j - i - 1]];
- }
- for (int j = i; j < len - 1; j++) {
- y[j] = y[j] ^ y[j + 1];
- }
- }
- }
-
- /**
- * Compute the multiplication of two polynomials. The index in the
- * array corresponds to the power of the entry. For example p[0] is the
- * constant term of the polynomial p.
- * @param p input polynomial
- * @param q input polynomial
- * @return polynomial represents p*q
- */
- public int[] multiply(int[] p, int[] q) {
- int len = p.length + q.length - 1;
- int[] result = new int[len];
- for (int i = 0; i < len; i++) {
- result[i] = 0;
- }
- for (int i = 0; i < p.length; i++) {
- for (int j = 0; j < q.length; j++) {
- result[i + j] = add(result[i + j], multiply(p[i], q[j]));
- }
- }
- return result;
- }
-
- /**
- * Compute the remainder of a dividend and divisor pair. The index in the
- * array corresponds to the power of the entry. For example p[0] is the
- * constant term of the polynomial p.
- * @param dividend dividend polynomial, the remainder will be placed here when return
- * @param divisor divisor polynomial
- */
- public void remainder(int[] dividend, int[] divisor) {
- for (int i = dividend.length - divisor.length; i >= 0; i--) {
- int ratio =
- divTable[dividend[i + divisor.length - 1]][divisor[divisor.length - 1]];
- for (int j = 0; j < divisor.length; j++) {
- int k = j + i;
- dividend[k] = dividend[k] ^ mulTable[ratio][divisor[j]];
- }
- }
- }
-
- /**
- * Compute the sum of two polynomials. The index in the
- * array corresponds to the power of the entry. For example p[0] is the
- * constant term of the polynomial p.
- * @param p input polynomial
- * @param q input polynomial
- * @return polynomial represents p+q
- */
- public int[] add(int[] p, int[] q) {
- int len = Math.max(p.length, q.length);
- int[] result = new int[len];
- for (int i = 0; i < len; i++) {
- if (i < p.length && i < q.length) {
- result[i] = add(p[i], q[i]);
- } else if (i < p.length) {
- result[i] = p[i];
- } else {
- result[i] = q[i];
- }
- }
- return result;
- }
-
- /**
- * Substitute x into polynomial p(x).
- * @param p input polynomial
- * @param x input field
- * @return p(x)
- */
- public int substitute(int[] p, int x) {
- int result = 0;
- int y = 1;
- for (int i = 0; i < p.length; i++) {
- result = result ^ mulTable[p[i]][y];
- y = mulTable[x][y];
- }
- return result;
- }
-
- /**
- * Perform Gaussian elimination on the given matrix. This matrix has to be a
- * fat matrix (number of rows > number of columns).
- */
- public void gaussianElimination(int[][] matrix) {
- assert(matrix != null && matrix.length > 0 && matrix[0].length > 0
- && matrix.length < matrix[0].length);
- int height = matrix.length;
- int width = matrix[0].length;
- for (int i = 0; i < height; i++) {
- boolean pivotFound = false;
- // scan the column for a nonzero pivot and swap it to the diagonal
- for (int j = i; j < height; j++) {
- if (matrix[i][j] != 0) {
- int[] tmp = matrix[i];
- matrix[i] = matrix[j];
- matrix[j] = tmp;
- pivotFound = true;
- break;
- }
- }
- if (!pivotFound) {
- continue;
- }
- int pivot = matrix[i][i];
- for (int j = i; j < width; j++) {
- matrix[i][j] = divide(matrix[i][j], pivot);
- }
- for (int j = i + 1; j < height; j++) {
- int lead = matrix[j][i];
- for (int k = i; k < width; k++) {
- matrix[j][k] = add(matrix[j][k], multiply(lead, matrix[i][k]));
- }
- }
- }
- for (int i = height - 1; i >=0; i--) {
- for (int j = 0; j < i; j++) {
- int lead = matrix[j][i];
- for (int k = i; k < width; k++) {
- matrix[j][k] = add(matrix[j][k], multiply(lead, matrix[i][k]));
- }
- }
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/HarIndex.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/HarIndex.java
deleted file mode 100644
index 5cb73c91394..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/HarIndex.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
-import java.util.List;
-import java.util.LinkedList;
-
-import org.apache.hadoop.util.LineReader;
-import org.apache.hadoop.io.Text;
-
-/**
- * Represents the contents of a HAR Index file. The HAR is assumed to be
- * comprising of RAID parity files only and no directories.
- */
-public class HarIndex {
- public static final String indexFileName = "_index";
- private List entries = new LinkedList();
-
- /**
- * Represents information in a single line of the HAR index file.
- */
- public static class IndexEntry {
- String fileName; // Name of the file in the part file.
- long startOffset; // Start offset within the part file.
- long length; // Length of this file within the part file.
- long mtime; // Modification time of the file.
- String partFileName; // Name of the part file.
-
- IndexEntry(String fileName, long startOffset, long length,
- long mtime, String partFileName) {
- this.fileName = fileName;
- this.startOffset = startOffset;
- this.length = length;
- this.mtime = mtime;
- this.partFileName = partFileName;
- }
-
- public String toString() {
- return "fileName=" + fileName +
- ", startOffset=" + startOffset +
- ", length=" + length +
- ", mtime=" + mtime +
- ", partFileName=" + partFileName;
- }
- }
-
- /**
- * Constructor that reads the contents of the index file.
- * @param in An input stream to the index file.
- * @param max The size of the index file.
- * @throws IOException
- */
- public HarIndex(InputStream in, long max) throws IOException {
- LineReader lineReader = new LineReader(in);
- Text text = new Text();
- long nread = 0;
- while (nread < max) {
- int n = lineReader.readLine(text);
- nread += n;
- String line = text.toString();
- try {
- parseLine(line);
- } catch (UnsupportedEncodingException e) {
- throw new IOException("UnsupportedEncodingException after reading " +
- nread + "bytes");
- }
- }
- }
-
- /**
- * Parses each line and extracts relevant information.
- * @param line
- * @throws UnsupportedEncodingException
- */
- void parseLine(String line) throws UnsupportedEncodingException {
- String[] splits = line.split(" ");
-
- boolean isDir = "dir".equals(splits[1]) ? true: false;
- if (!isDir && splits.length >= 6) {
- String name = URLDecoder.decode(splits[0], "UTF-8");
- String partName = URLDecoder.decode(splits[2], "UTF-8");
- long startIndex = Long.parseLong(splits[3]);
- long length = Long.parseLong(splits[4]);
- String[] newsplits = URLDecoder.decode(splits[5],"UTF-8").split(" ");
- if (newsplits != null && newsplits.length >= 4) {
- long mtime = Long.parseLong(newsplits[0]);
- IndexEntry entry = new IndexEntry(
- name, startIndex, length, mtime, partName);
- entries.add(entry);
- }
- }
- }
-
- /**
- * Finds the index entry corresponding to a HAR partFile at an offset.
- * @param partName The name of the part file (part-*).
- * @param partFileOffset The offset into the part file.
- * @return The entry corresponding to partName:partFileOffset.
- */
- public IndexEntry findEntry(String partName, long partFileOffset) {
- for (IndexEntry e: entries) {
- boolean nameMatch = partName.equals(e.partFileName);
- boolean inRange = (partFileOffset >= e.startOffset) &&
- (partFileOffset < e.startOffset + e.length);
- if (nameMatch && inRange) {
- return e;
- }
- }
- return null;
- }
-
- /**
- * Finds the index entry corresponding to a file in the archive
- */
- public IndexEntry findEntryByFileName(String fileName) {
- for (IndexEntry e: entries) {
- if (fileName.equals(e.fileName)) {
- return e;
- }
- }
- return null;
- }
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/JobMonitor.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/JobMonitor.java
deleted file mode 100644
index cda295c65a9..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/JobMonitor.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.util.StringUtils;
-
-/**
- * Periodically monitors the status of jobs registered with it.
- *
- * Jobs that are submitted for the same policy name are kept in the same list,
- * and the list itself is kept in a map that has the policy name as the key and
- * the list as value.
- */
-class JobMonitor implements Runnable {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.JobMonitor");
-
- volatile boolean running = true;
-
- private Map> jobs;
- public static final String JOBMONITOR_INTERVAL_KEY = "raid.jobmonitor.interval";
- private long jobMonitorInterval;
- private volatile long jobsMonitored = 0;
- private volatile long jobsSucceeded = 0;
-
- public JobMonitor(Configuration conf) {
- jobMonitorInterval = conf.getLong(JOBMONITOR_INTERVAL_KEY, 60000);
- jobs = new java.util.HashMap>();
- }
-
- public void run() {
- while (running) {
- try {
- LOG.info("JobMonitor thread continuing to run...");
- doMonitor();
- } catch (Throwable e) {
- LOG.error("JobMonitor encountered exception " +
- StringUtils.stringifyException(e));
- // All expected exceptions are caught by doMonitor(). It is better
- // to exit now, this will prevent RaidNode from submitting more jobs
- // since the number of running jobs will never decrease.
- return;
- }
- }
- }
-
- /**
- * Periodically checks status of running map-reduce jobs.
- */
- public void doMonitor() {
- while (running) {
- String[] keys = null;
- // Make a copy of the names of the current jobs.
- synchronized(jobs) {
- keys = jobs.keySet().toArray(new String[0]);
- }
-
- // Check all the jobs. We do not want to block access to `jobs`
- // because that will prevent new jobs from being added.
- // This is safe because JobMonitor.run is the only code that can
- // remove a job from `jobs`. Thus all elements in `keys` will have
- // valid values.
- Map> finishedJobs =
- new HashMap>();
-
- for (String key: keys) {
- // For each policy being monitored, get the list of jobs running.
- DistRaid[] jobListCopy = null;
- synchronized(jobs) {
- List jobList = jobs.get(key);
- synchronized(jobList) {
- jobListCopy = jobList.toArray(new DistRaid[jobList.size()]);
- }
- }
- // The code that actually contacts the JobTracker is not synchronized,
- // it uses copies of the list of jobs.
- for (DistRaid job: jobListCopy) {
- // Check each running job.
- try {
- boolean complete = job.checkComplete();
- if (complete) {
- addJob(finishedJobs, key, job);
- if (job.successful()) {
- jobsSucceeded++;
- }
- }
- } catch (IOException ioe) {
- // If there was an error, consider the job finished.
- addJob(finishedJobs, key, job);
- LOG.error("JobMonitor exception", ioe);
- }
- }
- }
-
- if (finishedJobs.size() > 0) {
- for (String key: finishedJobs.keySet()) {
- List finishedJobList = finishedJobs.get(key);
- // Iterate through finished jobs and remove from jobs.
- // removeJob takes care of locking.
- for (DistRaid job: finishedJobList) {
- removeJob(jobs, key, job);
- }
- }
- }
-
- try {
- Thread.sleep(jobMonitorInterval);
- } catch (InterruptedException ie) {
- }
- }
- }
-
- public int runningJobsCount(String key) {
- int count = 0;
- synchronized(jobs) {
- if (jobs.containsKey(key)) {
- List jobList = jobs.get(key);
- synchronized(jobList) {
- count = jobList.size();
- }
- }
- }
- return count;
- }
-
- public void monitorJob(String key, DistRaid job) {
- addJob(jobs, key, job);
- jobsMonitored++;
- }
-
- public long jobsMonitored() {
- return this.jobsMonitored;
- }
-
- public long jobsSucceeded() {
- return this.jobsSucceeded;
- }
-
- // For test code
- int runningJobsCount() {
- int total = 0;
- synchronized(jobs) {
- for (String key: jobs.keySet()) {
- total += jobs.get(key).size();
- }
- }
- return total;
- }
-
- private static void addJob(Map> jobsMap,
- String jobName, DistRaid job) {
- synchronized(jobsMap) {
- List list = null;
- if (jobsMap.containsKey(jobName)) {
- list = jobsMap.get(jobName);
- } else {
- list = new LinkedList();
- jobsMap.put(jobName, list);
- }
- synchronized(list) {
- list.add(job);
- }
- }
- }
-
- private static void removeJob(Map> jobsMap,
- String jobName, DistRaid job) {
- synchronized(jobsMap) {
- if (jobsMap.containsKey(jobName)) {
- List list = jobsMap.get(jobName);
- synchronized(list) {
- for (Iterator it = list.iterator(); it.hasNext(); ) {
- DistRaid val = it.next();
- if (val == job) {
- it.remove();
- }
- }
- if (list.size() == 0) {
- jobsMap.remove(jobName);
- }
- }
- }
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/LocalBlockFixer.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/LocalBlockFixer.java
deleted file mode 100644
index 0bf4ab00cd1..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/LocalBlockFixer.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-
-import org.apache.hadoop.net.NetUtils;
-
-import org.apache.hadoop.hdfs.DistributedFileSystem;
-
-import org.apache.hadoop.raid.RaidNode;
-import org.apache.hadoop.raid.RaidUtils;
-import org.apache.hadoop.raid.protocol.PolicyInfo.ErasureCodeType;
-
-/**
- * This class fixes source file blocks using the parity file,
- * and parity file blocks using the source file.
- * It periodically fetches the list of corrupt files from the namenode,
- * and figures out the location of the bad block by reading through
- * the corrupt file.
- */
-public class LocalBlockFixer extends BlockFixer {
- public static final Log LOG = LogFactory.getLog(LocalBlockFixer.class);
-
- private java.util.HashMap history;
-
- private BlockFixerHelper helper;
-
- public LocalBlockFixer(Configuration conf) throws IOException {
- super(conf);
- history = new java.util.HashMap();
- helper = new BlockFixerHelper(getConf());
- }
-
- public void run() {
- while (running) {
- try {
- LOG.info("LocalBlockFixer continuing to run...");
- doFix();
- } catch (Exception e) {
- LOG.error(StringUtils.stringifyException(e));
- } catch (Error err) {
- LOG.error("Exiting after encountering " +
- StringUtils.stringifyException(err));
- throw err;
- }
- }
- }
-
- void doFix() throws InterruptedException, IOException {
- while (running) {
- // Sleep before proceeding to fix files.
- Thread.sleep(blockFixInterval);
-
- // Purge history older than the history interval.
- purgeHistory();
-
- List corruptFiles = getCorruptFiles();
-
- filterUnfixableSourceFiles(corruptFiles.iterator());
-
- if (corruptFiles.isEmpty()) {
- // If there are no corrupt files, retry after some time.
- continue;
- }
- LOG.info("Found " + corruptFiles.size() + " corrupt files.");
-
- helper.sortCorruptFiles(corruptFiles);
-
- for (Path srcPath: corruptFiles) {
- if (!running) break;
- try {
- boolean fixed = helper.fixFile(srcPath);
- LOG.info("Adding " + srcPath + " to history");
- history.put(srcPath.toString(), new java.util.Date());
- if (fixed) {
- incrFilesFixed();
- }
- } catch (IOException ie) {
- LOG.error("Hit error while processing " + srcPath +
- ": " + StringUtils.stringifyException(ie));
- // Do nothing, move on to the next file.
- }
- }
- }
- }
-
-
- /**
- * We maintain history of fixed files because a fixed file may appear in
- * the list of corrupt files if we loop around too quickly.
- * This function removes the old items in the history so that we can
- * recognize files that have actually become corrupt since being fixed.
- */
- void purgeHistory() {
- java.util.Date cutOff = new java.util.Date(Time.now() -
- historyInterval);
- List toRemove = new java.util.ArrayList();
-
- for (String key: history.keySet()) {
- java.util.Date item = history.get(key);
- if (item.before(cutOff)) {
- toRemove.add(key);
- }
- }
- for (String key: toRemove) {
- LOG.info("Removing " + key + " from history");
- history.remove(key);
- }
- }
-
- /**
- * @return A list of corrupt files as obtained from the namenode
- */
- List getCorruptFiles() throws IOException {
- DistributedFileSystem dfs = helper.getDFS(new Path("/"));
-
- String[] files = RaidDFSUtil.getCorruptFiles(dfs);
- List corruptFiles = new LinkedList();
- for (String f: files) {
- Path p = new Path(f);
- if (!history.containsKey(p.toString())) {
- corruptFiles.add(p);
- }
- }
- RaidUtils.filterTrash(getConf(), corruptFiles);
- return corruptFiles;
- }
-
-}
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/LocalRaidNode.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/LocalRaidNode.java
deleted file mode 100644
index 5d2444d8af2..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/LocalRaidNode.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.util.List;
-
-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.fs.FileStatus;
-
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-
-/**
- * Implementation of {@link RaidNode} that performs raiding locally.
- */
-public class LocalRaidNode extends RaidNode {
-
- public static final Log LOG = LogFactory.getLog(LocalRaidNode.class);
-
- public LocalRaidNode(Configuration conf) throws IOException {
- super(conf);
- }
-
- /**
- * {@inheritDocs}
- */
- @Override
- void raidFiles(PolicyInfo info, List paths) throws IOException {
- doRaid(conf, info, paths);
- }
-
- /**
- * {@inheritDocs}
- */
- @Override
- int getRunningJobsForPolicy(String policyName) {
- return 0;
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ParityInputStream.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ParityInputStream.java
deleted file mode 100644
index b30cfcfe2a5..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ParityInputStream.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-
-import org.apache.hadoop.util.Progressable;
-
-/**
- * Wraps over multiple input streams and provides an input stream that is
- * an XOR of the streams.
- */
-class ParityInputStream extends InputStream {
- private static final int DEFAULT_BUFSIZE = 5*1024*1024;
- private InputStream[] streams;
- private byte[] xor;
- private byte[] buf;
- private int bufSize;
- private long remaining;
- private int available = 0;
- private int readPos = 0;
-
- public ParityInputStream(
- InputStream[] streams, long parityBlockSize, byte[] buf, byte[] xor) {
- assert buf.length == xor.length;
- bufSize = buf.length;
- this.streams = streams;
- remaining = parityBlockSize;
- this.buf = buf;
- this.xor = xor;
- }
-
- @Override
- public int read() throws IOException {
- makeAvailable();
- if (available == 0) {
- return -1;
- }
- int ret = xor[readPos];
- readPos++;
- available--;
- return ret;
- }
-
- @Override
- public int read(byte b[], int off, int len) throws IOException {
- makeAvailable();
- if (available == 0) {
- return -1;
- }
- int ret = Math.min(len, available);
- for (int i = 0; i < ret; ++i) {
- b[off+i] = xor[readPos+i];
- }
- readPos += ret;
- available -= ret;
- return ret;
- }
-
- public void close() throws IOException {
- for (InputStream i: streams) {
- i.close();
- }
- }
-
- /**
- * Send the contents of the stream to the sink.
- * @param sink
- * @param reporter
- * @throws IOException
- */
- public void drain(OutputStream sink, Progressable reporter)
- throws IOException {
-
- while (true) {
- makeAvailable();
- if (available == 0) {
- break;
- }
- sink.write(xor, readPos, available);
- available = 0;
- if (reporter != null) {
- reporter.progress();
- }
- }
- }
-
- /**
- * Make some bytes available for reading in the internal buffer.
- * @throws IOException
- */
- private void makeAvailable() throws IOException {
- if (available > 0 || remaining <= 0) {
- return;
- }
- // Read some bytes from the first stream.
- int xorlen = (int)Math.min(remaining, bufSize);
- readExact(streams[0], xor, xorlen);
-
- // Read bytes from all the other streams and xor them.
- for (int i = 1; i < streams.length; i++) {
- readExact(streams[i], buf, xorlen);
-
- for (int j = 0; j < xorlen; j++) {
- xor[j] ^= buf[j];
- }
- }
-
- remaining -= xorlen;
- available = xorlen;
- readPos = 0;
- readPos = 0;
- }
-
- private static void readExact(InputStream in, byte[] bufs, int toRead)
- throws IOException {
- int tread = 0;
- while (tread < toRead) {
- int read = in.read(bufs, tread, toRead - tread);
- if (read == -1) {
- // If the stream ends, fill in zeros.
- Arrays.fill(bufs, tread, toRead, (byte)0);
- tread = toRead;
- } else {
- tread += read;
- }
- }
- assert tread == toRead;
- }
-
-}
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidConfigurationException.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidConfigurationException.java
deleted file mode 100644
index 891863ae927..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidConfigurationException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * 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.raid;
-
-/**
- * Thrown when the config file for {@link RaidNode} is malformed.
- */
-public class RaidConfigurationException extends Exception {
- private static final long serialVersionUID = 4046516718965587999L;
-
- public RaidConfigurationException(String message) {
- super(message);
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidFilter.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidFilter.java
deleted file mode 100644
index 2af4ed9980b..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidFilter.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.conf.Configured;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-
-public class RaidFilter {
- static class Statistics {
- long numRaided = 0;
- long numTooNew = 0;
- long sizeTooNew = 0;
- long numTooSmall = 0;
- long sizeTooSmall = 0;
-
- public void aggregate(Statistics other) {
- this.numRaided += other.numRaided;
- this.numTooNew += other.numTooNew;
- this.sizeTooNew += other.sizeTooNew;
- this.numTooSmall += other.numTooSmall;
- this.sizeTooSmall += other.sizeTooSmall;
- }
-
- public String toString() {
- return "numRaided = " + numRaided +
- ", numTooNew = " + numTooNew +
- ", sizeTooNew = " + sizeTooNew +
- ", numTooSmall = " + numTooSmall +
- ", sizeTooSmall = " + sizeTooSmall;
- }
- }
-
- static class TimeBasedFilter extends Configured
- implements DirectoryTraversal.FileFilter {
- int targetRepl;
- Path raidDestPrefix;
- long modTimePeriod;
- long startTime;
- Statistics stats = new Statistics();
- String currentSrcPath = null;
- long[] modTimePeriods = new long[0];
- String[] otherSrcPaths = new String[0];
-
- TimeBasedFilter(Configuration conf, Path destPrefix, int targetRepl,
- long startTime, long modTimePeriod) {
- super(conf);
- this.raidDestPrefix = destPrefix;
- this.targetRepl = targetRepl;
- this.startTime = startTime;
- this.modTimePeriod = modTimePeriod;
- }
-
- TimeBasedFilter(Configuration conf,
- Path destPrefix, PolicyInfo info,
- List allPolicies, long startTime, Statistics stats) {
- super(conf);
- this.raidDestPrefix = destPrefix;
- this.targetRepl = Integer.parseInt(info.getProperty("targetReplication"));
- this.modTimePeriod = Long.parseLong(info.getProperty("modTimePeriod"));
- this.startTime = startTime;
- this.stats = stats;
- this.currentSrcPath = info.getSrcPath().toUri().getPath();
- initializeOtherPaths(allPolicies);
- }
-
- private void initializeOtherPaths(List allPolicies) {
- ArrayList tmp = new ArrayList(allPolicies);
- // Remove all policies where srcPath <= currentSrcPath or
- // matchingPrefixLength is < length(currentSrcPath)
- // The policies remaining are the only ones that could better
- // select a file chosen by the current policy.
- for (Iterator it = tmp.iterator(); it.hasNext(); ) {
- String src = it.next().getSrcPath().toUri().getPath();
- if (src.compareTo(currentSrcPath) <= 0) {
- it.remove();
- continue;
- }
- int matchLen = matchingPrefixLength(src, currentSrcPath);
- if (matchLen < currentSrcPath.length()) {
- it.remove();
- }
- }
- // Sort in reverse lexicographic order.
- Collections.sort(tmp, new Comparator() {
- public int compare(Object o1, Object o2) {
- return 0 -
- ((PolicyInfo)o1).getSrcPath().toUri().getPath().compareTo(
- ((PolicyInfo)o1).getSrcPath().toUri().getPath());
- }
- });
- otherSrcPaths = new String[tmp.size()];
- modTimePeriods = new long[otherSrcPaths.length];
- for (int i = 0; i < otherSrcPaths.length; i++) {
- otherSrcPaths[i] = tmp.get(i).getSrcPath().toUri().getPath();
- modTimePeriods[i] = Long.parseLong(
- tmp.get(i).getProperty("modTimePeriod"));
- }
- }
-
- public boolean check(FileStatus f) throws IOException {
- if (!canChooseForCurrentPolicy(f)) {
- return false;
- }
-
- // If the source file has fewer than or equal to 2 blocks, then skip it.
- long blockSize = f.getBlockSize();
- if (2 * blockSize >= f.getLen()) {
- stats.numTooSmall++;
- stats.sizeTooSmall += f.getLen();
- return false;
- }
-
- boolean select = false;
- try {
- Object ppair = RaidNode.getParityFile(
- raidDestPrefix, f.getPath(), getConf());
- // Is there is a valid parity file?
- if (ppair != null) {
- // Is the source at the target replication?
- if (f.getReplication() != targetRepl) {
- // Select the file so that its replication can be set.
- select = true;
- } else {
- stats.numRaided++;
- // Nothing to do, don't select the file.
- select = false;
- }
- } else {
- // No parity file.
- if (f.getModificationTime() + modTimePeriod < startTime) {
- // If the file is not too new, choose it for raiding.
- select = true;
- } else {
- select = false;
- stats.numTooNew++;
- stats.sizeTooNew += f.getLen();
- }
- }
- } catch (java.io.FileNotFoundException e) {
- select = true; // destination file does not exist
- } catch (java.io.IOException e) {
- // If there is a problem with the har path, this will let us continue.
- DirectoryTraversal.LOG.error(
- "Error while selecting " + StringUtils.stringifyException(e));
- }
- return select;
- }
-
- /**
- * Checks if a file can be chosen for the current policy.
- */
- boolean canChooseForCurrentPolicy(FileStatus stat) {
- boolean choose = true;
- if (otherSrcPaths.length > 0) {
- String fileStr = stat.getPath().toUri().getPath();
-
- // For a given string, find the best matching srcPath.
- int matchWithCurrent = matchingPrefixLength(fileStr, currentSrcPath);
- for (int i = 0; i < otherSrcPaths.length; i++) {
- // If the file is too new, move to the next.
- if (stat.getModificationTime() > startTime - modTimePeriods[i]) {
- continue;
- }
- int matchLen = matchingPrefixLength(fileStr, otherSrcPaths[i]);
- if (matchLen > 0 &&
- fileStr.charAt(matchLen - 1) == Path.SEPARATOR_CHAR) {
- matchLen--;
- }
- if (matchLen > matchWithCurrent) {
- choose = false;
- break;
- }
- }
- }
- return choose;
- }
-
- int matchingPrefixLength(final String s1, final String s2) {
- int len = 0;
- for (int j = 0; j < s1.length() && j < s2.length(); j++) {
- if (s1.charAt(j) == s2.charAt(j)) {
- len++;
- } else {
- break;
- }
- }
- return len;
- }
- }
-
- static class PreferenceFilter extends Configured
- implements DirectoryTraversal.FileFilter {
- Path firstChoicePrefix;
- DirectoryTraversal.FileFilter secondChoiceFilter;
-
- PreferenceFilter(Configuration conf,
- Path firstChoicePrefix, Path secondChoicePrefix,
- int targetRepl, long startTime, long modTimePeriod) {
- super(conf);
- this.firstChoicePrefix = firstChoicePrefix;
- this.secondChoiceFilter = new TimeBasedFilter(conf,
- secondChoicePrefix, targetRepl, startTime, modTimePeriod);
- }
-
- PreferenceFilter(Configuration conf,
- Path firstChoicePrefix, Path secondChoicePrefix,
- PolicyInfo info, List allPolicies, long startTime,
- Statistics stats) {
- super(conf);
- this.firstChoicePrefix = firstChoicePrefix;
- this.secondChoiceFilter = new TimeBasedFilter(
- conf, secondChoicePrefix, info, allPolicies, startTime, stats);
- }
-
- public boolean check(FileStatus f) throws IOException {
- Object firstChoicePPair =
- RaidNode.getParityFile(firstChoicePrefix, f.getPath(), getConf());
- if (firstChoicePPair == null) {
- // The decision is upto the the second choice filter.
- return secondChoiceFilter.check(f);
- } else {
- // There is already a parity file under the first choice path.
- // We dont want to choose this file.
- return false;
- }
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidNode.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidNode.java
deleted file mode 100644
index 27ecc0b4f74..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidNode.java
+++ /dev/null
@@ -1,1630 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.lang.Thread;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-
-import org.xml.sax.SAXException;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.hadoop.ipc.*;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.tools.HadoopArchives;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Daemon;
-import org.apache.hadoop.util.ToolRunner;
-import org.apache.hadoop.util.Time;
-import org.apache.hadoop.net.NetUtils;
-import org.apache.hadoop.fs.HarFileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.BlockLocation;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.util.Progressable;
-
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.raid.protocol.PolicyList;
-import org.apache.hadoop.raid.protocol.RaidProtocol;
-import org.apache.hadoop.raid.protocol.PolicyInfo.ErasureCodeType;
-
-/**
- * A base class that implements {@link RaidProtocol}.
- *
- * use raid.classname to specify which implementation to use
- */
-public abstract class RaidNode implements RaidProtocol {
-
- static{
- Configuration.addDefaultResource("hdfs-default.xml");
- Configuration.addDefaultResource("hdfs-site.xml");
- Configuration.addDefaultResource("mapred-default.xml");
- Configuration.addDefaultResource("mapred-site.xml");
- }
- public static final Log LOG = LogFactory.getLog( "org.apache.hadoop.raid.RaidNode");
- public static final long SLEEP_TIME = 10000L; // 10 seconds
- public static final String TRIGGER_MONITOR_SLEEP_TIME_KEY =
- "hdfs.raid.trigger.monitor.sleep.time";
- public static final int DEFAULT_PORT = 60000;
- // Default stripe length = 5, parity length for RS code = 3
- public static final int DEFAULT_STRIPE_LENGTH = 5;
- public static final int RS_PARITY_LENGTH_DEFAULT = 3;
-
- public static final String RS_PARITY_LENGTH_KEY = "hdfs.raidrs.paritylength";
- public static final String STRIPE_LENGTH_KEY = "hdfs.raid.stripeLength";
-
- public static final String DEFAULT_RAID_LOCATION = "/raid";
- public static final String RAID_LOCATION_KEY = "hdfs.raid.locations";
- public static final String DEFAULT_RAID_TMP_LOCATION = "/tmp/raid";
- public static final String RAID_TMP_LOCATION_KEY = "fs.raid.tmpdir";
- public static final String DEFAULT_RAID_HAR_TMP_LOCATION = "/tmp/raid_har";
- public static final String RAID_HAR_TMP_LOCATION_KEY = "fs.raid.hartmpdir";
-
- public static final String DEFAULT_RAIDRS_LOCATION = "/raidrs";
- public static final String RAIDRS_LOCATION_KEY = "hdfs.raidrs.locations";
- public static final String DEFAULT_RAIDRS_TMP_LOCATION = "/tmp/raidrs";
- public static final String RAIDRS_TMP_LOCATION_KEY = "fs.raidrs.tmpdir";
- public static final String DEFAULT_RAIDRS_HAR_TMP_LOCATION = "/tmp/raidrs_har";
- public static final String RAIDRS_HAR_TMP_LOCATION_KEY = "fs.raidrs.hartmpdir";
-
- public static final String HAR_SUFFIX = "_raid.har";
- public static final Pattern PARITY_HAR_PARTFILE_PATTERN =
- Pattern.compile(".*" + HAR_SUFFIX + "/part-.*");
-
- public static final String RAIDNODE_CLASSNAME_KEY = "raid.classname";
-
- /** RPC server */
- private Server server;
- /** RPC server address */
- private InetSocketAddress serverAddress = null;
- /** only used for testing purposes */
- protected boolean stopRequested = false;
-
- /** Configuration Manager */
- private ConfigManager configMgr;
-
- /** hadoop configuration */
- protected Configuration conf;
-
- protected boolean initialized; // Are we initialized?
- protected volatile boolean running; // Are we running?
-
- /** Deamon thread to trigger policies */
- Daemon triggerThread = null;
- public static long triggerMonitorSleepTime = SLEEP_TIME;
-
- /** Deamon thread to delete obsolete parity files */
- PurgeMonitor purgeMonitor = null;
- Daemon purgeThread = null;
-
- /** Deamon thread to har raid directories */
- Daemon harThread = null;
-
- /** Daemon thread to fix corrupt files */
- BlockFixer blockFixer = null;
- Daemon blockFixerThread = null;
-
- // statistics about RAW hdfs blocks. This counts all replicas of a block.
- public static class Statistics {
- long numProcessedBlocks; // total blocks encountered in namespace
- long processedSize; // disk space occupied by all blocks
- long remainingSize; // total disk space post RAID
-
- long numMetaBlocks; // total blocks in metafile
- long metaSize; // total disk space for meta files
-
- public void clear() {
- numProcessedBlocks = 0;
- processedSize = 0;
- remainingSize = 0;
- numMetaBlocks = 0;
- metaSize = 0;
- }
- public String toString() {
- long save = processedSize - (remainingSize + metaSize);
- long savep = 0;
- if (processedSize > 0) {
- savep = (save * 100)/processedSize;
- }
- String msg = " numProcessedBlocks = " + numProcessedBlocks +
- " processedSize = " + processedSize +
- " postRaidSize = " + remainingSize +
- " numMetaBlocks = " + numMetaBlocks +
- " metaSize = " + metaSize +
- " %save in raw disk space = " + savep;
- return msg;
- }
- }
-
- // Startup options
- static public enum StartupOption{
- TEST ("-test"),
- REGULAR ("-regular");
-
- private String name = null;
- private StartupOption(String arg) {this.name = arg;}
- public String getName() {return name;}
- }
-
- /**
- * Start RaidNode.
- *
- * The raid-node can be started with one of the following startup options:
- *
- *
{@link StartupOption#REGULAR REGULAR} - normal raid node startup
- *
- * The option is passed via configuration field:
- * fs.raidnode.startup
- *
- * The conf will be modified to reflect the actual ports on which
- * the RaidNode is up and running if the user passes the port as
- * zero in the conf.
- *
- * @param conf confirguration
- * @throws IOException
- */
-
- RaidNode(Configuration conf) throws IOException {
- try {
- initialize(conf);
- } catch (IOException e) {
- LOG.error(StringUtils.stringifyException(e));
- this.stop();
- throw e;
- } catch (Exception e) {
- this.stop();
- throw new IOException(e);
- }
- }
-
- public long getProtocolVersion(String protocol,
- long clientVersion) throws IOException {
- if (protocol.equals(RaidProtocol.class.getName())) {
- return RaidProtocol.versionID;
- } else {
- throw new IOException("Unknown protocol to name node: " + protocol);
- }
- }
-
- @Override
- public ProtocolSignature getProtocolSignature(String protocol,
- long clientVersion, int clientMethodsHash) throws IOException {
- return ProtocolSignature.getProtocolSignature(
- this, protocol, clientVersion, clientMethodsHash);
- }
-
- /**
- * Wait for service to finish.
- * (Normally, it runs forever.)
- */
- public void join() {
- try {
- if (server != null) server.join();
- if (triggerThread != null) triggerThread.join();
- if (blockFixerThread != null) blockFixerThread.join();
- if (purgeThread != null) purgeThread.join();
- } catch (InterruptedException ie) {
- // do nothing
- }
- }
-
- /**
- * Stop all RaidNode threads and wait for all to finish.
- */
- public void stop() {
- if (stopRequested) {
- return;
- }
- stopRequested = true;
- running = false;
- if (server != null) server.stop();
- if (triggerThread != null) triggerThread.interrupt();
- if (blockFixer != null) blockFixer.running = false;
- if (blockFixerThread != null) blockFixerThread.interrupt();
- if (purgeThread != null) purgeThread.interrupt();
- }
-
- private static InetSocketAddress getAddress(String address) {
- return NetUtils.createSocketAddr(address);
- }
-
- public static InetSocketAddress getAddress(Configuration conf) {
- String nodeport = conf.get("raid.server.address");
- if (nodeport == null) {
- nodeport = "localhost:" + DEFAULT_PORT;
- }
- return getAddress(nodeport);
- }
-
- public InetSocketAddress getListenerAddress() {
- return server.getListenerAddress();
- }
-
- private void initialize(Configuration conf)
- throws IOException, SAXException, InterruptedException, RaidConfigurationException,
- ClassNotFoundException, ParserConfigurationException {
- this.conf = conf;
- InetSocketAddress socAddr = RaidNode.getAddress(conf);
- int handlerCount = conf.getInt("fs.raidnode.handler.count", 10);
-
- // read in the configuration
- configMgr = new ConfigManager(conf);
-
- // create rpc server
- this.server = RPC.getServer(this, socAddr.getHostName(), socAddr.getPort(),
- handlerCount, false, conf);
-
- // The rpc-server port can be ephemeral... ensure we have the correct info
- this.serverAddress = this.server.getListenerAddress();
- LOG.info("RaidNode up at: " + this.serverAddress);
-
- initialized = true;
- running = true;
- this.server.start(); // start RPC server
-
- this.blockFixer = BlockFixer.createBlockFixer(conf);
- this.blockFixerThread = new Daemon(this.blockFixer);
- this.blockFixerThread.start();
- // start the deamon thread to fire polcies appropriately
- RaidNode.triggerMonitorSleepTime = conf.getLong(
- TRIGGER_MONITOR_SLEEP_TIME_KEY,
- SLEEP_TIME);
-
- // start the deamon thread to fire polcies appropriately
- this.triggerThread = new Daemon(new TriggerMonitor());
- this.triggerThread.start();
-
- // start the thread that deletes obsolete parity files
- this.purgeMonitor = new PurgeMonitor();
- this.purgeThread = new Daemon(purgeMonitor);
- this.purgeThread.start();
-
- // start the thread that creates HAR files
- this.harThread = new Daemon(new HarMonitor());
- this.harThread.start();
- }
-
-
- /**
- * Implement RaidProtocol methods
- */
-
- /** {@inheritDoc} */
- public PolicyList[] getAllPolicies() throws IOException {
- Collection list = configMgr.getAllPolicies();
- return list.toArray(new PolicyList[list.size()]);
- }
-
- /** {@inheritDoc} */
- public String recoverFile(String inStr, long corruptOffset) throws IOException {
-
- LOG.info("Recover File for " + inStr + " for corrupt offset " + corruptOffset);
- Path inputPath = new Path(inStr);
- Path srcPath = inputPath.makeQualified(inputPath.getFileSystem(conf));
- // find stripe length from config
- int stripeLength = getStripeLength(conf);
-
- // first try decode using XOR code
- Path destPref = xorDestinationPath(conf);
- Decoder decoder = new XORDecoder(conf, RaidNode.getStripeLength(conf));
- Path unraided = unRaid(conf, srcPath, destPref, decoder,
- stripeLength, corruptOffset);
- if (unraided != null) {
- return unraided.toString();
- }
-
- // try decode using ReedSolomon code
- destPref = rsDestinationPath(conf);
- decoder = new ReedSolomonDecoder(conf, RaidNode.getStripeLength(conf),
- RaidNode.rsParityLength(conf));
- unraided = unRaid(conf, srcPath, destPref, decoder,
- stripeLength, corruptOffset);
- if (unraided != null) {
- return unraided.toString();
- }
- return null;
- }
-
- /**
- * returns the number of raid jobs running for a particular policy
- */
- abstract int getRunningJobsForPolicy(String policyName);
-
- /**
- * Periodically checks to see which policies should be fired.
- */
- class TriggerMonitor implements Runnable {
- class ScanState {
- long fullScanStartTime;
- DirectoryTraversal pendingTraversal;
- RaidFilter.Statistics stats;
- ScanState() {
- fullScanStartTime = 0;
- pendingTraversal = null;
- stats = new RaidFilter.Statistics();
- }
- }
-
- private Map scanStateMap =
- new HashMap();
-
- /**
- */
- public void run() {
- while (running) {
- try {
- doProcess();
- } catch (Exception e) {
- LOG.error(StringUtils.stringifyException(e));
- } finally {
- LOG.info("Trigger thread continuing to run...");
- }
- }
- }
-
- /**
- * Should we select more files for a policy.
- */
- private boolean shouldSelectFiles(PolicyInfo info) {
- String policyName = info.getName();
- ScanState scanState = scanStateMap.get(policyName);
- int runningJobsCount = getRunningJobsForPolicy(policyName);
- // Is there a scan in progress for this policy?
- if (scanState.pendingTraversal != null) {
- int maxJobsPerPolicy = configMgr.getMaxJobsPerPolicy();
-
- // If there is a scan in progress for this policy, we can have
- // upto maxJobsPerPolicy running jobs.
- return (runningJobsCount < maxJobsPerPolicy);
- } else {
- // If there isn't a scan in progress for this policy, we don't
- // want to start a fresh scan if there is even one running job.
- if (runningJobsCount >= 1) {
- return false;
- }
- // Check the time of the last full traversal before starting a fresh
- // traversal.
- long lastScan = scanState.fullScanStartTime;
- return (now() > lastScan + configMgr.getPeriodicity());
- }
- }
-
- /**
- * Returns a list of pathnames that needs raiding.
- * The list of paths could be obtained by resuming a previously suspended
- * traversal.
- * The number of paths returned is limited by raid.distraid.max.jobs.
- */
- private List selectFiles(
- PolicyInfo info, ArrayList allPolicies) throws IOException {
- Path destPrefix = getDestinationPath(info.getErasureCode(), conf);
- String policyName = info.getName();
- Path srcPath = info.getSrcPath();
- long modTimePeriod = Long.parseLong(info.getProperty("modTimePeriod"));
-
- // Max number of files returned.
- int selectLimit = configMgr.getMaxFilesPerJob();
- int targetRepl = Integer.parseInt(info.getProperty("targetReplication"));
-
- long selectStartTime = Time.now();
-
- ScanState scanState = scanStateMap.get(policyName);
- // If we have a pending traversal, resume it.
- if (scanState.pendingTraversal != null) {
- DirectoryTraversal dt = scanState.pendingTraversal;
- LOG.info("Resuming traversal for policy " + policyName);
- DirectoryTraversal.FileFilter filter =
- filterForPolicy(selectStartTime, info, allPolicies, scanState.stats);
- List returnSet = dt.getFilteredFiles(filter, selectLimit);
- if (dt.doneTraversal()) {
- scanState.pendingTraversal = null;
- }
- return returnSet;
- }
-
- // Expand destination prefix path.
- String destpstr = destPrefix.toString();
- if (!destpstr.endsWith(Path.SEPARATOR)) {
- destpstr += Path.SEPARATOR;
- }
-
- List returnSet = new LinkedList();
-
- FileSystem fs = srcPath.getFileSystem(conf);
- FileStatus[] gpaths = fs.globStatus(srcPath);
- if (gpaths != null) {
- List selectedPaths = new LinkedList();
- for (FileStatus onepath: gpaths) {
- String pathstr = onepath.getPath().makeQualified(fs).toString();
- if (!pathstr.endsWith(Path.SEPARATOR)) {
- pathstr += Path.SEPARATOR;
- }
- if (pathstr.startsWith(destpstr) || destpstr.startsWith(pathstr)) {
- LOG.info("Skipping source " + pathstr +
- " because it conflicts with raid directory " + destpstr);
- } else {
- selectedPaths.add(onepath);
- }
- }
-
- // Set the time for a new traversal.
- scanState.fullScanStartTime = now();
- DirectoryTraversal dt = new DirectoryTraversal(fs, selectedPaths,
- conf.getInt("raid.directorytraversal.threads", 4));
- DirectoryTraversal.FileFilter filter =
- filterForPolicy(selectStartTime, info, allPolicies, scanState.stats);
- returnSet = dt.getFilteredFiles(filter, selectLimit);
- if (!dt.doneTraversal()) {
- scanState.pendingTraversal = dt;
- }
- }
- return returnSet;
- }
-
- /**
- * Keep processing policies.
- * If the config file has changed, then reload config file and start afresh.
- */
- private void doProcess() throws IOException, InterruptedException {
- ArrayList allPolicies = new ArrayList();
- for (PolicyList category : configMgr.getAllPolicies()) {
- for (PolicyInfo info: category.getAll()) {
- allPolicies.add(info);
- }
- }
- while (running) {
- Thread.sleep(RaidNode.triggerMonitorSleepTime);
-
- boolean reloaded = configMgr.reloadConfigsIfNecessary();
- if (reloaded) {
- allPolicies.clear();
- for (PolicyList category : configMgr.getAllPolicies()) {
- for (PolicyInfo info: category.getAll()) {
- allPolicies.add(info);
- }
- }
- }
- for (PolicyInfo info: allPolicies) {
- if (!scanStateMap.containsKey(info.getName())) {
- scanStateMap.put(info.getName(), new ScanState());
- }
-
- if (!shouldSelectFiles(info)) {
- continue;
- }
-
- LOG.info("Triggering Policy Filter " + info.getName() +
- " " + info.getSrcPath());
- List filteredPaths = null;
- try {
- filteredPaths = selectFiles(info, allPolicies);
- } catch (Exception e) {
- LOG.error("Exception while invoking filter on policy " + info.getName() +
- " srcPath " + info.getSrcPath() +
- " exception " + StringUtils.stringifyException(e));
- continue;
- }
-
- if (filteredPaths == null || filteredPaths.size() == 0) {
- LOG.info("No filtered paths for policy " + info.getName());
- continue;
- }
-
- // Apply the action on accepted paths
- LOG.info("Triggering Policy Action " + info.getName() +
- " " + info.getSrcPath() + " raid " + filteredPaths.size() + " files");
- try {
- raidFiles(info, filteredPaths);
- } catch (Exception e) {
- LOG.error("Exception while invoking action on policy " + info.getName() +
- " srcPath " + info.getSrcPath() +
- " exception " + StringUtils.stringifyException(e));
- continue;
- }
- }
- }
- }
-
- DirectoryTraversal.FileFilter filterForPolicy(
- long startTime, PolicyInfo info, List allPolicies,
- RaidFilter.Statistics stats)
- throws IOException {
- switch (info.getErasureCode()) {
- case XOR:
- // Return a preference-based filter that prefers RS parity files
- // over XOR parity files.
- return new RaidFilter.PreferenceFilter(
- conf, rsDestinationPath(conf), xorDestinationPath(conf),
- info, allPolicies, startTime, stats);
- case RS:
- return new RaidFilter.TimeBasedFilter(conf, rsDestinationPath(conf),
- info, allPolicies, startTime, stats);
- default:
- return null;
- }
- }
- }
-
- /**
- * raid a list of files, this will be overridden by subclasses of RaidNode
- */
- abstract void raidFiles(PolicyInfo info, List paths)
- throws IOException;
-
- static private Path getOriginalParityFile(Path destPathPrefix, Path srcPath) {
- return new Path(destPathPrefix, makeRelative(srcPath));
- }
-
- static class ParityFilePair {
- private Path path;
- private FileSystem fs;
-
- public ParityFilePair( Path path, FileSystem fs) {
- this.path = path;
- this.fs = fs;
- }
-
- public Path getPath() {
- return this.path;
- }
-
- public FileSystem getFileSystem() {
- return this.fs;
- }
-
- }
-
-
- /**
- * Returns the Path to the parity file of a given file
- *
- * @param destPathPrefix Destination prefix defined by some policy
- * @param srcPath Path to the original source file
- * @param create Boolean value telling whether a new parity file should be created
- * @return Path object representing the parity file of the source
- * @throws IOException
- */
- static ParityFilePair getParityFile(Path destPathPrefix, Path srcPath, Configuration conf) throws IOException {
- Path srcParent = srcPath.getParent();
-
- FileSystem fsDest = destPathPrefix.getFileSystem(conf);
- FileSystem fsSrc = srcPath.getFileSystem(conf);
-
- FileStatus srcStatus = null;
- try {
- srcStatus = fsSrc.getFileStatus(srcPath);
- } catch (java.io.FileNotFoundException e) {
- return null;
- }
-
- Path outDir = destPathPrefix;
- if (srcParent != null) {
- if (srcParent.getParent() == null) {
- outDir = destPathPrefix;
- } else {
- outDir = new Path(destPathPrefix, makeRelative(srcParent));
- }
- }
-
-
- //CASE 1: CHECK HAR - Must be checked first because har is created after
- // parity file and returning the parity file could result in error while
- // reading it.
- Path outPath = getOriginalParityFile(destPathPrefix, srcPath);
- String harDirName = srcParent.getName() + HAR_SUFFIX;
- Path HarPath = new Path(outDir,harDirName);
- if (fsDest.exists(HarPath)) {
- URI HarPathUri = HarPath.toUri();
- Path inHarPath = new Path("har://",HarPathUri.getPath()+"/"+outPath.toUri().getPath());
- FileSystem fsHar = new HarFileSystem(fsDest);
- fsHar.initialize(inHarPath.toUri(), conf);
- if (fsHar.exists(inHarPath)) {
- FileStatus inHar = fsHar.getFileStatus(inHarPath);
- if (inHar.getModificationTime() == srcStatus.getModificationTime()) {
- return new ParityFilePair(inHarPath,fsHar);
- }
- }
- }
-
- //CASE 2: CHECK PARITY
- try {
- FileStatus outHar = fsDest.getFileStatus(outPath);
- if (outHar.getModificationTime() == srcStatus.getModificationTime()) {
- return new ParityFilePair(outPath,fsDest);
- }
- } catch (java.io.FileNotFoundException e) {
- }
-
- return null; // NULL if no parity file
- }
-
- static ParityFilePair xorParityForSource(Path srcPath, Configuration conf)
- throws IOException {
- try {
- Path destPath = xorDestinationPath(conf);
- return getParityFile(destPath, srcPath, conf);
- } catch (FileNotFoundException e) {
- }
- return null;
- }
-
- static ParityFilePair rsParityForSource(Path srcPath, Configuration conf)
- throws IOException {
- try {
- Path destPath = rsDestinationPath(conf);
- return getParityFile(destPath, srcPath, conf);
- } catch (FileNotFoundException e) {
- }
- return null;
- }
-
- private ParityFilePair getParityFile(Path destPathPrefix, Path srcPath)
- throws IOException {
- return getParityFile(destPathPrefix, srcPath, conf);
- }
-
- /**
- * RAID a list of files.
- */
- void doRaid(Configuration conf, PolicyInfo info, List paths)
- throws IOException {
- int targetRepl = Integer.parseInt(info.getProperty("targetReplication"));
- int metaRepl = Integer.parseInt(info.getProperty("metaReplication"));
- int stripeLength = getStripeLength(conf);
- Path destPref = getDestinationPath(info.getErasureCode(), conf);
- String simulate = info.getProperty("simulate");
- boolean doSimulate = simulate == null ? false : Boolean
- .parseBoolean(simulate);
-
- Statistics statistics = new Statistics();
- int count = 0;
-
- for (FileStatus s : paths) {
- doRaid(conf, s, destPref, info.getErasureCode(), statistics,
- new RaidUtils.DummyProgressable(), doSimulate, targetRepl, metaRepl,
- stripeLength);
- if (count % 1000 == 0) {
- LOG.info("RAID statistics " + statistics.toString());
- }
- count++;
- }
- LOG.info("RAID statistics " + statistics.toString());
- }
-
-
- /**
- * RAID an individual file
- */
-
- static public void doRaid(Configuration conf, PolicyInfo info,
- FileStatus src, Statistics statistics, Progressable reporter)
- throws IOException {
- int targetRepl = Integer.parseInt(info.getProperty("targetReplication"));
- int metaRepl = Integer.parseInt(info.getProperty("metaReplication"));
- int stripeLength = getStripeLength(conf);
-
- Path destPref = getDestinationPath(info.getErasureCode(), conf);
- String simulate = info.getProperty("simulate");
- boolean doSimulate = simulate == null ? false : Boolean
- .parseBoolean(simulate);
-
- doRaid(conf, src, destPref, info.getErasureCode(), statistics,
- reporter, doSimulate, targetRepl, metaRepl, stripeLength);
- }
-
- /**
- * RAID an individual file
- */
- static public void doRaid(Configuration conf, FileStatus stat, Path destPath,
- PolicyInfo.ErasureCodeType code, Statistics statistics,
- Progressable reporter, boolean doSimulate,
- int targetRepl, int metaRepl, int stripeLength)
- throws IOException {
- Path p = stat.getPath();
- FileSystem srcFs = p.getFileSystem(conf);
-
- // extract block locations from File system
- BlockLocation[] locations = srcFs.getFileBlockLocations(stat, 0, stat.getLen());
-
- // if the file has fewer than 2 blocks, then nothing to do
- if (locations.length <= 2) {
- return;
- }
-
- // add up the raw disk space occupied by this file
- long diskSpace = 0;
- for (BlockLocation l: locations) {
- diskSpace += (l.getLength() * stat.getReplication());
- }
- statistics.numProcessedBlocks += locations.length;
- statistics.processedSize += diskSpace;
-
- // generate parity file
- generateParityFile(conf, stat, reporter, srcFs, destPath, code,
- locations, metaRepl, stripeLength);
-
- // reduce the replication factor of the source file
- if (!doSimulate) {
- if (srcFs.setReplication(p, (short)targetRepl) == false) {
- LOG.error("Error in reducing relication factor of file " + p + " to " + targetRepl);
- statistics.remainingSize += diskSpace; // no change in disk space usage
- return;
- }
- }
-
- diskSpace = 0;
- for (BlockLocation l: locations) {
- diskSpace += (l.getLength() * targetRepl);
- }
- statistics.remainingSize += diskSpace;
-
- // the metafile will have this many number of blocks
- int numMeta = locations.length / stripeLength;
- if (locations.length % stripeLength != 0) {
- numMeta++;
- }
-
- // we create numMeta for every file. This metablock has metaRepl # replicas.
- // the last block of the metafile might not be completely filled up, but we
- // ignore that for now.
- statistics.numMetaBlocks += (numMeta * metaRepl);
- statistics.metaSize += (numMeta * metaRepl * stat.getBlockSize());
- }
-
- /**
- * Create the parity file.
- */
- static private void generateParityFile(Configuration conf, FileStatus stat,
- Progressable reporter,
- FileSystem inFs,
- Path destPathPrefix,
- ErasureCodeType code,
- BlockLocation[] locations,
- int metaRepl, int stripeLength) throws IOException {
-
- Path inpath = stat.getPath();
- Path outpath = getOriginalParityFile(destPathPrefix, inpath);
- FileSystem outFs = outpath.getFileSystem(conf);
-
- // If the parity file is already upto-date, then nothing to do
- try {
- FileStatus stmp = outFs.getFileStatus(outpath);
- if (stmp.getModificationTime() == stat.getModificationTime()) {
- LOG.info("Parity file for " + inpath + "(" + locations.length +
- ") is " + outpath + " already upto-date. Nothing more to do.");
- return;
- }
- } catch (IOException e) {
- // ignore errors because the raid file might not exist yet.
- }
-
- Encoder encoder = encoderForCode(conf, code);
- encoder.encodeFile(inFs, inpath, outFs, outpath, (short)metaRepl, reporter);
-
- // set the modification time of the RAID file. This is done so that the modTime of the
- // RAID file reflects that contents of the source file that it has RAIDed. This should
- // also work for files that are being appended to. This is necessary because the time on
- // on the destination namenode may not be synchronised with the timestamp of the
- // source namenode.
- outFs.setTimes(outpath, stat.getModificationTime(), -1);
- inFs.setTimes(inpath, stat.getModificationTime(), stat.getAccessTime());
-
- FileStatus outstat = outFs.getFileStatus(outpath);
- FileStatus inStat = inFs.getFileStatus(inpath);
- LOG.info("Source file " + inpath + " of size " + inStat.getLen() +
- " Parity file " + outpath + " of size " + outstat.getLen() +
- " src mtime " + stat.getModificationTime() +
- " parity mtime " + outstat.getModificationTime());
- }
-
- /**
- * Extract a good block from the parity block. This assumes that the
- * corruption is in the main file and the parity file is always good.
- */
- public static Path unRaid(Configuration conf, Path srcPath,
- Path destPathPrefix, Decoder decoder, int stripeLength,
- long corruptOffset) throws IOException {
-
- // Test if parity file exists
- ParityFilePair ppair = getParityFile(destPathPrefix, srcPath, conf);
- if (ppair == null) {
- return null;
- }
-
- final Path recoveryDestination = new Path(
- RaidNode.unraidTmpDirectory(conf));
- FileSystem destFs = recoveryDestination.getFileSystem(conf);
- final Path recoveredPrefix =
- destFs.makeQualified(new Path(recoveryDestination, makeRelative(srcPath)));
- final Path recoveredPath =
- new Path(recoveredPrefix + "." + new Random().nextLong() + ".recovered");
- LOG.info("Creating recovered file " + recoveredPath);
-
- FileSystem srcFs = srcPath.getFileSystem(conf);
- decoder.decodeFile(srcFs, srcPath, ppair.getFileSystem(),
- ppair.getPath(), corruptOffset, recoveredPath);
-
- return recoveredPath;
- }
-
- public static Path unRaidCorruptBlock(Configuration conf, Path srcPath,
- Path destPathPrefix, Decoder decoder, int stripeLength,
- long corruptOffset) throws IOException {
- // Test if parity file exists
- ParityFilePair ppair = getParityFile(destPathPrefix, srcPath, conf);
- if (ppair == null) {
- LOG.error("Could not find parity file for " + srcPath);
- return null;
- }
-
- final Path recoveryDestination = new Path(RaidNode.xorTempPrefix(conf));
- FileSystem destFs = recoveryDestination.getFileSystem(conf);
- final Path recoveredPrefix =
- destFs.makeQualified(new Path(recoveryDestination, makeRelative(srcPath)));
- final Path recoveredBlock =
- new Path(recoveredPrefix + "." + new Random().nextLong() + ".recovered");
- LOG.info("Creating recovered Block " + recoveredBlock);
-
- FileSystem srcFs = srcPath.getFileSystem(conf);
- FileStatus stat = srcFs.getFileStatus(srcPath);
- long limit = Math.min(stat.getBlockSize(), stat.getLen() - corruptOffset);
- java.io.OutputStream out = ppair.getFileSystem().create(recoveredBlock);
- decoder.fixErasedBlock(srcFs, srcPath,
- ppair.getFileSystem(), ppair.getPath(),
- stat.getBlockSize(), corruptOffset, 0, limit, out);
- out.close();
- return recoveredBlock;
- }
-
- /**
- * Periodically delete orphaned parity files.
- */
- class PurgeMonitor implements Runnable {
- /**
- */
- public void run() {
- while (running) {
- try {
- doPurge();
- } catch (Exception e) {
- LOG.error(StringUtils.stringifyException(e));
- } finally {
- LOG.info("Purge parity files thread continuing to run...");
- }
- }
- }
-
- /**
- * Traverse the parity destination directory, removing directories that
- * no longer existing in the source.
- * @throws IOException
- */
- private void purgeDirectories(FileSystem fs, Path root) throws IOException {
- String prefix = root.toUri().getPath();
- List startPaths = new LinkedList();
- try {
- startPaths.add(fs.getFileStatus(root));
- } catch (FileNotFoundException e) {
- return;
- }
- DirectoryTraversal dt = new DirectoryTraversal(fs, startPaths);
- FileStatus dir = dt.getNextDirectory();
- for (; dir != null; dir = dt.getNextDirectory()) {
- Path dirPath = dir.getPath();
- if (dirPath.toUri().getPath().endsWith(HAR_SUFFIX)) {
- continue;
- }
- String dirStr = dirPath.toUri().getPath();
- if (!dirStr.startsWith(prefix)) {
- continue;
- }
- String src = dirStr.replaceFirst(prefix, "");
- if (src.length() == 0) continue;
- Path srcPath = new Path(src);
- if (!fs.exists(srcPath)) {
- LOG.info("Purging directory " + dirPath);
- boolean done = fs.delete(dirPath, true);
- if (!done) {
- LOG.error("Could not purge " + dirPath);
- }
- }
- }
- }
-
- /**
- * Delete orphaned files. The reason this is done by a separate thread
- * is to not burden the TriggerMonitor with scanning the
- * destination directories.
- */
- private void doPurge() throws IOException, InterruptedException {
- long prevExec = 0;
- while (running) {
-
- // The config may be reloaded by the TriggerMonitor.
- // This thread uses whatever config is currently active.
- while(now() < prevExec + configMgr.getPeriodicity()){
- Thread.sleep(SLEEP_TIME);
- }
-
- LOG.info("Started purge scan");
- prevExec = now();
-
- // expand destination prefix path
- Path destPref = xorDestinationPath(conf);
- FileSystem destFs = destPref.getFileSystem(conf);
- purgeDirectories(destFs, destPref);
-
- destPref = rsDestinationPath(conf);
- destFs = destPref.getFileSystem(conf);
- purgeDirectories(destFs, destPref);
-
- // fetch all categories
- for (PolicyList category : configMgr.getAllPolicies()) {
- for (PolicyInfo info: category.getAll()) {
-
- try {
- // expand destination prefix path
- destPref = getDestinationPath(info.getErasureCode(), conf);
- destFs = destPref.getFileSystem(conf);
-
- //get srcPaths
- Path[] srcPaths = info.getSrcPathExpanded();
-
- if (srcPaths != null) {
- for (Path srcPath: srcPaths) {
- // expand destination prefix
- Path destPath = getOriginalParityFile(destPref, srcPath);
-
- FileSystem srcFs = info.getSrcPath().getFileSystem(conf);
- FileStatus stat = null;
- try {
- stat = destFs.getFileStatus(destPath);
- } catch (FileNotFoundException e) {
- // do nothing, leave stat = null;
- }
- if (stat != null) {
- LOG.info("Purging obsolete parity files for policy " +
- info.getName() + " " + destPath);
- recursePurge(info.getErasureCode(), srcFs, destFs,
- destPref.toUri().getPath(), stat);
- }
-
- }
- }
- } catch (Exception e) {
- LOG.warn("Ignoring Exception while processing policy " +
- info.getName() + " " +
- StringUtils.stringifyException(e));
- }
- }
- }
- }
- }
-
- /**
- * The destPrefix is the absolute pathname of the destinationPath
- * specified in the policy (without the host:port)
- */
- void recursePurge(ErasureCodeType code,
- FileSystem srcFs, FileSystem destFs,
- String destPrefix, FileStatus dest)
- throws IOException {
-
- Path destPath = dest.getPath(); // pathname, no host:port
- String destStr = destPath.toUri().getPath();
- LOG.debug("Checking " + destPath + " prefix " + destPrefix);
-
- // Verify if it is a har file
- if (dest.isDirectory() && destStr.endsWith(HAR_SUFFIX)) {
- try {
- int harUsedPercent =
- usefulHar(code, srcFs, destFs, destPath, destPrefix, conf);
- LOG.info("Useful percentage of " + destStr + " " + harUsedPercent);
- // Delete the har if its usefulness reaches a threshold.
- if (harUsedPercent <= conf.getInt("raid.har.usage.threshold", 0)) {
- LOG.info("Purging " + destStr + " at usage " + harUsedPercent);
- boolean done = destFs.delete(destPath, true);
- if (!done) {
- LOG.error("Unable to purge directory " + destPath);
- }
- }
- } catch (IOException e) {
- LOG.warn("Error during purging " + destStr + " " +
- StringUtils.stringifyException(e));
- }
- return;
- }
-
- // Verify the destPrefix is a prefix of the destPath
- if (!destStr.startsWith(destPrefix)) {
- LOG.error("Destination path " + destStr + " should have " +
- destPrefix + " as its prefix.");
- return;
- }
-
- if (dest.isDirectory()) {
- FileStatus[] files = null;
- files = destFs.listStatus(destPath);
- if (files == null || files.length == 0){
- boolean done = destFs.delete(destPath,true); // ideal is false, but
- // DFSClient only deletes directories if it is recursive
- if (done) {
- LOG.info("Purged directory " + destPath );
- }
- else {
- LOG.error("Unable to purge directory " + destPath);
- }
- }
- if (files != null) {
- for (FileStatus one:files) {
- recursePurge(code, srcFs, destFs, destPrefix, one);
- }
- }
- // If the directory is empty now, it will be purged the next time this
- // thread runs.
- return; // the code below does the file checking
- }
-
- String src = destStr.replaceFirst(destPrefix, "");
-
- Path srcPath = new Path(src);
- boolean shouldDelete = false;
-
- if (!srcFs.exists(srcPath)) {
- shouldDelete = true;
- } else {
- try {
- // If there is a RS parity file, the XOR parity can be deleted.
- if (code == ErasureCodeType.XOR) {
- ParityFilePair ppair = getParityFile(
- getDestinationPath(ErasureCodeType.RS, conf), srcPath, conf);
- if (ppair != null) {
- shouldDelete = true;
- }
- }
- if (!shouldDelete) {
- Path dstPath = (new Path(destPrefix.trim())).makeQualified(destFs);
- ParityFilePair ppair = getParityFile(dstPath,srcPath);
- // If the parity file is not the appropriate one for the source or
- // the parityFs is not the same as this file's filesystem
- // (it is a HAR), this file can be deleted.
- if ( ppair == null ||
- !destFs.equals(ppair.getFileSystem()) ||
- !destPath.equals(ppair.getPath())) {
- shouldDelete = true;
- }
- }
- } catch (IOException e) {
- LOG.warn("Error during purging " + src + " " +
- StringUtils.stringifyException(e));
- }
- }
-
- if (shouldDelete) {
- boolean done = destFs.delete(destPath, false);
- if (done) {
- LOG.info("Purged file " + destPath );
- } else {
- LOG.error("Unable to purge file " + destPath );
- }
- }
- }
- }
-
- //
- // Returns the number of up-to-date files in the har as a percentage of the
- // total number of files in the har.
- //
- protected static int usefulHar(
- ErasureCodeType code,
- FileSystem srcFs, FileSystem destFs,
- Path harPath, String destPrefix, Configuration conf) throws IOException {
-
- FileSystem fsHar = new HarFileSystem(destFs);
- String harURIPath = harPath.toUri().getPath();
- Path qualifiedPath = new Path("har://", harURIPath +
- Path.SEPARATOR + harPath.getParent().toUri().getPath());
- fsHar.initialize(qualifiedPath.toUri(), conf);
- FileStatus[] filesInHar = fsHar.listStatus(qualifiedPath);
- if (filesInHar.length == 0) {
- return 0;
- }
- int numUseless = 0;
- for (FileStatus one: filesInHar) {
- Path parityPath = one.getPath();
- String parityStr = parityPath.toUri().getPath();
- if (parityStr.startsWith("har:/")) {
- LOG.error("Unexpected prefix har:/ for " + parityStr);
- continue;
- }
- String prefixToReplace = harURIPath + destPrefix;
- if (!parityStr.startsWith(prefixToReplace)) {
- continue;
- }
- String src = parityStr.substring(prefixToReplace.length());
- if (code == ErasureCodeType.XOR) {
- ParityFilePair ppair = getParityFile(
- getDestinationPath(ErasureCodeType.RS, conf), new Path(src), conf);
- if (ppair != null) {
- // There is a valid RS parity file, so the XOR one is useless.
- numUseless++;
- continue;
- }
- }
- try {
- FileStatus srcStatus = srcFs.getFileStatus(new Path(src));
- if (srcStatus == null) {
- numUseless++;
- } else if (one.getModificationTime() !=
- srcStatus.getModificationTime()) {
- numUseless++;
- }
- } catch (FileNotFoundException e) {
- LOG.info("File not found: " + e);
- numUseless++;
- }
- }
- int uselessPercent = numUseless * 100 / filesInHar.length;
- return 100 - uselessPercent;
- }
-
- private void doHar() throws IOException, InterruptedException {
- long prevExec = 0;
- while (running) {
-
- // The config may be reloaded by the TriggerMonitor.
- // This thread uses whatever config is currently active.
- while(now() < prevExec + configMgr.getPeriodicity()){
- Thread.sleep(SLEEP_TIME);
- }
-
- LOG.info("Started archive scan");
- prevExec = now();
-
- // fetch all categories
- for (PolicyList category : configMgr.getAllPolicies()) {
- for (PolicyInfo info: category.getAll()) {
- String tmpHarPath = tmpHarPathForCode(conf, info.getErasureCode());
- String str = info.getProperty("time_before_har");
- if (str != null) {
- try {
- long cutoff = now() - ( Long.parseLong(str) * 24L * 3600000L );
-
- Path destPref = getDestinationPath(info.getErasureCode(), conf);
- FileSystem destFs = destPref.getFileSystem(conf);
-
- //get srcPaths
- Path[] srcPaths = info.getSrcPathExpanded();
-
- if ( srcPaths != null ){
- for (Path srcPath: srcPaths) {
- // expand destination prefix
- Path destPath = getOriginalParityFile(destPref, srcPath);
-
- FileStatus stat = null;
- try {
- stat = destFs.getFileStatus(destPath);
- } catch (FileNotFoundException e) {
- // do nothing, leave stat = null;
- }
- if (stat != null) {
- LOG.info("Haring parity files for policy " +
- info.getName() + " " + destPath);
- recurseHar(info, destFs, stat, destPref.toUri().getPath(),
- srcPath.getFileSystem(conf), cutoff, tmpHarPath);
- }
- }
- }
- } catch (Exception e) {
- LOG.warn("Ignoring Exception while processing policy " +
- info.getName() + " " +
- StringUtils.stringifyException(e));
- }
- }
- }
- }
- }
- return;
- }
-
- void recurseHar(PolicyInfo info, FileSystem destFs, FileStatus dest,
- String destPrefix, FileSystem srcFs, long cutoff, String tmpHarPath)
- throws IOException {
-
- if (dest.isFile()) {
- return;
- }
-
- Path destPath = dest.getPath(); // pathname, no host:port
- String destStr = destPath.toUri().getPath();
-
- // Verify if it already contains a HAR directory
- if ( destFs.exists(new Path(destPath, destPath.getName()+HAR_SUFFIX)) ) {
- return;
- }
-
- FileStatus[] files = null;
- files = destFs.listStatus(destPath);
- boolean shouldHar = false;
- if (files != null) {
- shouldHar = files.length > 0;
- for (FileStatus one: files) {
- if (one.isDirectory()){
- recurseHar(info, destFs, one, destPrefix, srcFs, cutoff, tmpHarPath);
- shouldHar = false;
- } else if (one.getModificationTime() > cutoff ) {
- if (shouldHar) {
- LOG.info("Cannot archive " + destPath +
- " because " + one.getPath() + " was modified after cutoff");
- shouldHar = false;
- }
- }
- }
-
- if (shouldHar) {
- String src = destStr.replaceFirst(destPrefix, "");
- Path srcPath = new Path(src);
- FileStatus[] statuses = srcFs.listStatus(srcPath);
- Path destPathPrefix = new Path(destPrefix).makeQualified(destFs);
- if (statuses != null) {
- for (FileStatus status : statuses) {
- if (getParityFile(destPathPrefix,
- status.getPath().makeQualified(srcFs)) == null ) {
- LOG.info("Cannot archive " + destPath +
- " because it doesn't contain parity file for " +
- status.getPath().makeQualified(srcFs) + " on destination " +
- destPathPrefix);
- shouldHar = false;
- break;
- }
- }
- }
- }
- }
-
- if ( shouldHar ) {
- LOG.info("Archiving " + dest.getPath() + " to " + tmpHarPath );
- singleHar(info, destFs, dest, tmpHarPath);
- }
- }
-
-
- private void singleHar(PolicyInfo info, FileSystem destFs, FileStatus dest,
- String tmpHarPath) throws IOException {
-
- Random rand = new Random();
- Path root = new Path("/");
- Path qualifiedPath = dest.getPath().makeQualified(destFs);
- String harFileDst = qualifiedPath.getName() + HAR_SUFFIX;
- String harFileSrc = qualifiedPath.getName() + "-" +
- rand.nextLong() + "-" + HAR_SUFFIX;
- short metaReplication =
- (short) Integer.parseInt(info.getProperty("metaReplication"));
- // HadoopArchives.HAR_PARTFILE_LABEL is private, so hard-coding the label.
- conf.setLong("har.partfile.size", configMgr.getHarPartfileSize());
- HadoopArchives har = new HadoopArchives(conf);
- String[] args = new String[7];
- args[0] = "-Ddfs.replication=" + metaReplication;
- args[1] = "-archiveName";
- args[2] = harFileSrc;
- args[3] = "-p";
- args[4] = root.makeQualified(destFs).toString();
- args[5] = qualifiedPath.toUri().getPath().substring(1);
- args[6] = tmpHarPath.toString();
- int ret = 0;
- try {
- ret = ToolRunner.run(har, args);
- if (ret == 0 && !destFs.rename(new Path(tmpHarPath+"/"+harFileSrc),
- new Path(qualifiedPath, harFileDst))) {
- LOG.error("HAR rename didn't succeed from " + tmpHarPath+"/"+harFileSrc +
- " to " + qualifiedPath + "/" + harFileDst);
- ret = -2;
- }
- } catch (Exception exc) {
- throw new IOException("Error while creating archive " + ret, exc);
- }
-
- if (ret != 0){
- throw new IOException("Error while creating archive " + ret);
- }
- return;
- }
-
- /**
- * Periodically generates HAR files
- */
- class HarMonitor implements Runnable {
-
- public void run() {
- while (running) {
- try {
- doHar();
- } catch (Exception e) {
- LOG.error(StringUtils.stringifyException(e));
- } finally {
- LOG.info("Har parity files thread continuing to run...");
- }
- }
- LOG.info("Leaving Har thread.");
- }
-
- }
-
- /**
- * Return the temp path for XOR parity files
- */
- public static String unraidTmpDirectory(Configuration conf) {
- return conf.get(RAID_TMP_LOCATION_KEY, DEFAULT_RAID_TMP_LOCATION);
- }
-
- /**
- * Return the temp path for ReedSolomonEncoder parity files
- */
- public static String rsTempPrefix(Configuration conf) {
- return conf.get(RAIDRS_TMP_LOCATION_KEY, DEFAULT_RAIDRS_TMP_LOCATION);
- }
-
- /**
- * Return the temp path for XOR parity files
- */
- public static String xorTempPrefix(Configuration conf) {
- return conf.get(RAID_TMP_LOCATION_KEY, DEFAULT_RAID_TMP_LOCATION);
- }
-
- /**
- * Return the temp path for XOR parity files
- */
- public static String xorHarTempPrefix(Configuration conf) {
- return conf.get(RAID_HAR_TMP_LOCATION_KEY, DEFAULT_RAID_HAR_TMP_LOCATION);
- }
-
- /**
- * Return the temp path for ReedSolomonEncoder parity files
- */
- public static String rsHarTempPrefix(Configuration conf) {
- return conf.get(RAIDRS_HAR_TMP_LOCATION_KEY,
- DEFAULT_RAIDRS_HAR_TMP_LOCATION);
- }
-
- /**
- * Return the destination path for ReedSolomon parity files
- */
- public static Path rsDestinationPath(Configuration conf, FileSystem fs) {
- String loc = conf.get(RAIDRS_LOCATION_KEY, DEFAULT_RAIDRS_LOCATION);
- Path p = new Path(loc.trim());
- p = p.makeQualified(fs);
- return p;
- }
-
- /**
- * Return the destination path for ReedSolomon parity files
- */
- public static Path rsDestinationPath(Configuration conf)
- throws IOException {
- String loc = conf.get(RAIDRS_LOCATION_KEY, DEFAULT_RAIDRS_LOCATION);
- Path p = new Path(loc.trim());
- FileSystem fs = FileSystem.get(p.toUri(), conf);
- p = p.makeQualified(fs);
- return p;
- }
-
- /**
- * Return the destination path for XOR parity files
- */
- public static Path xorDestinationPath(Configuration conf, FileSystem fs) {
- String loc = conf.get(RAID_LOCATION_KEY, DEFAULT_RAID_LOCATION);
- Path p = new Path(loc.trim());
- p = p.makeQualified(fs);
- return p;
- }
-
- /**
- * Return the destination path for XOR parity files
- */
- public static Path xorDestinationPath(Configuration conf)
- throws IOException {
- String loc = conf.get(RAID_LOCATION_KEY, DEFAULT_RAID_LOCATION);
- Path p = new Path(loc.trim());
- FileSystem fs = FileSystem.get(p.toUri(), conf);
- p = p.makeQualified(fs);
- return p;
- }
-
- /**
- * Return the path prefix that stores the parity files
- */
- static Path getDestinationPath(ErasureCodeType code, Configuration conf)
- throws IOException {
- switch (code) {
- case XOR:
- return xorDestinationPath(conf);
- case RS:
- return rsDestinationPath(conf);
- default:
- return null;
- }
- }
-
- static Encoder encoderForCode(Configuration conf, ErasureCodeType code) {
- int stripeLength = getStripeLength(conf);
- switch (code) {
- case XOR:
- return new XOREncoder(conf, stripeLength);
- case RS:
- return new ReedSolomonEncoder(conf, stripeLength, rsParityLength(conf));
- default:
- return null;
- }
- }
-
- static String tmpHarPathForCode(Configuration conf, ErasureCodeType code) {
- switch (code) {
- case XOR:
- return xorHarTempPrefix(conf);
- case RS:
- return rsHarTempPrefix(conf);
- default:
- return null;
- }
- }
-
- /**
- * Obtain stripe length from configuration
- */
- public static int getStripeLength(Configuration conf) {
- return conf.getInt(STRIPE_LENGTH_KEY, DEFAULT_STRIPE_LENGTH);
- }
-
- /**
- * Obtain stripe length from configuration
- */
- public static int rsParityLength(Configuration conf) {
- return conf.getInt(RS_PARITY_LENGTH_KEY, RS_PARITY_LENGTH_DEFAULT);
- }
-
- static boolean isParityHarPartFile(Path p) {
- Matcher m = PARITY_HAR_PARTFILE_PATTERN.matcher(p.toUri().getPath());
- return m.matches();
- }
-
- /**
- * Returns current time.
- */
- static long now() {
- return Time.now();
- }
-
- /**
- * Make an absolute path relative by stripping the leading /
- */
- static private Path makeRelative(Path path) {
- if (!path.isAbsolute()) {
- return path;
- }
- String p = path.toUri().getPath();
- String relative = p.substring(1, p.length());
- return new Path(relative);
- }
-
- private static void printUsage() {
- System.err.println("Usage: java RaidNode ");
- }
-
- private static StartupOption parseArguments(String args[]) {
- int argsLen = (args == null) ? 0 : args.length;
- StartupOption startOpt = StartupOption.REGULAR;
- for(int i=0; i < argsLen; i++) {
- String cmd = args[i]; // We have to parse command line args in future.
- }
- return startOpt;
- }
-
-
- /**
- * Convert command line options to configuration parameters
- */
- private static void setStartupOption(Configuration conf, StartupOption opt) {
- conf.set("fs.raidnode.startup", opt.toString());
- }
-
- /**
- * Create an instance of the appropriate subclass of RaidNode
- */
- public static RaidNode createRaidNode(Configuration conf)
- throws ClassNotFoundException {
- try {
- // default to distributed raid node
- Class> raidNodeClass =
- conf.getClass(RAIDNODE_CLASSNAME_KEY, DistRaidNode.class);
- if (!RaidNode.class.isAssignableFrom(raidNodeClass)) {
- throw new ClassNotFoundException("not an implementation of RaidNode");
- }
- Constructor> constructor =
- raidNodeClass.getConstructor(new Class[] {Configuration.class} );
- return (RaidNode) constructor.newInstance(conf);
- } catch (NoSuchMethodException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- } catch (InstantiationException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- } catch (IllegalAccessException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- } catch (InvocationTargetException e) {
- throw new ClassNotFoundException("cannot construct blockfixer", e);
- }
- }
-
- /**
- * Create an instance of the RaidNode
- */
- public static RaidNode createRaidNode(String argv[], Configuration conf)
- throws IOException, ClassNotFoundException {
- if (conf == null) {
- conf = new Configuration();
- }
- StartupOption startOpt = parseArguments(argv);
- if (startOpt == null) {
- printUsage();
- return null;
- }
- setStartupOption(conf, startOpt);
- RaidNode node = createRaidNode(conf);
- return node;
- }
-
-
- /**
- */
- public static void main(String argv[]) throws Exception {
- try {
- StringUtils.startupShutdownMessage(RaidNode.class, argv, LOG);
- RaidNode raid = createRaidNode(argv, null);
- if (raid != null) {
- raid.join();
- }
- } catch (Throwable e) {
- LOG.error(StringUtils.stringifyException(e));
- System.exit(-1);
- }
- }
-
-
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidShell.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidShell.java
deleted file mode 100644
index 625a6a8eefe..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidShell.java
+++ /dev/null
@@ -1,682 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.IOException;
-import java.io.FileNotFoundException;
-import java.util.Collection;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.LinkedHashMap;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.net.InetSocketAddress;
-import javax.security.auth.login.LoginException;
-
-import org.apache.hadoop.ipc.*;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.net.NetUtils;
-import org.apache.hadoop.conf.Configured;
-import org.apache.hadoop.util.Tool;
-import org.apache.hadoop.util.ToolRunner;
-import org.apache.hadoop.util.Time;
-import org.apache.hadoop.io.retry.RetryPolicy;
-import org.apache.hadoop.io.retry.RetryPolicies;
-import org.apache.hadoop.io.retry.RetryProxy;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.fs.FileUtil;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.BlockLocation;
-import org.apache.hadoop.fs.HarFileSystem;
-
-import org.apache.hadoop.hdfs.DistributedFileSystem;
-import org.apache.hadoop.hdfs.DistributedRaidFileSystem;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.raid.protocol.PolicyList;
-import org.apache.hadoop.raid.protocol.RaidProtocol;
-
-/**
- * A {@link RaidShell} that allows browsing configured raid policies.
- */
-public class RaidShell extends Configured implements Tool {
- static {
- Configuration.addDefaultResource("hdfs-default.xml");
- Configuration.addDefaultResource("hdfs-site.xml");
- }
- public static final Log LOG = LogFactory.getLog( "org.apache.hadoop.RaidShell");
- public RaidProtocol raidnode;
- RaidProtocol rpcRaidnode;
- private UserGroupInformation ugi;
- volatile boolean clientRunning = true;
- private Configuration conf;
-
- /**
- * Start RaidShell.
- *
- * The RaidShell connects to the specified RaidNode and performs basic
- * configuration options.
- * @throws IOException
- */
- public RaidShell(Configuration conf) throws IOException {
- super(conf);
- this.conf = conf;
- }
-
- void initializeRpc(Configuration conf, InetSocketAddress address) throws IOException {
- this.ugi = UserGroupInformation.getCurrentUser();
- this.rpcRaidnode = createRPCRaidnode(address, conf, ugi);
- this.raidnode = createRaidnode(rpcRaidnode);
- }
-
- void initializeLocal(Configuration conf) throws IOException {
- this.ugi = UserGroupInformation.getCurrentUser();
- }
-
- public static RaidProtocol createRaidnode(Configuration conf) throws IOException {
- return createRaidnode(RaidNode.getAddress(conf), conf);
- }
-
- public static RaidProtocol createRaidnode(InetSocketAddress raidNodeAddr,
- Configuration conf) throws IOException {
- return createRaidnode(createRPCRaidnode(raidNodeAddr, conf,
- UserGroupInformation.getCurrentUser()));
- }
-
- private static RaidProtocol createRPCRaidnode(InetSocketAddress raidNodeAddr,
- Configuration conf, UserGroupInformation ugi)
- throws IOException {
- LOG.debug("RaidShell connecting to " + raidNodeAddr);
- return (RaidProtocol)RPC.getProxy(RaidProtocol.class,
- RaidProtocol.versionID, raidNodeAddr, ugi, conf,
- NetUtils.getSocketFactory(conf, RaidProtocol.class));
- }
-
- private static RaidProtocol createRaidnode(RaidProtocol rpcRaidnode)
- throws IOException {
- RetryPolicy createPolicy = RetryPolicies.retryUpToMaximumCountWithFixedSleep(
- 5, 5000, TimeUnit.MILLISECONDS);
-
- Map,RetryPolicy> remoteExceptionToPolicyMap =
- new HashMap, RetryPolicy>();
-
- Map,RetryPolicy> exceptionToPolicyMap =
- new HashMap, RetryPolicy>();
- exceptionToPolicyMap.put(RemoteException.class,
- RetryPolicies.retryByRemoteException(
- RetryPolicies.TRY_ONCE_THEN_FAIL, remoteExceptionToPolicyMap));
- RetryPolicy methodPolicy = RetryPolicies.retryByException(
- RetryPolicies.TRY_ONCE_THEN_FAIL, exceptionToPolicyMap);
- Map methodNameToPolicyMap = new HashMap();
-
- methodNameToPolicyMap.put("create", methodPolicy);
-
- return (RaidProtocol) RetryProxy.create(RaidProtocol.class,
- rpcRaidnode, methodNameToPolicyMap);
- }
-
- private void checkOpen() throws IOException {
- if (!clientRunning) {
- IOException result = new IOException("RaidNode closed");
- throw result;
- }
- }
-
- /**
- * Close the connection to the raidNode.
- */
- public synchronized void close() throws IOException {
- if(clientRunning) {
- clientRunning = false;
- RPC.stopProxy(rpcRaidnode);
- }
- }
-
- /**
- * Displays format of commands.
- */
- private static void printUsage(String cmd) {
- String prefix = "Usage: java " + RaidShell.class.getSimpleName();
- if ("-showConfig".equals(cmd)) {
- System.err.println("Usage: java RaidShell" +
- " [-showConfig]");
- } else if ("-recover".equals(cmd)) {
- System.err.println("Usage: java RaidShell" +
- " [-recover srcPath1 corruptOffset]");
- } else if ("-recoverBlocks".equals(cmd)) {
- System.err.println("Usage: java RaidShell" +
- " [-recoverBlocks path1 path2...]");
- } else {
- System.err.println("Usage: java RaidShell");
- System.err.println(" [-showConfig ]");
- System.err.println(" [-help [cmd]]");
- System.err.println(" [-recover srcPath1 corruptOffset]");
- System.err.println(" [-recoverBlocks path1 path2...]");
- System.err.println(" [-fsck [path]]");
- System.err.println();
- ToolRunner.printGenericCommandUsage(System.err);
- }
- }
-
- /**
- * run
- */
- public int run(String argv[]) throws Exception {
-
- if (argv.length < 1) {
- printUsage("");
- return -1;
- }
-
- int exitCode = -1;
- int i = 0;
- String cmd = argv[i++];
- //
- // verify that we have enough command line parameters
- //
- if ("-showConfig".equals(cmd)) {
- if (argv.length < 1) {
- printUsage(cmd);
- return exitCode;
- }
- } else if ("-recover".equals(cmd)) {
- if (argv.length < 3) {
- printUsage(cmd);
- return exitCode;
- }
- } else if ("-fsck".equals(cmd)) {
- if ((argv.length < 1) || (argv.length > 2)) {
- printUsage(cmd);
- return exitCode;
- }
- }
-
- try {
- if ("-showConfig".equals(cmd)) {
- initializeRpc(conf, RaidNode.getAddress(conf));
- exitCode = showConfig(cmd, argv, i);
- } else if ("-recover".equals(cmd)) {
- initializeRpc(conf, RaidNode.getAddress(conf));
- exitCode = recoverAndPrint(cmd, argv, i);
- } else if ("-recoverBlocks".equals(cmd)) {
- initializeLocal(conf);
- recoverBlocks(argv, i);
- exitCode = 0;
- } else if ("-fsck".equals(cmd)) {
- if (argv.length == 1) {
- // if there are no args, check the whole file system
- exitCode = fsck("/");
- } else {
- // argv.length == 2
- // otherwise, check the path passed
- exitCode = fsck(argv[1]);
- }
- } else {
- exitCode = -1;
- System.err.println(cmd.substring(1) + ": Unknown command");
- printUsage("");
- }
- } catch (IllegalArgumentException arge) {
- exitCode = -1;
- System.err.println(cmd.substring(1) + ": " + arge.getLocalizedMessage());
- printUsage(cmd);
- } catch (RemoteException e) {
- //
- // This is a error returned by raidnode server. Print
- // out the first line of the error mesage, ignore the stack trace.
- exitCode = -1;
- try {
- String[] content;
- content = e.getLocalizedMessage().split("\n");
- System.err.println(cmd.substring(1) + ": " +
- content[0]);
- } catch (Exception ex) {
- System.err.println(cmd.substring(1) + ": " +
- ex.getLocalizedMessage());
- }
- } catch (IOException e) {
- //
- // IO exception encountered locally.
- //
- exitCode = -1;
- System.err.println(cmd.substring(1) + ": " +
- e.getLocalizedMessage());
- } catch (Exception re) {
- exitCode = -1;
- System.err.println(cmd.substring(1) + ": " + re.getLocalizedMessage());
- } finally {
- }
- return exitCode;
- }
-
- /**
- * Apply operation specified by 'cmd' on all parameters
- * starting from argv[startindex].
- */
- private int showConfig(String cmd, String argv[], int startindex) throws IOException {
- int exitCode = 0;
- int i = startindex;
- PolicyList[] all = raidnode.getAllPolicies();
- for (PolicyList list: all) {
- for (PolicyInfo p : list.getAll()) {
- System.out.println(p);
- }
- }
- return exitCode;
- }
-
- /**
- * Recovers the specified path from the parity file
- */
- public Path[] recover(String cmd, String argv[], int startindex)
- throws IOException {
- Path[] paths = new Path[(argv.length - startindex) / 2];
- int j = 0;
- for (int i = startindex; i < argv.length; i = i + 2) {
- String path = argv[i];
- long corruptOffset = Long.parseLong(argv[i+1]);
- LOG.info("RaidShell recoverFile for " + path + " corruptOffset " + corruptOffset);
- Path recovered = new Path("/tmp/recovered." + Time.now());
- FileSystem fs = recovered.getFileSystem(conf);
- DistributedFileSystem dfs = (DistributedFileSystem)fs;
- Configuration raidConf = new Configuration(conf);
- raidConf.set("fs.hdfs.impl",
- "org.apache.hadoop.hdfs.DistributedRaidFileSystem");
- raidConf.set("fs.raid.underlyingfs.impl",
- "org.apache.hadoop.hdfs.DistributedFileSystem");
- raidConf.setBoolean("fs.hdfs.impl.disable.cache", true);
- java.net.URI dfsUri = dfs.getUri();
- FileSystem raidFs = FileSystem.get(dfsUri, raidConf);
- FileUtil.copy(raidFs, new Path(path), fs, recovered, false, conf);
-
- paths[j] = recovered;
- LOG.info("Raidshell created recovery file " + paths[j]);
- j++;
- }
- return paths;
- }
-
- public int recoverAndPrint(String cmd, String argv[], int startindex)
- throws IOException {
- int exitCode = 0;
- for (Path p : recover(cmd,argv,startindex)) {
- System.out.println(p);
- }
- return exitCode;
- }
-
- public void recoverBlocks(String[] args, int startIndex)
- throws IOException {
- LOG.debug("Recovering blocks for " + (args.length - startIndex) + " files");
- BlockFixer.BlockFixerHelper fixer = new BlockFixer.BlockFixerHelper(conf);
- for (int i = startIndex; i < args.length; i++) {
- String path = args[i];
- fixer.fixFile(new Path(path));
- }
- }
-
- /**
- * checks whether a file has more than the allowable number of
- * corrupt blocks and must therefore be considered corrupt
- */
- private boolean isFileCorrupt(final DistributedFileSystem dfs,
- final Path filePath)
- throws IOException {
- // corruptBlocksPerStripe:
- // map stripe # -> # of corrupt blocks in that stripe (data + parity)
- HashMap corruptBlocksPerStripe =
- new LinkedHashMap();
-
- // read conf
- final int stripeBlocks = RaidNode.getStripeLength(conf);
-
- // figure out which blocks are missing/corrupted
- final FileStatus fileStatus = dfs.getFileStatus(filePath);
- final long blockSize = fileStatus.getBlockSize();
- final long fileLength = fileStatus.getLen();
- final long fileLengthInBlocks = (fileLength / blockSize) +
- (((fileLength % blockSize) == 0) ? 0L : 1L);
- final long fileStripes = (fileLengthInBlocks / stripeBlocks) +
- (((fileLengthInBlocks % stripeBlocks) == 0) ? 0L : 1L);
- final BlockLocation[] fileBlocks =
- dfs.getFileBlockLocations(fileStatus, 0, fileLength);
-
- // figure out which stripes these corrupted blocks belong to
- for (BlockLocation fileBlock: fileBlocks) {
- int blockNo = (int) (fileBlock.getOffset() / blockSize);
- final int stripe = (int) (blockNo / stripeBlocks);
- if (fileBlock.isCorrupt() ||
- (fileBlock.getNames().length == 0 && fileBlock.getLength() > 0)) {
- if (corruptBlocksPerStripe.get(stripe) == null) {
- corruptBlocksPerStripe.put(stripe, 1);
- } else {
- corruptBlocksPerStripe.put(stripe, corruptBlocksPerStripe.
- get(stripe) + 1);
- }
- LOG.debug("file " + filePath.toString() + " corrupt in block " +
- blockNo + "/" + fileLengthInBlocks + ", stripe " + stripe +
- "/" + fileStripes);
- } else {
- LOG.debug("file " + filePath.toString() + " OK in block " + blockNo +
- "/" + fileLengthInBlocks + ", stripe " + stripe + "/" +
- fileStripes);
- }
- }
-
- RaidInfo raidInfo = getFileRaidInfo(dfs, filePath);
-
- // now check parity blocks
- if (raidInfo.raidType != RaidType.NONE) {
- checkParityBlocks(filePath, corruptBlocksPerStripe, blockSize,
- fileStripes, raidInfo);
- }
-
- final int maxCorruptBlocksPerStripe = raidInfo.parityBlocksPerStripe;
-
- for (int corruptBlocksInStripe: corruptBlocksPerStripe.values()) {
- if (corruptBlocksInStripe > maxCorruptBlocksPerStripe) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * holds the type of raid used for a particular file
- */
- private enum RaidType {
- XOR,
- RS,
- NONE
- }
-
- /**
- * holds raid type and parity file pair
- */
- private class RaidInfo {
- public RaidInfo(final RaidType raidType,
- final RaidNode.ParityFilePair parityPair,
- final int parityBlocksPerStripe) {
- this.raidType = raidType;
- this.parityPair = parityPair;
- this.parityBlocksPerStripe = parityBlocksPerStripe;
- }
- public final RaidType raidType;
- public final RaidNode.ParityFilePair parityPair;
- public final int parityBlocksPerStripe;
- }
-
- /**
- * returns the raid for a given file
- */
- private RaidInfo getFileRaidInfo(final DistributedFileSystem dfs,
- final Path filePath)
- throws IOException {
- // now look for the parity file
- Path destPath = null;
- RaidNode.ParityFilePair ppair = null;
- try {
- // look for xor parity file first
- destPath = RaidNode.xorDestinationPath(conf);
- ppair = RaidNode.getParityFile(destPath, filePath, conf);
- } catch (FileNotFoundException ignore) {
- }
- if (ppair != null) {
- return new RaidInfo(RaidType.XOR, ppair, 1);
- } else {
- // failing that, look for rs parity file
- try {
- destPath = RaidNode.rsDestinationPath(conf);
- ppair = RaidNode.getParityFile(destPath, filePath, conf);
- } catch (FileNotFoundException ignore) {
- }
- if (ppair != null) {
- return new RaidInfo(RaidType.RS, ppair, RaidNode.rsParityLength(conf));
- } else {
- return new RaidInfo(RaidType.NONE, null, 0);
- }
- }
- }
-
- /**
- * gets the parity blocks corresponding to file
- * returns the parity blocks in case of DFS
- * and the part blocks containing parity blocks
- * in case of HAR FS
- */
- private BlockLocation[] getParityBlocks(final Path filePath,
- final long blockSize,
- final long fileStripes,
- final RaidInfo raidInfo)
- throws IOException {
-
-
- final String parityPathStr = raidInfo.parityPair.getPath().toUri().
- getPath();
- FileSystem parityFS = raidInfo.parityPair.getFileSystem();
-
- // get parity file metadata
- FileStatus parityFileStatus = parityFS.
- getFileStatus(new Path(parityPathStr));
- long parityFileLength = parityFileStatus.getLen();
-
- if (parityFileLength != fileStripes * raidInfo.parityBlocksPerStripe *
- blockSize) {
- throw new IOException("expected parity file of length" +
- (fileStripes * raidInfo.parityBlocksPerStripe *
- blockSize) +
- " but got parity file of length " +
- parityFileLength);
- }
-
- BlockLocation[] parityBlocks =
- parityFS.getFileBlockLocations(parityFileStatus, 0L, parityFileLength);
-
- if (parityFS instanceof DistributedFileSystem ||
- parityFS instanceof DistributedRaidFileSystem) {
- long parityBlockSize = parityFileStatus.getBlockSize();
- if (parityBlockSize != blockSize) {
- throw new IOException("file block size is " + blockSize +
- " but parity file block size is " +
- parityBlockSize);
- }
- } else if (parityFS instanceof HarFileSystem) {
- LOG.debug("HAR FS found");
- } else {
- LOG.warn("parity file system is not of a supported type");
- }
-
- return parityBlocks;
- }
-
- /**
- * checks the parity blocks for a given file and modifies
- * corruptBlocksPerStripe accordingly
- */
- private void checkParityBlocks(final Path filePath,
- final HashMap
- corruptBlocksPerStripe,
- final long blockSize,
- final long fileStripes,
- final RaidInfo raidInfo)
- throws IOException {
-
- // get the blocks of the parity file
- // because of har, multiple blocks may be returned as one container block
- BlockLocation[] containerBlocks = getParityBlocks(filePath, blockSize,
- fileStripes, raidInfo);
-
- long parityStripeLength = blockSize *
- ((long) raidInfo.parityBlocksPerStripe);
-
- long parityFileLength = parityStripeLength * fileStripes;
-
- long parityBlocksFound = 0L;
-
- for (BlockLocation cb: containerBlocks) {
- if (cb.getLength() % blockSize != 0) {
- throw new IOException("container block size is not " +
- "multiple of parity block size");
- }
- int blocksInContainer = (int) (cb.getLength() / blockSize);
- LOG.debug("found container with offset " + cb.getOffset() +
- ", length " + cb.getLength());
-
- for (long offset = cb.getOffset();
- offset < cb.getOffset() + cb.getLength();
- offset += blockSize) {
- long block = offset / blockSize;
-
- int stripe = (int) (offset / parityStripeLength);
-
- if (stripe < 0) {
- // before the beginning of the parity file
- continue;
- }
- if (stripe >= fileStripes) {
- // past the end of the parity file
- break;
- }
-
- parityBlocksFound++;
-
- if (cb.isCorrupt() ||
- (cb.getNames().length == 0 && cb.getLength() > 0)) {
- LOG.debug("parity file for " + filePath.toString() +
- " corrupt in block " + block +
- ", stripe " + stripe + "/" + fileStripes);
-
- if (corruptBlocksPerStripe.get(stripe) == null) {
- corruptBlocksPerStripe.put(stripe, 1);
- } else {
- corruptBlocksPerStripe.put(stripe,
- corruptBlocksPerStripe.get(stripe) +
- 1);
- }
- } else {
- LOG.debug("parity file for " + filePath.toString() +
- " OK in block " + block +
- ", stripe " + stripe + "/" + fileStripes);
- }
- }
- }
-
- long parityBlocksExpected = raidInfo.parityBlocksPerStripe * fileStripes;
- if (parityBlocksFound != parityBlocksExpected ) {
- throw new IOException("expected " + parityBlocksExpected +
- " parity blocks but got " + parityBlocksFound);
- }
- }
-
-
- /**
- * checks the raided file system, prints a list of corrupt files to
- * System.out and returns the number of corrupt files
- */
- public int fsck(final String path) throws IOException {
-
- FileSystem fs = (new Path(path)).getFileSystem(conf);
-
- // if we got a raid fs, get the underlying fs
- if (fs instanceof DistributedRaidFileSystem) {
- fs = ((DistributedRaidFileSystem) fs).getFileSystem();
- }
-
- // check that we have a distributed fs
- if (!(fs instanceof DistributedFileSystem)) {
- throw new IOException("expected DistributedFileSystem but got " +
- fs.getClass().getName());
- }
- final DistributedFileSystem dfs = (DistributedFileSystem) fs;
-
- // get conf settings
- String xorPrefix = RaidNode.xorDestinationPath(conf).toUri().getPath();
- String rsPrefix = RaidNode.rsDestinationPath(conf).toUri().getPath();
- if (!xorPrefix.endsWith("/")) {
- xorPrefix = xorPrefix + "/";
- }
- if (!rsPrefix.endsWith("/")) {
- rsPrefix = rsPrefix + "/";
- }
- LOG.debug("prefixes: " + xorPrefix + ", " + rsPrefix);
-
- // get a list of corrupted files (not considering parity blocks just yet)
- // from the name node
- // these are the only files we need to consider:
- // if a file has no corrupted data blocks, it is OK even if some
- // of its parity blocks are corrupted, so no further checking is
- // necessary
- final String[] files = RaidDFSUtil.getCorruptFiles(dfs);
- final List corruptFileCandidates = new LinkedList();
- for (final String f: files) {
- final Path p = new Path(f);
- // if this file is a parity file
- // or if it does not start with the specified path,
- // ignore it
- if (!p.toString().startsWith(xorPrefix) &&
- !p.toString().startsWith(rsPrefix) &&
- p.toString().startsWith(path)) {
- corruptFileCandidates.add(p);
- }
- }
- // filter files marked for deletion
- RaidUtils.filterTrash(conf, corruptFileCandidates);
-
- int numberOfCorruptFiles = 0;
-
- for (final Path corruptFileCandidate: corruptFileCandidates) {
- if (isFileCorrupt(dfs, corruptFileCandidate)) {
- System.out.println(corruptFileCandidate.toString());
- numberOfCorruptFiles++;
- }
- }
-
- return numberOfCorruptFiles;
- }
-
- /**
- * main() has some simple utility methods
- */
- public static void main(String argv[]) throws Exception {
- RaidShell shell = null;
- try {
- shell = new RaidShell(new Configuration());
- int res = ToolRunner.run(shell, argv);
- System.exit(res);
- } catch (RPC.VersionMismatch v) {
- System.err.println("Version Mismatch between client and server" +
- "... command aborted.");
- System.exit(-1);
- } catch (IOException e) {
- System.err.
- println("Bad connection to RaidNode or NameNode. command aborted.");
- System.err.println(e.getMessage());
- System.exit(-1);
- } finally {
- shell.close();
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidUtils.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidUtils.java
deleted file mode 100644
index 7ce0c828039..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/RaidUtils.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.PositionedReadable;
-import org.apache.hadoop.fs.Seekable;
-import org.apache.hadoop.io.IOUtils;
-import org.apache.hadoop.util.Progressable;
-
-public class RaidUtils {
- /**
- * A {@link Progressable} that does nothing.
- *
- * We could have used Reporter.NULL here but that would introduce
- * a dependency on mapreduce.
- */
- public static class DummyProgressable implements Progressable {
- /**
- * Do nothing.
- */
- @Override
- public void progress() {
- }
- }
-
- /**
- * Removes files matching the trash file pattern.
- */
- public static void filterTrash(Configuration conf, List files) {
- // Remove files under Trash.
- String trashPattern = conf.get("raid.blockfixer.trash.pattern",
- "^/user/.*/\\.Trash.*");
- for (Iterator it = files.iterator(); it.hasNext(); ) {
- String pathStr = it.next().toString();
- if (Pattern.matches(trashPattern, pathStr)) {
- it.remove();
- }
- }
- }
-
- public static void readTillEnd(InputStream in, byte[] buf, boolean eofOK)
- throws IOException {
- int toRead = buf.length;
- int numRead = 0;
- while (numRead < toRead) {
- int nread = in.read(buf, numRead, toRead - numRead);
- if (nread < 0) {
- if (eofOK) {
- // EOF hit, fill with zeros
- Arrays.fill(buf, numRead, toRead, (byte)0);
- numRead = toRead;
- } else {
- // EOF hit, throw.
- throw new IOException("Premature EOF");
- }
- } else {
- numRead += nread;
- }
- }
- }
-
- public static void copyBytes(
- InputStream in, OutputStream out, byte[] buf, long count)
- throws IOException {
- for (long bytesRead = 0; bytesRead < count; ) {
- int toRead = Math.min(buf.length, (int)(count - bytesRead));
- IOUtils.readFully(in, buf, 0, toRead);
- bytesRead += toRead;
- out.write(buf, 0, toRead);
- }
- }
-
- public static class ZeroInputStream extends InputStream
- implements Seekable, PositionedReadable {
- private long endOffset;
- private long pos;
-
- public ZeroInputStream(long endOffset) {
- this.endOffset = endOffset;
- this.pos = 0;
- }
-
- @Override
- public int read() throws IOException {
- if (pos < endOffset) {
- pos++;
- return 0;
- }
- return -1;
- }
-
- @Override
- public int available() throws IOException {
- return (int)(endOffset - pos);
- }
-
- @Override
- public long getPos() throws IOException {
- return pos;
- }
-
- @Override
- public void seek(long seekOffset) throws IOException {
- if (seekOffset < endOffset) {
- pos = seekOffset;
- } else {
- throw new IOException("Illegal Offset" + pos);
- }
- }
-
- @Override
- public boolean seekToNewSource(long targetPos) throws IOException {
- return false;
- }
-
- @Override
- public int read(long position, byte[] buffer, int offset, int length)
- throws IOException {
- int count = 0;
- for (; position < endOffset && count < length; position++) {
- buffer[offset + count] = 0;
- count++;
- }
- return count;
- }
-
- @Override
- public void readFully(long position, byte[] buffer, int offset, int length)
- throws IOException {
- int count = 0;
- for (; position < endOffset && count < length; position++) {
- buffer[offset + count] = 0;
- count++;
- }
- if (count < length) {
- throw new IOException("Premature EOF");
- }
- }
-
- @Override
- public void readFully(long position, byte[] buffer) throws IOException {
- readFully(position, buffer, 0, buffer.length);
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonCode.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonCode.java
deleted file mode 100644
index 0a5d91bf4d7..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonCode.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * 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.raid;
-import java.util.Set;
-
-
-public class ReedSolomonCode implements ErasureCode {
-
- private final int stripeSize;
- private final int paritySize;
- private final int[] generatingPolynomial;
- private final int PRIMITIVE_ROOT = 2;
- private final int[] primitivePower;
- private final GaloisField GF = GaloisField.getInstance();
- private int[] errSignature;
- private final int[] paritySymbolLocations;
- private final int[] dataBuff;
-
- public ReedSolomonCode(int stripeSize, int paritySize) {
- assert(stripeSize + paritySize < GF.getFieldSize());
- this.stripeSize = stripeSize;
- this.paritySize = paritySize;
- this.errSignature = new int[paritySize];
- this.paritySymbolLocations = new int[paritySize];
- this.dataBuff = new int[paritySize + stripeSize];
- for (int i = 0; i < paritySize; i++) {
- paritySymbolLocations[i] = i;
- }
-
- this.primitivePower = new int[stripeSize + paritySize];
- // compute powers of the primitive root
- for (int i = 0; i < stripeSize + paritySize; i++) {
- primitivePower[i] = GF.power(PRIMITIVE_ROOT, i);
- }
- // compute generating polynomial
- int[] gen = {1};
- int[] poly = new int[2];
- for (int i = 0; i < paritySize; i++) {
- poly[0] = primitivePower[i];
- poly[1] = 1;
- gen = GF.multiply(gen, poly);
- }
- // generating polynomial has all generating roots
- generatingPolynomial = gen;
- }
-
- @Override
- public void encode(int[] message, int[] parity) {
- assert(message.length == stripeSize && parity.length == paritySize);
- for (int i = 0; i < paritySize; i++) {
- dataBuff[i] = 0;
- }
- for (int i = 0; i < stripeSize; i++) {
- dataBuff[i + paritySize] = message[i];
- }
- GF.remainder(dataBuff, generatingPolynomial);
- for (int i = 0; i < paritySize; i++) {
- parity[i] = dataBuff[i];
- }
- }
-
- @Override
- public void decode(int[] data, int[] erasedLocation, int[] erasedValue) {
- if (erasedLocation.length == 0) {
- return;
- }
- assert(erasedLocation.length == erasedValue.length);
- for (int i = 0; i < erasedLocation.length; i++) {
- data[erasedLocation[i]] = 0;
- }
- for (int i = 0; i < erasedLocation.length; i++) {
- errSignature[i] = primitivePower[erasedLocation[i]];
- erasedValue[i] = GF.substitute(data, primitivePower[i]);
- }
- GF.solveVandermondeSystem(errSignature, erasedValue, erasedLocation.length);
- }
-
- @Override
- public int stripeSize() {
- return this.stripeSize;
- }
-
- @Override
- public int paritySize() {
- return this.paritySize;
- }
-
- @Override
- public int symbolSize() {
- return (int) Math.round(Math.log(GF.getFieldSize()) / Math.log(2));
- }
-
- /**
- * Given parity symbols followed by message symbols, return the locations of
- * symbols that are corrupted. Can resolve up to (parity length / 2) error
- * locations.
- * @param data The message and parity. The parity should be placed in the
- * first part of the array. In each integer, the relevant portion
- * is present in the least significant bits of each int.
- * The number of elements in data is stripeSize() + paritySize().
- * Note that data may be changed after calling this method.
- * @param errorLocations The set to put the error location results
- * @return true If the locations can be resolved, return true.
- */
- public boolean computeErrorLocations(int[] data,
- Set errorLocations) {
- assert(data.length == paritySize + stripeSize && errorLocations != null);
- errorLocations.clear();
- int maxError = paritySize / 2;
- int[][] syndromeMatrix = new int[maxError][];
- for (int i = 0; i < syndromeMatrix.length; ++i) {
- syndromeMatrix[i] = new int[maxError + 1];
- }
- int[] syndrome = new int[paritySize];
-
- if (computeSyndrome(data, syndrome)) {
- // Parity check OK. No error location added.
- return true;
- }
- for (int i = 0; i < maxError; ++i) {
- for (int j = 0; j < maxError + 1; ++j) {
- syndromeMatrix[i][j] = syndrome[i + j];
- }
- }
- GF.gaussianElimination(syndromeMatrix);
- int[] polynomial = new int[maxError + 1];
- polynomial[0] = 1;
- for (int i = 0; i < maxError; ++i) {
- polynomial[i + 1] = syndromeMatrix[maxError - 1 - i][maxError];
- }
- for (int i = 0; i < paritySize + stripeSize; ++i) {
- int possibleRoot = GF.divide(1, primitivePower[i]);
- if (GF.substitute(polynomial, possibleRoot) == 0) {
- errorLocations.add(i);
- }
- }
- // Now recover with error locations and check the syndrome again
- int[] locations = new int[errorLocations.size()];
- int k = 0;
- for (int loc : errorLocations) {
- locations[k++] = loc;
- }
- int [] erasedValue = new int[locations.length];
- decode(data, locations, erasedValue);
- for (int i = 0; i < locations.length; ++i) {
- data[locations[i]] = erasedValue[i];
- }
- return computeSyndrome(data, syndrome);
- }
-
- /**
- * Compute the syndrome of the input [parity, message]
- * @param data [parity, message]
- * @param syndrome The syndromes (checksums) of the data
- * @return true If syndromes are all zeros
- */
- private boolean computeSyndrome(int[] data, int [] syndrome) {
- boolean corruptionFound = false;
- for (int i = 0; i < paritySize; i++) {
- syndrome[i] = GF.substitute(data, primitivePower[i]);
- if (syndrome[i] != 0) {
- corruptionFound = true;
- }
- }
- return !corruptionFound;
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonDecoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonDecoder.java
deleted file mode 100644
index 35eab7d6af3..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonDecoder.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.ChecksumException;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hdfs.BlockMissingException;
-
-public class ReedSolomonDecoder extends Decoder {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.ReedSolomonDecoder");
- private ErasureCode reedSolomonCode;
-
- public ReedSolomonDecoder(
- Configuration conf, int stripeSize, int paritySize) {
- super(conf, stripeSize, paritySize);
- this.reedSolomonCode = new ReedSolomonCode(stripeSize, paritySize);
- }
-
- @Override
- protected void fixErasedBlock(
- FileSystem fs, Path srcFile,
- FileSystem parityFs, Path parityFile,
- long blockSize, long errorOffset, long bytesToSkip, long limit,
- OutputStream out) throws IOException {
- FSDataInputStream[] inputs = new FSDataInputStream[stripeSize + paritySize];
- int[] erasedLocations = buildInputs(fs, srcFile, parityFs, parityFile,
- errorOffset, inputs);
- int blockIdxInStripe = ((int)(errorOffset/blockSize)) % stripeSize;
- int erasedLocationToFix = paritySize + blockIdxInStripe;
- writeFixedBlock(inputs, erasedLocations, erasedLocationToFix,
- bytesToSkip, limit, out);
- }
-
- protected int[] buildInputs(FileSystem fs, Path srcFile,
- FileSystem parityFs, Path parityFile,
- long errorOffset, FSDataInputStream[] inputs)
- throws IOException {
- LOG.info("Building inputs to recover block starting at " + errorOffset);
- FileStatus srcStat = fs.getFileStatus(srcFile);
- long blockSize = srcStat.getBlockSize();
- long blockIdx = (int)(errorOffset / blockSize);
- long stripeIdx = blockIdx / stripeSize;
- LOG.info("FileSize = " + srcStat.getLen() + ", blockSize = " + blockSize +
- ", blockIdx = " + blockIdx + ", stripeIdx = " + stripeIdx);
- ArrayList erasedLocations = new ArrayList();
- // First open streams to the parity blocks.
- for (int i = 0; i < paritySize; i++) {
- long offset = blockSize * (stripeIdx * paritySize + i);
- FSDataInputStream in = parityFs.open(
- parityFile, conf.getInt("io.file.buffer.size", 64 * 1024));
- in.seek(offset);
- LOG.info("Adding " + parityFile + ":" + offset + " as input " + i);
- inputs[i] = in;
- }
- // Now open streams to the data blocks.
- for (int i = paritySize; i < paritySize + stripeSize; i++) {
- long offset = blockSize * (stripeIdx * stripeSize + i - paritySize);
- if (offset == errorOffset) {
- LOG.info(srcFile + ":" + offset +
- " is known to have error, adding zeros as input " + i);
- inputs[i] = new FSDataInputStream(new RaidUtils.ZeroInputStream(
- offset + blockSize));
- erasedLocations.add(i);
- } else if (offset > srcStat.getLen()) {
- LOG.info(srcFile + ":" + offset +
- " is past file size, adding zeros as input " + i);
- inputs[i] = new FSDataInputStream(new RaidUtils.ZeroInputStream(
- offset + blockSize));
- } else {
- FSDataInputStream in = fs.open(
- srcFile, conf.getInt("io.file.buffer.size", 64 * 1024));
- in.seek(offset);
- LOG.info("Adding " + srcFile + ":" + offset + " as input " + i);
- inputs[i] = in;
- }
- }
- if (erasedLocations.size() > paritySize) {
- String msg = "Too many erased locations: " + erasedLocations.size();
- LOG.error(msg);
- throw new IOException(msg);
- }
- int[] locs = new int[erasedLocations.size()];
- for (int i = 0; i < locs.length; i++) {
- locs[i] = erasedLocations.get(i);
- }
- return locs;
- }
-
- /**
- * Decode the inputs provided and write to the output.
- * @param inputs array of inputs.
- * @param erasedLocations indexes in the inputs which are known to be erased.
- * @param erasedLocationToFix index in the inputs which needs to be fixed.
- * @param skipBytes number of bytes to skip before writing to output.
- * @param limit maximum number of bytes to be written/skipped.
- * @param out the output.
- * @throws IOException
- */
- void writeFixedBlock(
- FSDataInputStream[] inputs,
- int[] erasedLocations,
- int erasedLocationToFix,
- long skipBytes,
- long limit,
- OutputStream out) throws IOException {
-
- LOG.info("Need to write " + (limit - skipBytes) +
- " bytes for erased location index " + erasedLocationToFix);
- int[] tmp = new int[inputs.length];
- int[] decoded = new int[erasedLocations.length];
- long toDiscard = skipBytes;
- // Loop while the number of skipped + written bytes is less than the max.
- for (long written = 0; skipBytes + written < limit; ) {
- erasedLocations = readFromInputs(inputs, erasedLocations, limit);
- if (decoded.length != erasedLocations.length) {
- decoded = new int[erasedLocations.length];
- }
-
- int toWrite = (int)Math.min((long)bufSize, limit - (skipBytes + written));
- if (toDiscard >= toWrite) {
- toDiscard -= toWrite;
- continue;
- }
-
- // Decoded bufSize amount of data.
- for (int i = 0; i < bufSize; i++) {
- performDecode(readBufs, writeBufs, i, tmp, erasedLocations, decoded);
- }
-
- for (int i = 0; i < erasedLocations.length; i++) {
- if (erasedLocations[i] == erasedLocationToFix) {
- toWrite -= toDiscard;
- out.write(writeBufs[i], (int)toDiscard, toWrite);
- toDiscard = 0;
- written += toWrite;
- LOG.debug("Wrote " + toWrite + " bytes for erased location index " +
- erasedLocationToFix);
- break;
- }
- }
- }
- }
-
- int[] readFromInputs(
- FSDataInputStream[] inputs,
- int[] erasedLocations,
- long limit) throws IOException {
- // For every input, read some data = bufSize.
- for (int i = 0; i < inputs.length; i++) {
- long curPos = inputs[i].getPos();
- try {
- RaidUtils.readTillEnd(inputs[i], readBufs[i], true);
- continue;
- } catch (BlockMissingException e) {
- LOG.error("Encountered BlockMissingException in stream " + i);
- } catch (ChecksumException e) {
- LOG.error("Encountered ChecksumException in stream " + i);
- }
-
- // Found a new erased location.
- if (erasedLocations.length == paritySize) {
- String msg = "Too many read errors";
- LOG.error(msg);
- throw new IOException(msg);
- }
-
- // Add this stream to the set of erased locations.
- int[] newErasedLocations = new int[erasedLocations.length + 1];
- for (int j = 0; j < erasedLocations.length; j++) {
- newErasedLocations[j] = erasedLocations[j];
- }
- newErasedLocations[newErasedLocations.length - 1] = i;
- erasedLocations = newErasedLocations;
-
- LOG.info("Using zeros for stream " + i);
- inputs[i] = new FSDataInputStream(
- new RaidUtils.ZeroInputStream(curPos + limit));
- inputs[i].seek(curPos);
- RaidUtils.readTillEnd(inputs[i], readBufs[i], true);
- }
- return erasedLocations;
- }
-
- void performDecode(byte[][] readBufs, byte[][] writeBufs,
- int idx, int[] inputs,
- int[] erasedLocations, int[] decoded) {
- for (int i = 0; i < decoded.length; i++) {
- decoded[i] = 0;
- }
- for (int i = 0; i < inputs.length; i++) {
- inputs[i] = readBufs[i][idx] & 0x000000FF;
- }
- reedSolomonCode.decode(inputs, erasedLocations, decoded);
- for (int i = 0; i < decoded.length; i++) {
- writeBufs[i][idx] = (byte)decoded[i];
- }
- }
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonEncoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonEncoder.java
deleted file mode 100644
index 411978449d9..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/ReedSolomonEncoder.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.util.Progressable;
-
-public class ReedSolomonEncoder extends Encoder {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.ReedSolomonEncoder");
- private ErasureCode reedSolomonCode;
-
- public ReedSolomonEncoder(
- Configuration conf, int stripeSize, int paritySize) {
- super(conf, stripeSize, paritySize);
- this.reedSolomonCode = new ReedSolomonCode(stripeSize, paritySize);
- }
-
- protected void encodeStripe(
- InputStream[] blocks,
- long stripeStartOffset,
- long blockSize,
- OutputStream[] outs,
- Progressable reporter) throws IOException {
-
- int[] data = new int[stripeSize];
- int[] code = new int[paritySize];
-
- for (long encoded = 0; encoded < blockSize; encoded += bufSize) {
- // Read some data from each block = bufSize.
- for (int i = 0; i < blocks.length; i++) {
- RaidUtils.readTillEnd(blocks[i], readBufs[i], true);
- }
-
- // Encode the data read.
- for (int j = 0; j < bufSize; j++) {
- performEncode(readBufs, writeBufs, j, data, code);
- }
-
- // Now that we have some data to write, send it to the temp files.
- for (int i = 0; i < paritySize; i++) {
- outs[i].write(writeBufs[i], 0, bufSize);
- }
-
- if (reporter != null) {
- reporter.progress();
- }
- }
- }
-
- void performEncode(byte[][] readBufs, byte[][] writeBufs, int idx,
- int[] data, int[] code) {
- for (int i = 0; i < paritySize; i++) {
- code[i] = 0;
- }
- for (int i = 0; i < stripeSize; i++) {
- data[i] = readBufs[i][idx] & 0x000000FF;
- }
- reedSolomonCode.encode(data, code);
- for (int i = 0; i < paritySize; i++) {
- writeBufs[i][idx] = (byte)code[i];
- }
- }
-
- @Override
- public Path getParityTempPath() {
- return new Path(RaidNode.rsTempPrefix(conf));
- }
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/XORDecoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/XORDecoder.java
deleted file mode 100644
index 3dfe592f8ad..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/XORDecoder.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.OutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-
-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.FSDataInputStream;
-import org.apache.hadoop.fs.Path;
-
-public class XORDecoder extends Decoder {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.XORDecoder");
-
- public XORDecoder(
- Configuration conf, int stripeSize) {
- super(conf, stripeSize, 1);
- }
-
- @Override
- protected void fixErasedBlock(
- FileSystem fs, Path srcFile, FileSystem parityFs, Path parityFile,
- long blockSize, long errorOffset, long bytesToSkip, long limit,
- OutputStream out) throws IOException {
- LOG.info("Fixing block at " + srcFile + ":" + errorOffset +
- ", skipping " + bytesToSkip + ", limit " + limit);
- FileStatus srcStat = fs.getFileStatus(srcFile);
- ArrayList xorinputs = new ArrayList();
-
- FSDataInputStream parityFileIn = parityFs.open(parityFile);
- parityFileIn.seek(parityOffset(errorOffset, blockSize));
- xorinputs.add(parityFileIn);
-
- long errorBlockOffset = (errorOffset / blockSize) * blockSize;
- long[] srcOffsets = stripeOffsets(errorOffset, blockSize);
- for (int i = 0; i < srcOffsets.length; i++) {
- if (srcOffsets[i] == errorBlockOffset) {
- LOG.info("Skipping block at " + srcFile + ":" + errorBlockOffset);
- continue;
- }
- if (srcOffsets[i] < srcStat.getLen()) {
- FSDataInputStream in = fs.open(srcFile);
- in.seek(srcOffsets[i]);
- xorinputs.add(in);
- }
- }
- FSDataInputStream[] inputs = xorinputs.toArray(
- new FSDataInputStream[]{null});
- ParityInputStream recovered =
- new ParityInputStream(inputs, limit, readBufs[0], writeBufs[0]);
- recovered.skip(bytesToSkip);
- recovered.drain(out, null);
- }
-
- protected long[] stripeOffsets(long errorOffset, long blockSize) {
- long[] offsets = new long[stripeSize];
- long stripeIdx = errorOffset / (blockSize * stripeSize);
- long startOffsetOfStripe = stripeIdx * stripeSize * blockSize;
- for (int i = 0; i < stripeSize; i++) {
- offsets[i] = startOffsetOfStripe + i * blockSize;
- }
- return offsets;
- }
-
- protected long parityOffset(long errorOffset, long blockSize) {
- long stripeIdx = errorOffset / (blockSize * stripeSize);
- return stripeIdx * blockSize;
- }
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/XOREncoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/XOREncoder.java
deleted file mode 100644
index 469a1716e02..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/XOREncoder.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * 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.raid;
-
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.IOException;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.util.Progressable;
-
-public class XOREncoder extends Encoder {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.XOREncoder");
- public XOREncoder(
- Configuration conf, int stripeSize) {
- super(conf, stripeSize, 1);
- }
-
- @Override
- protected void encodeStripe(
- InputStream[] blocks,
- long stripeStartOffset,
- long blockSize,
- OutputStream[] outs,
- Progressable reporter) throws IOException {
- LOG.info("Peforming XOR ");
- ParityInputStream parityIn =
- new ParityInputStream(blocks, blockSize, readBufs[0], writeBufs[0]);
- try {
- parityIn.drain(outs[0], reporter);
- } finally {
- parityIn.close();
- }
- }
-
- @Override
- public Path getParityTempPath() {
- return new Path(RaidNode.unraidTmpDirectory(conf));
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/PolicyInfo.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/PolicyInfo.java
deleted file mode 100644
index 2df302a905d..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/PolicyInfo.java
+++ /dev/null
@@ -1,256 +0,0 @@
-/**
- * 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.raid.protocol;
-
-import java.io.IOException;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.util.Properties;
-import java.util.Enumeration;
-import java.lang.Math;
-import java.text.SimpleDateFormat;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.io.Text;
-import org.apache.hadoop.io.Writable;
-import org.apache.hadoop.io.WritableFactories;
-import org.apache.hadoop.io.WritableFactory;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FileStatus;
-
-/**
- * Maintains information about one policy
- */
-public class PolicyInfo implements Writable {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.protocol.PolicyInfo");
- protected static final SimpleDateFormat dateFormat =
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
- private Path srcPath; // the specified src path
- private String policyName; // name of policy
- private ErasureCodeType codeType;// the erasure code used
- private String description; // A verbose description of this policy
- private Configuration conf; // Hadoop configuration
-
- private Properties properties; // Policy-dependent properties
-
- private ReentrantReadWriteLock plock; // protects policy operations.
- public static enum ErasureCodeType {
- XOR, RS;
- public static ErasureCodeType fromString(String s) {
- if (XOR.toString().equalsIgnoreCase(s)) {
- return XOR;
- }
- if (RS.toString().equalsIgnoreCase(s)) {
- return RS;
- }
- return null;
- }
- }
-
- /**
- * Create the empty object
- */
- public PolicyInfo() {
- this.conf = null;
- this.policyName = "";
- this.description = "";
- this.srcPath = null;
- this.properties = new Properties();
- this.plock = new ReentrantReadWriteLock();
- }
-
- /**
- * Create the metadata that describes a policy
- */
- public PolicyInfo(String policyName, Configuration conf) {
- this.conf = conf;
- this.policyName = policyName;
- this.description = "";
- this.srcPath = null;
- this.properties = new Properties();
- this.plock = new ReentrantReadWriteLock();
- }
-
- /**
- * Copy fields from another PolicyInfo
- */
- public void copyFrom(PolicyInfo other) {
- if (other.conf != null) {
- this.conf = other.conf;
- }
- if (other.policyName != null && other.policyName.length() > 0) {
- this.policyName = other.policyName;
- }
- if (other.description != null && other.description.length() > 0) {
- this.description = other.description;
- }
- if (other.codeType != null) {
- this.codeType = other.codeType;
- }
- if (other.srcPath != null) {
- this.srcPath = other.srcPath;
- }
- for (Object key : other.properties.keySet()) {
- String skey = (String) key;
- this.properties.setProperty(skey, other.properties.getProperty(skey));
- }
- }
-
- /**
- * Sets the input path on which this policy has to be applied
- */
- public void setSrcPath(String in) throws IOException {
- srcPath = new Path(in);
- srcPath = srcPath.makeQualified(srcPath.getFileSystem(conf));
- }
-
- /**
- * Set the erasure code type used in this policy
- */
- public void setErasureCode(String code) {
- this.codeType = ErasureCodeType.fromString(code);
- }
-
- /**
- * Set the description of this policy.
- */
- public void setDescription(String des) {
- this.description = des;
- }
-
- /**
- * Sets an internal property.
- * @param name property name.
- * @param value property value.
- */
- public void setProperty(String name, String value) {
- properties.setProperty(name, value);
- }
-
- /**
- * Returns the value of an internal property.
- * @param name property name.
- */
- public String getProperty(String name) {
- return properties.getProperty(name);
- }
-
- /**
- * Get the name of this policy.
- */
- public String getName() {
- return this.policyName;
- }
-
- /**
- * Get the destination path of this policy.
- */
- public ErasureCodeType getErasureCode() {
- return this.codeType;
- }
-
- /**
- * Get the srcPath
- */
- public Path getSrcPath() {
- return srcPath;
- }
-
- /**
- * Get the expanded (unglobbed) forms of the srcPaths
- */
- public Path[] getSrcPathExpanded() throws IOException {
- FileSystem fs = srcPath.getFileSystem(conf);
-
- // globbing on srcPath
- FileStatus[] gpaths = fs.globStatus(srcPath);
- if (gpaths == null) {
- return null;
- }
- Path[] values = new Path[gpaths.length];
- for (int i = 0; i < gpaths.length; i++) {
- Path p = gpaths[i].getPath();
- values[i] = p.makeQualified(fs);
- }
- return values;
- }
-
- /**
- * Convert this policy into a printable form
- */
- public String toString() {
- StringBuffer buff = new StringBuffer();
- buff.append("Policy Name:\t" + policyName + " --------------------\n");
- buff.append("Source Path:\t" + srcPath + "\n");
- buff.append("Erasure Code:\t" + codeType + "\n");
- for (Enumeration> e = properties.propertyNames(); e.hasMoreElements();) {
- String name = (String) e.nextElement();
- buff.append( name + ":\t" + properties.getProperty(name) + "\n");
- }
- if (description.length() > 0) {
- int len = Math.min(description.length(), 80);
- String sub = description.substring(0, len).trim();
- sub = sub.replaceAll("\n", " ");
- buff.append("Description:\t" + sub + "...\n");
- }
- return buff.toString();
- }
-
- //////////////////////////////////////////////////
- // Writable
- //////////////////////////////////////////////////
- static { // register a ctor
- WritableFactories.setFactory
- (PolicyInfo.class,
- new WritableFactory() {
- public Writable newInstance() { return new PolicyInfo(); }
- });
- }
-
- public void write(DataOutput out) throws IOException {
- Text.writeString(out, srcPath.toString());
- Text.writeString(out, policyName);
- Text.writeString(out, codeType.toString());
- Text.writeString(out, description);
- out.writeInt(properties.size());
- for (Enumeration> e = properties.propertyNames(); e.hasMoreElements();) {
- String name = (String) e.nextElement();
- Text.writeString(out, name);
- Text.writeString(out, properties.getProperty(name));
- }
- }
-
- public void readFields(DataInput in) throws IOException {
- this.srcPath = new Path(Text.readString(in));
- this.policyName = Text.readString(in);
- this.codeType = ErasureCodeType.fromString(Text.readString(in));
- this.description = Text.readString(in);
- for (int n = in.readInt(); n>0; n--) {
- String name = Text.readString(in);
- String value = Text.readString(in);
- properties.setProperty(name,value);
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/PolicyList.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/PolicyList.java
deleted file mode 100644
index eb3dc6e7449..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/PolicyList.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- * 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.raid.protocol;
-
-import java.io.IOException;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.util.Collection;
-import java.util.List;
-import java.util.LinkedList;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.io.Writable;
-import org.apache.hadoop.io.WritableFactories;
-import org.apache.hadoop.io.WritableFactory;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.conf.Configuration;
-
-/**
- * Maintains informatiom about all policies that belong to a category.
- * These policies have to be applied one-at-a-time and cannot be run
- * simultaneously.
- */
-public class PolicyList implements Writable {
- public static final Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.protocol.PolicyList");
-
- private List category; // list of policies
- private Path srcPath;
-
- /**
- * Create a new category of policies.
- */
- public PolicyList() {
- this.category = new LinkedList();
- this.srcPath = null;
- }
-
- /**
- * Add a new policy to this category.
- */
- public void add(PolicyInfo info) {
- category.add(info);
- }
-
- public void setSrcPath(Configuration conf, String src) throws IOException {
- srcPath = new Path(src);
- srcPath = srcPath.makeQualified(srcPath.getFileSystem(conf));
- }
-
- public Path getSrcPath() {
- return srcPath;
- }
-
- /**
- * Returns the policies in this category
- */
- public Collection getAll() {
- return category;
- }
-
- //////////////////////////////////////////////////
- // Writable
- //////////////////////////////////////////////////
- static { // register a ctor
- WritableFactories.setFactory
- (PolicyList.class,
- new WritableFactory() {
- public Writable newInstance() { return new PolicyList(); }
- });
- }
-
- public void write(DataOutput out) throws IOException {
- out.writeInt(category.size());
- for (PolicyInfo p : category) {
- p.write(out);
- }
- }
-
- public void readFields(DataInput in) throws IOException {
- int count = in.readInt();
- for (int i = 0; i < count; i++) {
- PolicyInfo p = new PolicyInfo();
- p.readFields(in);
- add(p);
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/RaidProtocol.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/RaidProtocol.java
deleted file mode 100644
index 0dac296e188..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/java/org/apache/hadoop/raid/protocol/RaidProtocol.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * 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.raid.protocol;
-
-import java.util.Collection;
-import java.io.IOException;
-
-import org.apache.hadoop.ipc.VersionedProtocol;
-import org.apache.hadoop.fs.Path;
-
-/**********************************************************************
- * RaidProtocol is used by user code
- * {@link org.apache.hadoop.raid.RaidShell} class to communicate
- * with the RaidNode. User code can manipulate the configured policies.
- *
- **********************************************************************/
-public interface RaidProtocol extends VersionedProtocol {
-
- /**
- * Compared to the previous version the following changes have been introduced:
- * Only the latest change is reflected.
- * 1: new protocol introduced
- */
- public static final long versionID = 1L;
-
- /**
- * Get a listing of all configured policies
- * @throws IOException
- * return all categories of configured policies
- */
- public PolicyList[] getAllPolicies() throws IOException;
-
- /**
- * Unraid the specified input path. This is called when the specified file
- * is corrupted. This call will move the specified file to file.old
- * and then recover it from the RAID subsystem.
- *
- * @param inputPath The absolute pathname of the file to be recovered.
- * @param corruptOffset The offset that has the corruption
- */
- public String recoverFile(String inputPath, long corruptOffset) throws IOException;
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/start-raidnode-remote.sh b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/start-raidnode-remote.sh
deleted file mode 100644
index 3e9405eb72f..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/start-raidnode-remote.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env bash
-
-# 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.
-
-
-# Start hadoop RaidNode process on machine specified on file conf/raidnode
-
-usage="Usage: start-raidnode-remote.sh"
-
-params=$#
-bin=`dirname "$0"`
-bin=`cd "$bin"; pwd`
-
-DEFAULT_LIBEXEC_DIR="$bin"
-HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
-. $HADOOP_LIBEXEC_DIR/hadoop-config.sh
-
-# get arguments
-if [ $# -ge 1 ]; then
- echo $usage
- exit
-fi
-
-if [ -f "${HADOOP_CONF_DIR}/raidnode" ]; then
- export HADOOP_SLAVES="${HADOOP_CONF_DIR}/raidnode"
- echo "Starting raidnode at "`cat ${HADOOP_SLAVES}`
- "$bin"/slaves.sh --config $HADOOP_CONF_DIR cd "$HADOOP_PREFIX" \; "$bin/start-raidnode.sh"
-else
- echo "No raidnode file in ${HADOOP_CONF_DIR}/raidnode"
-fi
-
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/start-raidnode.sh b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/start-raidnode.sh
deleted file mode 100644
index d193bb1aeb6..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/start-raidnode.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env bash
-
-# 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.
-
-
-# Start hadoop RaidNode process
-# Run this on RaidNode machine
-
-usage="Usage: start-raidnode.sh"
-
-params=$#
-bin=`dirname "$0"`
-bin=`cd "$bin"; pwd`
-
-DEFAULT_LIBEXEC_DIR="$bin"
-HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
-. $HADOOP_LIBEXEC_DIR/hadoop-config.sh
-
-# get arguments
-if [ $# -ge 1 ]; then
- echo $usage
-fi
-
-if [ -f "${HADOOP_CONF_DIR}/hadoop-env.sh" ]; then
- . "${HADOOP_CONF_DIR}/hadoop-env.sh"
-fi
-export HADOOP_OPTS="$HADOOP_OPTS $HADOOP_RAIDNODE_OPTS"
-
-"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR start org.apache.hadoop.raid.RaidNode
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/stop-raidnode-remote.sh b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/stop-raidnode-remote.sh
deleted file mode 100644
index d185629b23b..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/stop-raidnode-remote.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env bash
-
-# 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.
-
-
-# Stop hadoop RaidNode process on machine specified on file conf/raidnode
-
-usage="Usage: stop-raidnode-remote.sh"
-
-params=$#
-bin=`dirname "$0"`
-bin=`cd "$bin"; pwd`
-
-DEFAULT_LIBEXEC_DIR="$bin"
-HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
-. $HADOOP_LIBEXEC_DIR/hadoop-config.sh
-
-# get arguments
-if [ $# -ge 1 ]; then
- echo $usage
-fi
-
-if [ -f "${HADOOP_CONF_DIR}/raidnode" ]; then
- export HADOOP_SLAVES="${HADOOP_CONF_DIR}/raidnode"
- echo "Stopping raidnode at "`cat ${HADOOP_SLAVES}`
- "$bin"/slaves.sh --config $HADOOP_CONF_DIR cd "$HADOOP_PREFIX" \; "$bin/stop-raidnode.sh"
-else
- echo "No raidnode file in ${HADOOP_CONF_DIR}/raidnode"
-fi
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/stop-raidnode.sh b/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/stop-raidnode.sh
deleted file mode 100644
index 02a61a87f7c..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/main/sbin/stop-raidnode.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-
-# 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.
-
-
-# Stop hadoop RaidNode process
-# Run this on RaidNode machine.
-
-usage="Usage: stop-raidnode.sh"
-
-params=$#
-bin=`dirname "$0"`
-bin=`cd "$bin"; pwd`
-
-DEFAULT_LIBEXEC_DIR="$bin"
-HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
-. $HADOOP_LIBEXEC_DIR/hadoop-config.sh
-
-# get arguments
-if [ $# -ge 1 ]; then
- echo $usage
-fi
-
-export HADOOP_OPTS="$HADOOP_OPTS $HADOOP_RAIDNODE_OPTS"
-
-"$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR stop org.apache.hadoop.raid.RaidNode
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/TestRaidDfs.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/TestRaidDfs.java
deleted file mode 100644
index ae7d0293a7c..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/TestRaidDfs.java
+++ /dev/null
@@ -1,501 +0,0 @@
-/**
- * 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 static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.RandomAccessFile;
-import java.net.URI;
-import java.util.Random;
-import java.util.regex.Pattern;
-import java.util.zip.CRC32;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.raid.RaidNode;
-import org.apache.hadoop.raid.RaidUtils;
-import org.apache.hadoop.raid.protocol.PolicyInfo.ErasureCodeType;
-import org.apache.hadoop.util.StringUtils;
-import org.junit.Test;
-
-public class TestRaidDfs {
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
- final static String LOG_DIR = "target/raidlog";
- final static long RELOAD_INTERVAL = 1000;
- final static Log LOG = LogFactory.getLog("org.apache.hadoop.raid.TestRaidDfs");
- final static int NUM_DATANODES = 3;
-
- Configuration conf;
- String namenode = null;
- String hftp = null;
- MiniDFSCluster dfs = null;
- FileSystem fileSys = null;
- String jobTrackerName = null;
- ErasureCodeType code;
- int stripeLength;
-
- private void mySetup(
- String erasureCode, int rsParityLength) throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
-
- conf.set("fs.raid.recoverylogdir", LOG_DIR);
- conf.setInt(RaidNode.RS_PARITY_LENGTH_KEY, rsParityLength);
-
- // scan all policies once every 5 second
- conf.setLong("raid.policy.rescan.interval", 5000);
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- // do not use map-reduce cluster for Raiding
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
-
- conf.set("raid.server.address", "localhost:0");
- conf.setInt("hdfs.raid.stripeLength", stripeLength);
- conf.set("xor".equals(erasureCode) ? RaidNode.RAID_LOCATION_KEY :
- RaidNode.RAIDRS_LOCATION_KEY, "/destraid");
-
- dfs = new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATANODES).build();
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
- namenode = fileSys.getUri().toString();
- hftp = "hftp://localhost.localdomain:" + dfs.getNameNodePort();
-
- FileSystem.setDefaultUri(conf, namenode);
- }
-
- private void myTearDown() throws Exception {
- if (dfs != null) { dfs.shutdown(); }
- }
-
- private LocatedBlocks getBlockLocations(Path file, long length)
- throws IOException {
- DistributedFileSystem dfs = (DistributedFileSystem) fileSys;
- return RaidDFSUtil.getBlockLocations(
- dfs, file.toUri().getPath(), 0, length);
- }
-
- private LocatedBlocks getBlockLocations(Path file)
- throws IOException {
- FileStatus stat = fileSys.getFileStatus(file);
- return getBlockLocations(file, stat.getLen());
- }
-
- private DistributedRaidFileSystem getRaidFS() throws IOException {
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- Configuration clientConf = new Configuration(conf);
- clientConf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedRaidFileSystem");
- clientConf.set("fs.raid.underlyingfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
- clientConf.setBoolean("fs.hdfs.impl.disable.cache", true);
- URI dfsUri = dfs.getUri();
- return (DistributedRaidFileSystem)FileSystem.get(dfsUri, clientConf);
- }
-
- public static void waitForFileRaided(
- Log logger, FileSystem fileSys, Path file, Path destPath)
- throws IOException, InterruptedException {
- FileStatus parityStat = null;
- String fileName = file.getName().toString();
- // wait till file is raided
- while (parityStat == null) {
- logger.info("Waiting for files to be raided.");
- try {
- FileStatus[] listPaths = fileSys.listStatus(destPath);
- if (listPaths != null) {
- for (FileStatus f : listPaths) {
- logger.info("File raided so far : " + f.getPath());
- String found = f.getPath().getName().toString();
- if (fileName.equals(found)) {
- parityStat = f;
- break;
- }
- }
- }
- } catch (FileNotFoundException e) {
- //ignore
- }
- Thread.sleep(1000); // keep waiting
- }
-
- while (true) {
- LocatedBlocks locations = null;
- DistributedFileSystem dfs = (DistributedFileSystem) fileSys;
- locations = RaidDFSUtil.getBlockLocations(
- dfs, file.toUri().getPath(), 0, parityStat.getLen());
- if (!locations.isUnderConstruction()) {
- break;
- }
- Thread.sleep(1000);
- }
-
- while (true) {
- FileStatus stat = fileSys.getFileStatus(file);
- if (stat.getReplication() == 1) break;
- Thread.sleep(1000);
- }
- }
-
- private void corruptBlockAndValidate(Path srcFile, Path destPath,
- int[] listBlockNumToCorrupt, long blockSize, int numBlocks)
- throws IOException, InterruptedException {
- int repl = 1;
- long crc = createTestFilePartialLastBlock(fileSys, srcFile, repl,
- numBlocks, blockSize);
- long length = fileSys.getFileStatus(srcFile).getLen();
-
- RaidNode.doRaid(conf, fileSys.getFileStatus(srcFile),
- destPath, code, new RaidNode.Statistics(), new RaidUtils.DummyProgressable(),
- false, repl, repl, stripeLength);
-
- // Delete first block of file
- for (int blockNumToCorrupt : listBlockNumToCorrupt) {
- LOG.info("Corrupt block " + blockNumToCorrupt + " of file " + srcFile);
- LocatedBlocks locations = getBlockLocations(srcFile);
- corruptBlock(dfs, srcFile, locations.get(blockNumToCorrupt).getBlock(),
- NUM_DATANODES, true);
- }
-
- // Validate
- DistributedRaidFileSystem raidfs = getRaidFS();
- assertTrue(validateFile(raidfs, srcFile, length, crc));
- validateLogFile(getRaidFS(), new Path(LOG_DIR));
- }
-
- /**
- * Create a file, corrupt several blocks in it and ensure that the file can be
- * read through DistributedRaidFileSystem by ReedSolomon coding.
- */
- @Test
- public void testRaidDfsRs() throws Exception {
- LOG.info("Test testRaidDfs started.");
-
- code = ErasureCodeType.RS;
- long blockSize = 8192L;
- int numBlocks = 8;
- stripeLength = 3;
- mySetup("rs", 3);
-
- int[][] corrupt = {{1, 2, 3}, {1, 4, 7}, {3, 6, 7}};
- try {
- for (int i = 0; i < corrupt.length; i++) {
- Path file = new Path("/user/dhruba/raidtest/file" + i);
- corruptBlockAndValidate(
- file, new Path("/destraid"), corrupt[i], blockSize, numBlocks);
- }
- } catch (Exception e) {
- LOG.info("testRaidDfs Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
- LOG.info("Test testRaidDfs completed.");
- }
-
- /**
- * Test DistributedRaidFileSystem.readFully()
- */
- @Test
- public void testReadFully() throws Exception {
- code = ErasureCodeType.XOR;
- stripeLength = 3;
- mySetup("xor", 1);
-
- try {
- Path file = new Path("/user/raid/raidtest/file1");
- long crc = createTestFile(fileSys, file, 1, 8, 8192L);
- FileStatus stat = fileSys.getFileStatus(file);
- LOG.info("Created " + file + ", crc=" + crc + ", len=" + stat.getLen());
-
- byte[] filebytes = new byte[(int)stat.getLen()];
- // Test that readFully returns the correct CRC when there are no errors.
- DistributedRaidFileSystem raidfs = getRaidFS();
- FSDataInputStream stm = raidfs.open(file);
- stm.readFully(0, filebytes);
- assertEquals(crc, bufferCRC(filebytes));
- stm.close();
-
- // Generate parity.
- RaidNode.doRaid(conf, fileSys.getFileStatus(file),
- new Path("/destraid"), code, new RaidNode.Statistics(),
- new RaidUtils.DummyProgressable(),
- false, 1, 1, stripeLength);
- int[] corrupt = {0, 4, 7}; // first, last and middle block
- for (int blockIdx : corrupt) {
- LOG.info("Corrupt block " + blockIdx + " of file " + file);
- LocatedBlocks locations = getBlockLocations(file);
- corruptBlock(dfs, file, locations.get(blockIdx).getBlock(),
- NUM_DATANODES, true);
- }
- // Test that readFully returns the correct CRC when there are errors.
- stm = raidfs.open(file);
- stm.readFully(0, filebytes);
- assertEquals(crc, bufferCRC(filebytes));
- } finally {
- myTearDown();
- }
- }
-
- /**
- * Test that access time and mtime of a source file do not change after
- * raiding.
- */
- @Test
- public void testAccessTime() throws Exception {
- LOG.info("Test testAccessTime started.");
-
- code = ErasureCodeType.XOR;
- long blockSize = 8192L;
- int numBlocks = 8;
- int repl = 1;
- stripeLength = 3;
- mySetup("xor", 1);
-
- Path file = new Path("/user/dhruba/raidtest/file");
- createTestFilePartialLastBlock(fileSys, file, repl, numBlocks, blockSize);
- FileStatus stat = fileSys.getFileStatus(file);
-
- try {
- RaidNode.doRaid(conf, fileSys.getFileStatus(file),
- new Path("/destraid"), code, new RaidNode.Statistics(),
- new RaidUtils.DummyProgressable(), false, repl, repl, stripeLength);
-
- FileStatus newStat = fileSys.getFileStatus(file);
-
- assertEquals(stat.getModificationTime(), newStat.getModificationTime());
- assertEquals(stat.getAccessTime(), newStat.getAccessTime());
- } finally {
- myTearDown();
- }
- }
-
- /**
- * Create a file, corrupt a block in it and ensure that the file can be
- * read through DistributedRaidFileSystem by XOR code.
- */
- @Test
- public void testRaidDfsXor() throws Exception {
- LOG.info("Test testRaidDfs started.");
-
- code = ErasureCodeType.XOR;
- long blockSize = 8192L;
- int numBlocks = 8;
- stripeLength = 3;
- mySetup("xor", 1);
-
- int[][] corrupt = {{0}, {4}, {7}}; // first, last and middle block
- try {
- for (int i = 0; i < corrupt.length; i++) {
- Path file = new Path("/user/dhruba/raidtest/" + i);
- corruptBlockAndValidate(
- file, new Path("/destraid"), corrupt[i], blockSize, numBlocks);
- }
- } catch (Exception e) {
- LOG.info("testRaidDfs Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
- LOG.info("Test testRaidDfs completed.");
- }
-
- //
- // creates a file and populate it with random data. Returns its crc.
- //
- public static long createTestFile(FileSystem fileSys, Path name, int repl,
- int numBlocks, long blocksize)
- throws IOException {
- CRC32 crc = new CRC32();
- Random rand = new Random();
- FSDataOutputStream stm = fileSys.create(name, true,
- fileSys.getConf().getInt("io.file.buffer.size", 4096),
- (short)repl, blocksize);
- // fill random data into file
- final byte[] b = new byte[(int)blocksize];
- for (int i = 0; i < numBlocks; i++) {
- rand.nextBytes(b);
- stm.write(b);
- crc.update(b);
- }
- stm.close();
- return crc.getValue();
- }
-
- //
- // Creates a file with partially full last block. Populate it with random
- // data. Returns its crc.
- //
- public static long createTestFilePartialLastBlock(
- FileSystem fileSys, Path name, int repl, int numBlocks, long blocksize)
- throws IOException {
- CRC32 crc = new CRC32();
- Random rand = new Random();
- FSDataOutputStream stm = fileSys.create(name, true,
- fileSys.getConf().getInt("io.file.buffer.size", 4096),
- (short)repl, blocksize);
- // Write whole blocks.
- byte[] b = new byte[(int)blocksize];
- for (int i = 1; i < numBlocks; i++) {
- rand.nextBytes(b);
- stm.write(b);
- crc.update(b);
- }
- // Write partial block.
- b = new byte[(int)blocksize/2 - 1];
- rand.nextBytes(b);
- stm.write(b);
- crc.update(b);
-
- stm.close();
- return crc.getValue();
- }
-
- static long bufferCRC(byte[] buf) {
- CRC32 crc = new CRC32();
- crc.update(buf, 0, buf.length);
- return crc.getValue();
- }
-
- //
- // validates that file matches the crc.
- //
- public static boolean validateFile(FileSystem fileSys, Path name, long length,
- long crc)
- throws IOException {
-
- long numRead = 0;
- CRC32 newcrc = new CRC32();
- FSDataInputStream stm = fileSys.open(name);
- final byte[] b = new byte[4192];
- int num = 0;
- while (num >= 0) {
- num = stm.read(b);
- if (num < 0) {
- break;
- }
- numRead += num;
- newcrc.update(b, 0, num);
- }
- stm.close();
-
- if (numRead != length) {
- LOG.info("Number of bytes read " + numRead +
- " does not match file size " + length);
- return false;
- }
-
- LOG.info(" Newcrc " + newcrc.getValue() + " old crc " + crc);
- if (newcrc.getValue() != crc) {
- LOG.info("CRC mismatch of file " + name + ": " + newcrc + " vs. " + crc);
- return false;
- }
- return true;
- }
- //
- // validates the contents of raid recovery log file
- //
- public static void validateLogFile(FileSystem fileSys, Path logDir)
- throws IOException {
- FileStatus f = fileSys.listStatus(logDir)[0];
- FSDataInputStream stm = fileSys.open(f.getPath());
- try {
- BufferedReader reader = new BufferedReader(new InputStreamReader(stm));
- assertEquals("Recovery attempt log", reader.readLine());
- assertTrue(Pattern.matches("Source path : /user/dhruba/raidtest/.*",
- reader.readLine()));
- assertTrue(Pattern.matches("Alternate path : .*/destraid",
- reader.readLine()));
- assertEquals("Stripe lentgh : 3", reader.readLine());
- assertTrue(Pattern.matches("Corrupt offset : \\d*", reader.readLine()));
- assertTrue(Pattern.matches("Output from unRaid : " +
- "hdfs://.*/tmp/raid/user/dhruba/raidtest/.*recovered",
- reader.readLine()));
- } finally {
- stm.close();
- }
- LOG.info("Raid HDFS Recovery log verified");
- }
-
- //
- // Delete/Corrupt specified block of file
- //
- public static void corruptBlock(MiniDFSCluster dfs, Path file, ExtendedBlock blockNum,
- int numDataNodes, boolean delete) throws IOException {
- // Now deliberately remove/truncate replicas of blocks
- int numDeleted = 0;
- int numCorrupted = 0;
- for (int i = 0; i < numDataNodes; i++) {
- File block = MiniDFSCluster.getBlockFile(i, blockNum);
- if (block == null || !block.exists()) {
- continue;
- }
- if (delete) {
- block.delete();
- LOG.info("Deleted block " + block);
- numDeleted++;
- } else {
- // Corrupt
- long seekPos = block.length()/2;
- RandomAccessFile raf = new RandomAccessFile(block, "rw");
- raf.seek(seekPos);
- int data = raf.readInt();
- raf.seek(seekPos);
- raf.writeInt(data+1);
- LOG.info("Corrupted block " + block);
- numCorrupted++;
- }
- }
- assertTrue("Nothing corrupted or deleted",
- (numCorrupted + numDeleted) > 0);
- }
-
- public static void corruptBlock(Path file, ExtendedBlock blockNum,
- int numDataNodes, long offset) throws IOException {
- // Now deliberately corrupt replicas of the the block.
- for (int i = 0; i < numDataNodes; i++) {
- File block = MiniDFSCluster.getBlockFile(i, blockNum);
- if (block == null || !block.exists()) {
- continue;
- }
- RandomAccessFile raf = new RandomAccessFile(block, "rw");
- raf.seek(offset);
- int data = raf.readInt();
- raf.seek(offset);
- raf.writeInt(data+1);
- LOG.info("Corrupted block " + block);
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockPlacementPolicyRaid.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockPlacementPolicyRaid.java
deleted file mode 100644
index 84cc534d215..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestBlockPlacementPolicyRaid.java
+++ /dev/null
@@ -1,518 +0,0 @@
-/**
- * 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.server.blockmanagement;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-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.BlockLocation;
-import org.apache.hadoop.fs.FileStatus;
-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.MiniDFSCluster;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlock;
-import org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRaid.CachedFullPathNames;
-import org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRaid.CachedLocatedBlocks;
-import org.apache.hadoop.hdfs.server.blockmanagement.BlockPlacementPolicyRaid.FileType;
-import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
-import org.apache.hadoop.hdfs.server.namenode.INodeFile;
-import org.apache.hadoop.hdfs.server.namenode.NameNodeRaidTestUtil;
-import org.apache.hadoop.hdfs.server.namenode.NameNodeRaidUtil;
-import org.apache.hadoop.net.NetworkTopology;
-import org.apache.hadoop.raid.RaidNode;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class TestBlockPlacementPolicyRaid {
- private Configuration conf = null;
- private MiniDFSCluster cluster = null;
- private FSNamesystem namesystem = null;
- private BlockManager blockManager;
- private NetworkTopology networktopology;
- private BlockPlacementPolicyRaid policy = null;
- private FileSystem fs = null;
- String[] rack1 = {"/rack1"};
- String[] rack2 = {"/rack2"};
- String[] host1 = {"host1.rack1.com"};
- String[] host2 = {"host2.rack2.com"};
- String xorPrefix = null;
- String raidTempPrefix = null;
- String raidrsTempPrefix = null;
- String raidrsHarTempPrefix = null;
-
- final static Log LOG =
- LogFactory.getLog(TestBlockPlacementPolicyRaid.class);
-
- protected void setupCluster() throws IOException {
- conf = new Configuration();
- conf.setLong(DFSConfigKeys.DFS_BLOCKREPORT_INTERVAL_MSEC_KEY, 1000L);
- conf.set("dfs.replication.pending.timeout.sec", "2");
- conf.setLong(DFSConfigKeys.DFS_BLOCK_SIZE_KEY, 1L);
- conf.set("dfs.block.replicator.classname",
- BlockPlacementPolicyRaid.class.getName());
- conf.set(RaidNode.STRIPE_LENGTH_KEY, "2");
- conf.set(RaidNode.RS_PARITY_LENGTH_KEY, "3");
- conf.setInt(DFSConfigKeys.DFS_BYTES_PER_CHECKSUM_KEY, 1);
- // start the cluster with one datanode first
- cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).
- format(true).racks(rack1).hosts(host1).build();
- cluster.waitActive();
- namesystem = cluster.getNameNode().getNamesystem();
- blockManager = namesystem.getBlockManager();
- networktopology = blockManager.getDatanodeManager().getNetworkTopology();
-
- Assert.assertTrue("BlockPlacementPolicy type is not correct.",
- blockManager.getBlockPlacementPolicy() instanceof BlockPlacementPolicyRaid);
- policy = (BlockPlacementPolicyRaid)blockManager.getBlockPlacementPolicy();
- fs = cluster.getFileSystem();
- xorPrefix = RaidNode.xorDestinationPath(conf).toUri().getPath();
- raidTempPrefix = RaidNode.xorTempPrefix(conf);
- raidrsTempPrefix = RaidNode.rsTempPrefix(conf);
- raidrsHarTempPrefix = RaidNode.rsHarTempPrefix(conf);
- }
-
- /**
- * Test that the parity files will be placed at the good locations when we
- * create them.
- */
- @Test
- public void testChooseTargetForRaidFile() throws IOException {
- setupCluster();
- try {
- String src = "/dir/file";
- String parity = raidrsTempPrefix + src;
- DFSTestUtil.createFile(fs, new Path(src), 4, (short)1, 0L);
- DFSTestUtil.waitReplication(fs, new Path(src), (short)1);
- refreshPolicy();
- setBlockPlacementPolicy(namesystem, policy);
- // start 3 more datanodes
- String[] racks = {"/rack2", "/rack2", "/rack2",
- "/rack2", "/rack2", "/rack2"};
- String[] hosts =
- {"host2.rack2.com", "host3.rack2.com", "host4.rack2.com",
- "host5.rack2.com", "host6.rack2.com", "host7.rack2.com"};
- cluster.startDataNodes(conf, 6, true, null, racks, hosts, null);
- int numBlocks = 6;
- DFSTestUtil.createFile(fs, new Path(parity), numBlocks, (short)2, 0L);
- DFSTestUtil.waitReplication(fs, new Path(parity), (short)2);
- FileStatus srcStat = fs.getFileStatus(new Path(src));
- BlockLocation[] srcLoc =
- fs.getFileBlockLocations(srcStat, 0, srcStat.getLen());
- FileStatus parityStat = fs.getFileStatus(new Path(parity));
- BlockLocation[] parityLoc =
- fs.getFileBlockLocations(parityStat, 0, parityStat.getLen());
- int parityLen = RaidNode.rsParityLength(conf);
- for (int i = 0; i < numBlocks / parityLen; i++) {
- Set locations = new HashSet();
- for (int j = 0; j < srcLoc.length; j++) {
- String [] names = srcLoc[j].getNames();
- for (int k = 0; k < names.length; k++) {
- LOG.info("Source block location: " + names[k]);
- locations.add(names[k]);
- }
- }
- for (int j = 0 ; j < parityLen; j++) {
- String[] names = parityLoc[j + i * parityLen].getNames();
- for (int k = 0; k < names.length; k++) {
- LOG.info("Parity block location: " + names[k]);
- Assert.assertTrue(locations.add(names[k]));
- }
- }
- }
- } finally {
- if (cluster != null) {
- cluster.shutdown();
- }
- }
- }
-
- /**
- * Test that the har parity files will be placed at the good locations when we
- * create them.
- */
- @Test
- public void testChooseTargetForHarRaidFile() throws IOException {
- setupCluster();
- try {
- String[] racks = {"/rack2", "/rack2", "/rack2",
- "/rack2", "/rack2", "/rack2"};
- String[] hosts =
- {"host2.rack2.com", "host3.rack2.com", "host4.rack2.com",
- "host5.rack2.com", "host6.rack2.com", "host7.rack2.com"};
- cluster.startDataNodes(conf, 6, true, null, racks, hosts, null);
- String harParity = raidrsHarTempPrefix + "/dir/file";
- int numBlocks = 11;
- DFSTestUtil.createFile(fs, new Path(harParity), numBlocks, (short)1, 0L);
- DFSTestUtil.waitReplication(fs, new Path(harParity), (short)1);
- FileStatus stat = fs.getFileStatus(new Path(harParity));
- BlockLocation[] loc = fs.getFileBlockLocations(stat, 0, stat.getLen());
- int rsParityLength = RaidNode.rsParityLength(conf);
- for (int i = 0; i < numBlocks - rsParityLength; i++) {
- Set locations = new HashSet();
- for (int j = 0; j < rsParityLength; j++) {
- for (int k = 0; k < loc[i + j].getNames().length; k++) {
- // verify that every adjacent 4 blocks are on differnt nodes
- String name = loc[i + j].getNames()[k];
- LOG.info("Har Raid block location: " + name);
- Assert.assertTrue(locations.add(name));
- }
- }
- }
- } finally {
- if (cluster != null) {
- cluster.shutdown();
- }
- }
- }
-
- /**
- * Test BlockPlacementPolicyRaid.CachedLocatedBlocks
- * Verify that the results obtained from cache is the same as
- * the results obtained directly
- */
- @Test
- public void testCachedBlocks() throws IOException {
- setupCluster();
- try {
- String file1 = "/dir/file1";
- String file2 = "/dir/file2";
- DFSTestUtil.createFile(fs, new Path(file1), 3, (short)1, 0L);
- DFSTestUtil.createFile(fs, new Path(file2), 4, (short)1, 0L);
- // test blocks cache
- CachedLocatedBlocks cachedBlocks = new CachedLocatedBlocks(namesystem);
- verifyCachedBlocksResult(cachedBlocks, namesystem, file1);
- verifyCachedBlocksResult(cachedBlocks, namesystem, file1);
- verifyCachedBlocksResult(cachedBlocks, namesystem, file2);
- verifyCachedBlocksResult(cachedBlocks, namesystem, file2);
- try {
- Thread.sleep(1200L);
- } catch (InterruptedException e) {
- }
- verifyCachedBlocksResult(cachedBlocks, namesystem, file2);
- verifyCachedBlocksResult(cachedBlocks, namesystem, file1);
- } finally {
- if (cluster != null) {
- cluster.shutdown();
- }
- }
- }
-
- /**
- * Test BlockPlacementPolicyRaid.CachedFullPathNames
- * Verify that the results obtained from cache is the same as
- * the results obtained directly
- */
- @Test
- public void testCachedPathNames() throws IOException {
- setupCluster();
- try {
- String file1 = "/dir/file1";
- String file2 = "/dir/file2";
- DFSTestUtil.createFile(fs, new Path(file1), 3, (short)1, 0L);
- DFSTestUtil.createFile(fs, new Path(file2), 4, (short)1, 0L);
- // test full path cache
- CachedFullPathNames cachedFullPathNames =
- new CachedFullPathNames(namesystem);
- final BlockCollection[] bcs = NameNodeRaidTestUtil.getBlockCollections(
- namesystem, file1, file2);
-
- verifyCachedFullPathNameResult(cachedFullPathNames, bcs[0]);
- verifyCachedFullPathNameResult(cachedFullPathNames, bcs[0]);
- verifyCachedFullPathNameResult(cachedFullPathNames, bcs[1]);
- verifyCachedFullPathNameResult(cachedFullPathNames, bcs[1]);
- try {
- Thread.sleep(1200L);
- } catch (InterruptedException e) {
- }
- verifyCachedFullPathNameResult(cachedFullPathNames, bcs[1]);
- verifyCachedFullPathNameResult(cachedFullPathNames, bcs[0]);
- } finally {
- if (cluster != null) {
- cluster.shutdown();
- }
- }
- }
- /**
- * Test the result of getCompanionBlocks() on the unraided files
- */
- @Test
- public void testGetCompanionBLocks() throws IOException {
- setupCluster();
- try {
- String file1 = "/dir/file1";
- String file2 = "/raid/dir/file2";
- String file3 = "/raidrs/dir/file3";
- // Set the policy to default policy to place the block in the default way
- setBlockPlacementPolicy(namesystem, new BlockPlacementPolicyDefault(
- conf, namesystem, networktopology));
- DFSTestUtil.createFile(fs, new Path(file1), 3, (short)1, 0L);
- DFSTestUtil.createFile(fs, new Path(file2), 4, (short)1, 0L);
- DFSTestUtil.createFile(fs, new Path(file3), 8, (short)1, 0L);
- Collection companionBlocks;
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, getBlocks(namesystem, file1).get(0).getBlock());
- Assert.assertTrue(companionBlocks == null || companionBlocks.size() == 0);
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, getBlocks(namesystem, file1).get(2).getBlock());
- Assert.assertTrue(companionBlocks == null || companionBlocks.size() == 0);
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, getBlocks(namesystem, file2).get(0).getBlock());
- Assert.assertEquals(1, companionBlocks.size());
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, getBlocks(namesystem, file2).get(3).getBlock());
- Assert.assertEquals(1, companionBlocks.size());
-
- int rsParityLength = RaidNode.rsParityLength(conf);
- companionBlocks = getCompanionBlocks(
- namesystem, policy, getBlocks(namesystem, file3).get(0).getBlock());
- Assert.assertEquals(rsParityLength, companionBlocks.size());
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, getBlocks(namesystem, file3).get(4).getBlock());
- Assert.assertEquals(rsParityLength, companionBlocks.size());
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, getBlocks(namesystem, file3).get(6).getBlock());
- Assert.assertEquals(2, companionBlocks.size());
- } finally {
- if (cluster != null) {
- cluster.shutdown();
- }
- }
- }
-
- static void setBlockPlacementPolicy(
- FSNamesystem namesystem, BlockPlacementPolicy policy) {
- namesystem.writeLock();
- try {
- namesystem.getBlockManager().setBlockPlacementPolicy(policy);
- } finally {
- namesystem.writeUnlock();
- }
- }
-
- /**
- * Test BlockPlacementPolicyRaid actually deletes the correct replica.
- * Start 2 datanodes and create 1 source file and its parity file.
- * 1) Start host1, create the parity file with replication 1
- * 2) Start host2, create the source file with replication 2
- * 3) Set repliation of source file to 1
- * Verify that the policy should delete the block with more companion blocks.
- */
- @Test
- public void testDeleteReplica() throws IOException {
- setupCluster();
- try {
- // Set the policy to default policy to place the block in the default way
- setBlockPlacementPolicy(namesystem, new BlockPlacementPolicyDefault(
- conf, namesystem, networktopology));
- DatanodeDescriptor datanode1 = blockManager.getDatanodeManager(
- ).getDatanodeCyclicIteration("").iterator().next().getValue();
- String source = "/dir/file";
- String parity = xorPrefix + source;
-
- final Path parityPath = new Path(parity);
- DFSTestUtil.createFile(fs, parityPath, 3, (short)1, 0L);
- DFSTestUtil.waitReplication(fs, parityPath, (short)1);
-
- // start one more datanode
- cluster.startDataNodes(conf, 1, true, null, rack2, host2, null);
- DatanodeDescriptor datanode2 = null;
- for(Map.Entry e : blockManager.getDatanodeManager(
- ).getDatanodeCyclicIteration("")) {
- final DatanodeDescriptor d = e.getValue();
- if (!d.getName().equals(datanode1.getName())) {
- datanode2 = d;
- }
- }
- Assert.assertTrue(datanode2 != null);
- cluster.waitActive();
- final Path sourcePath = new Path(source);
- DFSTestUtil.createFile(fs, sourcePath, 5, (short)2, 0L);
- DFSTestUtil.waitReplication(fs, sourcePath, (short)2);
-
- refreshPolicy();
- Assert.assertEquals(parity,
- policy.getParityFile(source));
- Assert.assertEquals(source,
- policy.getSourceFile(parity, xorPrefix));
-
- List sourceBlocks = getBlocks(namesystem, source);
- List parityBlocks = getBlocks(namesystem, parity);
- Assert.assertEquals(5, sourceBlocks.size());
- Assert.assertEquals(3, parityBlocks.size());
-
- // verify the result of getCompanionBlocks()
- Collection companionBlocks;
- companionBlocks = getCompanionBlocks(
- namesystem, policy, sourceBlocks.get(0).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{0, 1}, new int[]{0});
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, sourceBlocks.get(1).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{0, 1}, new int[]{0});
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, sourceBlocks.get(2).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{2, 3}, new int[]{1});
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, sourceBlocks.get(3).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{2, 3}, new int[]{1});
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, sourceBlocks.get(4).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{4}, new int[]{2});
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, parityBlocks.get(0).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{0, 1}, new int[]{0});
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, parityBlocks.get(1).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{2, 3}, new int[]{1});
-
- companionBlocks = getCompanionBlocks(
- namesystem, policy, parityBlocks.get(2).getBlock());
- verifyCompanionBlocks(companionBlocks, sourceBlocks, parityBlocks,
- new int[]{4}, new int[]{2});
-
- // Set the policy back to raid policy. We have to create a new object
- // here to clear the block location cache
- refreshPolicy();
- setBlockPlacementPolicy(namesystem, policy);
- // verify policy deletes the correct blocks. companion blocks should be
- // evenly distributed.
- fs.setReplication(sourcePath, (short)1);
- DFSTestUtil.waitReplication(fs, sourcePath, (short)1);
- Map counters = new HashMap();
- refreshPolicy();
- for (int i = 0; i < parityBlocks.size(); i++) {
- companionBlocks = getCompanionBlocks(
- namesystem, policy, parityBlocks.get(i).getBlock());
-
- counters = BlockPlacementPolicyRaid.countCompanionBlocks(
- companionBlocks, false);
- Assert.assertTrue(counters.get(datanode1.getName()) >= 1 &&
- counters.get(datanode1.getName()) <= 2);
- Assert.assertTrue(counters.get(datanode1.getName()) +
- counters.get(datanode2.getName()) ==
- companionBlocks.size());
-
- counters = BlockPlacementPolicyRaid.countCompanionBlocks(
- companionBlocks, true);
- Assert.assertTrue(counters.get(datanode1.getParent().getName()) >= 1 &&
- counters.get(datanode1.getParent().getName()) <= 2);
- Assert.assertTrue(counters.get(datanode1.getParent().getName()) +
- counters.get(datanode2.getParent().getName()) ==
- companionBlocks.size());
- }
- } finally {
- if (cluster != null) {
- cluster.shutdown();
- }
- }
- }
-
- // create a new BlockPlacementPolicyRaid to clear the cache
- private void refreshPolicy() {
- policy = new BlockPlacementPolicyRaid();
- policy.initialize(conf, namesystem, networktopology);
- }
-
- private void verifyCompanionBlocks(Collection companionBlocks,
- List sourceBlocks, List parityBlocks,
- int[] sourceBlockIndexes, int[] parityBlockIndexes) {
- Set blockSet = new HashSet();
- for (LocatedBlock b : companionBlocks) {
- blockSet.add(b.getBlock());
- }
- Assert.assertEquals(sourceBlockIndexes.length + parityBlockIndexes.length,
- blockSet.size());
- for (int index : sourceBlockIndexes) {
- Assert.assertTrue(blockSet.contains(sourceBlocks.get(index).getBlock()));
- }
- for (int index : parityBlockIndexes) {
- Assert.assertTrue(blockSet.contains(parityBlocks.get(index).getBlock()));
- }
- }
-
- private void verifyCachedFullPathNameResult(
- CachedFullPathNames cachedFullPathNames, BlockCollection bc)
- throws IOException {
- String res1 = bc.getName();
- String res2 = cachedFullPathNames.get(bc);
- LOG.info("Actual path name: " + res1);
- LOG.info("Cached path name: " + res2);
- Assert.assertEquals(cachedFullPathNames.get(bc),
- bc.getName());
- }
-
- private void verifyCachedBlocksResult(CachedLocatedBlocks cachedBlocks,
- FSNamesystem namesystem, String file) throws IOException{
- long len = NameNodeRaidUtil.getFileInfo(namesystem, file, true).getLen();
- List res1 = NameNodeRaidUtil.getBlockLocations(namesystem,
- file, 0L, len, false, false).getLocatedBlocks();
- List res2 = cachedBlocks.get(file);
- for (int i = 0; i < res1.size(); i++) {
- LOG.info("Actual block: " + res1.get(i).getBlock());
- LOG.info("Cached block: " + res2.get(i).getBlock());
- Assert.assertEquals(res1.get(i).getBlock(), res2.get(i).getBlock());
- }
- }
-
- private Collection getCompanionBlocks(
- FSNamesystem namesystem, BlockPlacementPolicyRaid policy,
- ExtendedBlock block) throws IOException {
- INodeFile inode = (INodeFile)blockManager.blocksMap.getBlockCollection(block
- .getLocalBlock());
- FileType type = policy.getFileType(inode.getFullPathName());
- return policy.getCompanionBlocks(inode.getFullPathName(), type,
- block.getLocalBlock());
- }
-
- private List getBlocks(FSNamesystem namesystem, String file)
- throws IOException {
- long len = NameNodeRaidUtil.getFileInfo(namesystem, file, true).getLen();
- return NameNodeRaidUtil.getBlockLocations(namesystem,
- file, 0, len, false, false).getLocatedBlocks();
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRaidTestUtil.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRaidTestUtil.java
deleted file mode 100644
index 967df15632c..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/hdfs/server/namenode/NameNodeRaidTestUtil.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * 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.server.namenode;
-
-import org.apache.hadoop.fs.UnresolvedLinkException;
-import org.apache.hadoop.hdfs.server.blockmanagement.BlockCollection;
-
-public class NameNodeRaidTestUtil {
- public static BlockCollection[] getBlockCollections(final FSNamesystem namesystem,
- final String... files) throws UnresolvedLinkException {
- final BlockCollection[] inodes = new BlockCollection[files.length];
- final FSDirectory dir = namesystem.dir;
- dir.readLock();
- try {
- for(int i = 0; i < files.length; i++) {
- inodes[i] = (BlockCollection)dir.rootDir.getNode(files[i], true);
- }
- return inodes;
- } finally {
- dir.readUnlock();
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixer.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixer.java
deleted file mode 100644
index 960d11e30df..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixer.java
+++ /dev/null
@@ -1,671 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.net.URI;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Random;
-import java.util.zip.CRC32;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-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.MiniDFSCluster;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-import org.apache.hadoop.hdfs.TestRaidDfs;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.mapred.JobConf;
-import org.apache.hadoop.mapred.JobContext;
-import org.apache.hadoop.mapred.MiniMRCluster;
-import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig;
-import org.apache.hadoop.util.JarFinder;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-import org.junit.Test;
-
-
-public class TestBlockFixer {
- final static Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.TestBlockFixer");
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
- final static String CONFIG_FILE = new File(TEST_DIR,
- "test-raid.xml").getAbsolutePath();
- public static final String DistBlockFixer_JAR =
- JarFinder.getJar(DistBlockFixer.class);
- final static long RELOAD_INTERVAL = 1000;
- final static int NUM_DATANODES = 3;
- Configuration conf;
- String namenode = null;
- MiniDFSCluster dfs = null;
- String hftp = null;
- MiniMRCluster mr = null;
- FileSystem fileSys = null;
- RaidNode cnode = null;
- String jobTrackerName = null;
- Random rand = new Random();
-
- /**
- * Tests isXorParityFile and isRsParityFile
- */
- @Test
- public void testIsParityFile() throws IOException {
- Configuration testConf = new Configuration();
- testConf.set("hdfs.raid.locations", "/raid");
- testConf.set("hdfs.raidrs.locations", "/raidrs");
-
- BlockFixer.BlockFixerHelper helper =
- new BlockFixer.BlockFixerHelper(testConf);
-
- assertFalse("incorrectly identified rs parity file as xor parity file",
- helper.isXorParityFile(new Path("/raidrs/test/test")));
- assertTrue("could not identify rs parity file",
- helper.isRsParityFile(new Path("/raidrs/test/test")));
- assertTrue("could not identify xor parity file",
- helper.isXorParityFile(new Path("/raid/test/test")));
- assertFalse("incorrectly identified xor parity file as rs parity file",
- helper.isRsParityFile(new Path("/raid/test/test")));
- }
-
-
- /**
- * Test the filtering of trash files from the list of corrupt files.
- */
- @Test
- public void testTrashFilter() {
- List files = new LinkedList();
- // Paths that do not match the trash pattern.
- Path p1 = new Path("/user/raid/raidtest/f1");
- Path p2 = new Path("/user/.Trash/");
- // Paths that match the trash pattern.
- Path p3 = new Path("/user/raid/.Trash/raidtest/f1");
- Path p4 = new Path("/user/raid/.Trash/");
- files.add(p1);
- files.add(p3);
- files.add(p4);
- files.add(p2);
-
- Configuration conf = new Configuration();
- RaidUtils.filterTrash(conf, files);
-
- assertEquals("expected 2 non-trash files but got " + files.size(),
- 2, files.size());
- for (Path p: files) {
- assertTrue("wrong file returned by filterTrash",
- p == p1 || p == p2);
- }
- }
-
- @Test
- public void testBlockFixLocal() throws Exception {
- implBlockFix(true);
- }
-
- /**
- * Create a file with three stripes, corrupt a block each in two stripes,
- * and wait for the the file to be fixed.
- */
- protected void implBlockFix(boolean local) throws Exception {
- LOG.info("Test testBlockFix started.");
- long blockSize = 8192L;
- int stripeLength = 3;
- mySetup(stripeLength, -1); // never har
- Path file1 = new Path("/user/dhruba/raidtest/file1");
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- long crc1 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 7, blockSize);
- long file1Len = fileSys.getFileStatus(file1).getLen();
- LOG.info("Test testBlockFix created test files");
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.setInt("raid.blockfix.interval", 1000);
- if (local) {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.LocalBlockFixer");
- } else {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.DistBlockFixer");
- }
- localConf.setLong("raid.blockfix.filespertask", 2L);
-
- try {
- cnode = RaidNode.createRaidNode(null, localConf);
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file1, destPath);
- cnode.stop(); cnode.join();
-
- FileStatus srcStat = fileSys.getFileStatus(file1);
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- LocatedBlocks locs = RaidDFSUtil.getBlockLocations(
- dfs, file1.toUri().getPath(), 0, srcStat.getLen());
-
- String[] corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("no corrupt files expected", 0, corruptFiles.length);
- assertEquals("filesFixed() should return 0 before fixing files",
- 0, cnode.blockFixer.filesFixed());
-
- // Corrupt blocks in two different stripes. We can fix them.
- int[] corruptBlockIdxs = new int[]{0, 4, 6};
- for (int idx: corruptBlockIdxs)
- corruptBlock(locs.get(idx).getBlock());
- reportCorruptBlocks(dfs, file1, corruptBlockIdxs, blockSize);
-
- corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("file not corrupted", 1, corruptFiles.length);
- assertEquals("wrong file corrupted",
- corruptFiles[0], file1.toUri().getPath());
- assertEquals("wrong number of corrupt blocks", 3,
- RaidDFSUtil.corruptBlocksInFile(dfs, file1.toUri().getPath(), 0,
- srcStat.getLen()).size());
-
- cnode = RaidNode.createRaidNode(null, localConf);
- long start = Time.now();
- while (cnode.blockFixer.filesFixed() < 1 &&
- Time.now() - start < 120000) {
- LOG.info("Test testBlockFix waiting for files to be fixed.");
- Thread.sleep(1000);
- }
- assertEquals("file not fixed", 1, cnode.blockFixer.filesFixed());
-
- dfs = getDFS(conf, dfs);
- assertTrue("file not fixed",
- TestRaidDfs.validateFile(dfs, file1, file1Len, crc1));
-
- } catch (Exception e) {
- LOG.info("Test testBlockFix Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
- LOG.info("Test testBlockFix completed.");
- }
-
- /**
- * Tests integrity of generated block.
- * Create a file and delete a block entirely. Wait for the block to be
- * regenerated. Now stop RaidNode and corrupt the generated block.
- * Test that corruption in the generated block can be detected by clients.
- */
- protected void generatedBlockTestCommon(String testName, int blockToCorrupt,
- boolean local) throws Exception {
- LOG.info("Test " + testName + " started.");
- long blockSize = 8192L;
- int stripeLength = 3;
- mySetup(stripeLength, -1); // never har
- Path file1 = new Path("/user/dhruba/raidtest/file1");
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- long crc1 = TestRaidDfs.createTestFile(fileSys, file1, 1, 7, blockSize);
- long file1Len = fileSys.getFileStatus(file1).getLen();
- LOG.info("Test " + testName + " created test files");
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.setInt("raid.blockfix.interval", 1000);
- if (local) {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.LocalBlockFixer");
- } else {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.DistBlockFixer");
- }
- localConf.setLong("raid.blockfix.filespertask", 2L);
- try {
- cnode = RaidNode.createRaidNode(null, localConf);
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file1, destPath);
- cnode.stop(); cnode.join();
-
- FileStatus srcStat = fileSys.getFileStatus(file1);
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- LocatedBlocks locs = RaidDFSUtil.getBlockLocations(
- dfs, file1.toUri().getPath(), 0, srcStat.getLen());
-
- String[] corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("no corrupt files expected", 0, corruptFiles.length);
- assertEquals("filesFixed() should return 0 before fixing files",
- 0, cnode.blockFixer.filesFixed());
-
- corruptBlock(locs.get(0).getBlock());
- reportCorruptBlocks(dfs, file1, new int[]{0}, blockSize);
-
- corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("file not corrupted",
- 1, corruptFiles.length);
- assertEquals("wrong file corrupted",
- corruptFiles[0], file1.toUri().getPath());
-
- cnode = RaidNode.createRaidNode(null, localConf);
- long start = Time.now();
- while (cnode.blockFixer.filesFixed() < 1 &&
- Time.now() - start < 120000) {
- LOG.info("Test " + testName + " waiting for files to be fixed.");
- Thread.sleep(1000);
- }
- assertEquals("file not fixed",
- 1, cnode.blockFixer.filesFixed());
-
- // Stop RaidNode
- cnode.stop(); cnode.join(); cnode = null;
-
- // The block has successfully been reconstructed.
- dfs = getDFS(conf, dfs);
- assertTrue("file not fixed",
- TestRaidDfs.validateFile(dfs, file1, file1Len, crc1));
-
- // Now corrupt the generated block.
- locs = RaidDFSUtil.getBlockLocations(
- dfs, file1.toUri().getPath(), 0, srcStat.getLen());
- corruptBlock(locs.get(0).getBlock());
- reportCorruptBlocks(dfs, file1, new int[]{0}, blockSize);
-
- try {
- Thread.sleep(5*1000);
- } catch (InterruptedException ignore) {
- }
- try {
- TestRaidDfs.validateFile(dfs, file1, file1Len, crc1);
- fail("Expected exception not thrown");
- } catch (org.apache.hadoop.fs.ChecksumException ce) {
- } catch (org.apache.hadoop.hdfs.BlockMissingException bme) {
- }
- } catch (Exception e) {
- LOG.info("Test " + testName + " Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
- LOG.info("Test " + testName + " completed.");
- }
-
- /**
- * Tests integrity of generated block.
- * Create a file and delete a block entirely. Wait for the block to be
- * regenerated. Now stop RaidNode and corrupt the generated block.
- * Test that corruption in the generated block can be detected by clients.
- */
- @Test
- public void testGeneratedBlockLocal() throws Exception {
- generatedBlockTestCommon("testGeneratedBlock", 3, true);
- }
-
- /**
- * Tests integrity of generated last block.
- * Create a file and delete a block entirely. Wait for the block to be
- * regenerated. Now stop RaidNode and corrupt the generated block.
- * Test that corruption in the generated block can be detected by clients.
- */
- @Test
- public void testGeneratedLastBlockLocal() throws Exception {
- generatedBlockTestCommon("testGeneratedLastBlock", 6, true);
- }
-
- @Test
- public void testParityBlockFixLocal() throws Exception {
- implParityBlockFix("testParityBlockFixLocal", true);
- }
-
- /**
- * Corrupt a parity file and wait for it to get fixed.
- */
- protected void implParityBlockFix(String testName, boolean local)
- throws Exception {
- LOG.info("Test " + testName + " started.");
- long blockSize = 8192L;
- int stripeLength = 3;
- mySetup(stripeLength, -1); // never har
- Path file1 = new Path("/user/dhruba/raidtest/file1");
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- Path parityFile = new Path("/destraid/user/dhruba/raidtest/file1");
- TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 7, blockSize);
- LOG.info("Test " + testName + " created test files");
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.setInt("raid.blockfix.interval", 1000);
- if (local) {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.LocalBlockFixer");
- } else {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.DistBlockFixer");
- }
- localConf.setLong("raid.blockfix.filespertask", 2L);
-
- try {
- cnode = RaidNode.createRaidNode(null, localConf);
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file1, destPath);
- cnode.stop(); cnode.join();
-
- long parityCRC = getCRC(fileSys, parityFile);
-
- FileStatus parityStat = fileSys.getFileStatus(parityFile);
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- LocatedBlocks locs = RaidDFSUtil.getBlockLocations(
- dfs, parityFile.toUri().getPath(), 0, parityStat.getLen());
-
- String[] corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("no corrupt files expected", 0, corruptFiles.length);
- assertEquals("filesFixed() should return 0 before fixing files",
- 0, cnode.blockFixer.filesFixed());
-
- // Corrupt parity blocks for different stripes.
- int[] corruptBlockIdxs = new int[]{0, 1, 2};
- for (int idx: corruptBlockIdxs)
- corruptBlock(locs.get(idx).getBlock());
- reportCorruptBlocks(dfs, parityFile, corruptBlockIdxs, blockSize);
-
- corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("file not corrupted",
- 1, corruptFiles.length);
- assertEquals("wrong file corrupted",
- corruptFiles[0], parityFile.toUri().getPath());
-
- cnode = RaidNode.createRaidNode(null, localConf);
- long start = Time.now();
- while (cnode.blockFixer.filesFixed() < 1 &&
- Time.now() - start < 120000) {
- LOG.info("Test " + testName + " waiting for files to be fixed.");
- Thread.sleep(1000);
- }
- assertEquals("file not fixed",
- 1, cnode.blockFixer.filesFixed());
-
- long checkCRC = getCRC(fileSys, parityFile);
-
- assertEquals("file not fixed",
- parityCRC, checkCRC);
-
- } catch (Exception e) {
- LOG.info("Test " + testName + " Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
- LOG.info("Test " + testName + " completed.");
- }
-
- @Test
- public void testParityHarBlockFixLocal() throws Exception {
- implParityHarBlockFix("testParityHarBlockFixLocal", true);
- }
-
- protected void implParityHarBlockFix(String testName, boolean local)
- throws Exception {
- LOG.info("Test " + testName + " started.");
- long blockSize = 8192L;
- int stripeLength = 3;
- mySetup(stripeLength, 0); // Time before har = 0 days.
- Path file1 = new Path("/user/dhruba/raidtest/file1");
- // Parity file will have 7 blocks.
- TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 20, blockSize);
- LOG.info("Test " + testName + " created test files");
-
- // create an instance of the RaidNode
- // HAR block size = 2 * src block size = 2 * parity block size.
- Configuration localConf = new Configuration(conf);
- localConf.setLong("har.block.size", blockSize * 2);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.setInt("raid.blockfix.interval", 1000);
- if (local) {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.LocalBlockFixer");
- } else {
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.DistBlockFixer");
- }
- localConf.setLong("raid.blockfix.filespertask", 2L);
-
- try {
- cnode = RaidNode.createRaidNode(null, localConf);
- Path harDirectory =
- new Path("/destraid/user/dhruba/raidtest/raidtest" +
- RaidNode.HAR_SUFFIX);
- long start = Time.now();
- while (Time.now() - start < 1000 * 120) {
- if (fileSys.exists(harDirectory)) {
- break;
- }
- LOG.info("Test " + testName + " waiting for har");
- Thread.sleep(1000);
- }
-
- Path partFile = new Path(harDirectory, "part-0");
- long partCRC = getCRC(fileSys, partFile);
- FileStatus partStat = fileSys.getFileStatus(partFile);
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- LocatedBlocks locs = RaidDFSUtil.getBlockLocations(
- dfs, partFile.toUri().getPath(), 0, partStat.getLen());
- // 7 parity blocks => 4 har blocks.
- assertEquals("wrong number of har blocks",
- 4, locs.getLocatedBlocks().size());
- cnode.stop(); cnode.join();
-
- String[] corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("no corrupt files expected", 0, corruptFiles.length);
- assertEquals("filesFixed() should return 0 before fixing files",
- 0, cnode.blockFixer.filesFixed());
-
- // Corrupt parity blocks for different stripes.
- int[] corruptBlockIdxs = new int[]{0, 3};
- for (int idx: corruptBlockIdxs)
- corruptBlock(locs.get(idx).getBlock());
- reportCorruptBlocks(dfs, partFile, corruptBlockIdxs,
- partStat.getBlockSize());
-
- corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("file not corrupted", 1, corruptFiles.length);
- assertEquals("wrong file corrupted",
- corruptFiles[0], partFile.toUri().getPath());
-
- cnode = RaidNode.createRaidNode(null, localConf);
- start = Time.now();
- while (cnode.blockFixer.filesFixed() < 1 &&
- Time.now() - start < 120000) {
- LOG.info("Test " + testName + " waiting for files to be fixed.");
- Thread.sleep(1000);
- }
- assertEquals("file not fixed",
- 1, cnode.blockFixer.filesFixed());
-
- long checkCRC = getCRC(fileSys, partFile);
-
- assertEquals("file not fixed",
- partCRC, checkCRC);
- } catch (Exception e) {
- LOG.info("Test " + testName + " Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
- LOG.info("Test " + testName + " completed.");
- }
-
-
- protected static DistributedFileSystem getDFS(
- Configuration conf, FileSystem dfs) throws IOException {
- Configuration clientConf = new Configuration(conf);
- clientConf.set("fs.hdfs.impl",
- "org.apache.hadoop.hdfs.DistributedFileSystem");
- clientConf.setBoolean("fs.hdfs.impl.disable.cache", true);
- URI dfsUri = dfs.getUri();
- FileSystem.closeAll();
- return (DistributedFileSystem) FileSystem.get(dfsUri, clientConf);
- }
-
- protected void mySetup(int stripeLength, int timeBeforeHar) throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
-
- conf.set("raid.config.file", CONFIG_FILE);
- conf.setBoolean("raid.config.reload", true);
- conf.setLong("raid.config.reload.interval", RELOAD_INTERVAL);
-
- // scan all policies once every 5 second
- conf.setLong("raid.policy.rescan.interval", 5000);
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- // do not use map-reduce cluster for Raiding
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- conf.set("raid.server.address", "localhost:0");
- conf.setInt("hdfs.raid.stripeLength", stripeLength);
- conf.set("hdfs.raid.locations", "/destraid");
-
- conf.setBoolean("dfs.permissions", false);
-
- conf.set("mapreduce.framework.name", "yarn");
-
- dfs = new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATANODES).build();
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
- namenode = fileSys.getUri().toString();
-
- FileSystem.setDefaultUri(conf, namenode);
- mr = new MiniMRCluster(4, namenode, 3);
- JobConf jobConf = mr.createJobConf();
- jobTrackerName = "localhost:" + jobConf.get(JTConfig.JT_IPC_ADDRESS);
- hftp = "hftp://localhost.localdomain:" + dfs.getNameNodePort();
-
- FileSystem.setDefaultUri(conf, namenode);
- conf.set("mapred.job.tracker", jobTrackerName);
- conf.set("mapreduce.framework.name", "yarn");
- String rmAdress = jobConf.get("yarn.resourcemanager.address");
- if (rmAdress != null) {
- conf.set("yarn.resourcemanager.address", rmAdress);
- }
- String schedulerAdress =
- jobConf.get("yarn.resourcemanager.scheduler.address");
- if (schedulerAdress != null) {
- conf.set("yarn.resourcemanager.scheduler.address", schedulerAdress);
- }
- String jobHistoryAddress =
- jobConf.get("mapreduce.jobhistory.address");
- if (jobHistoryAddress != null) {
- conf.set("mapreduce.jobhistory.address", jobHistoryAddress);
- }
- conf.set(JobContext.JAR, TestBlockFixer.DistBlockFixer_JAR);
-
- FileWriter fileWriter = new FileWriter(CONFIG_FILE);
- fileWriter.write("\n");
- String str = " " +
- " " +
- " " +
- "xor " +
- " /destraid " +
- " " +
- "targetReplication " +
- "1 " +
- "after RAIDing, decrease the replication factor of a file to this value." +
- " " +
- " " +
- " " +
- "metaReplication " +
- "1 " +
- " replication factor of parity file" +
- " " +
- " " +
- " " +
- "modTimePeriod " +
- "2000 " +
- " time (milliseconds) after a file is modified to make it " +
- "a candidate for RAIDing " +
- " " +
- " ";
- if (timeBeforeHar >= 0) {
- str +=
- " " +
- "time_before_har " +
- "" + timeBeforeHar + " " +
- " amount of time waited before har'ing parity files" +
- " " +
- " ";
- }
-
- str +=
- "" +
- "" +
- "";
- fileWriter.write(str);
- fileWriter.close();
- }
-
- protected void myTearDown() throws Exception {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- if (mr != null) { mr.shutdown(); }
- if (dfs != null) { dfs.shutdown(); }
- }
-
- public static long getCRC(FileSystem fs, Path p) throws IOException {
- CRC32 crc = new CRC32();
- FSDataInputStream stm = fs.open(p);
- int b;
- while ((b = stm.read())>=0) {
- crc.update(b);
- }
- stm.close();
- return crc.getValue();
- }
-
- void corruptBlock(ExtendedBlock block) throws IOException {
- assertTrue("Could not corrupt block",
- dfs.corruptBlockOnDataNodes(block) > 0);
- }
-
- static void reportCorruptBlocks(FileSystem fs, Path file, int[] idxs,
- long blockSize) throws IOException {
-
- FSDataInputStream in = fs.open(file);
- for (int idx: idxs) {
- long offset = idx * blockSize;
- LOG.info("Reporting corrupt block " + file + ":" + offset);
- in.seek(offset);
- try {
- in.readFully(new byte[(int)blockSize]);
- fail("Expected exception not thrown for " + file + ":" + offset);
- } catch (org.apache.hadoop.fs.ChecksumException e) {
- } catch (org.apache.hadoop.hdfs.BlockMissingException bme) {
- }
- }
- }
-}
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerBlockFixDist.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerBlockFixDist.java
deleted file mode 100644
index 6eeba5be4f5..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerBlockFixDist.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * 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.raid;
-import org.junit.Test;
-
-public class TestBlockFixerBlockFixDist extends TestBlockFixer {
- @Test
- public void testBlockFixDist() throws Exception {
- implBlockFix(false);
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerDistConcurrency.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerDistConcurrency.java
deleted file mode 100644
index c4257722743..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerDistConcurrency.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hdfs.DistributedFileSystem;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-import org.apache.hadoop.hdfs.TestRaidDfs;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-import org.junit.Test;
-
-public class TestBlockFixerDistConcurrency extends TestBlockFixer {
- /**
- * tests that we can have 2 concurrent jobs fixing files
- * (dist block fixer)
- */
- @Test
- public void testConcurrentJobs() throws Exception {
- LOG.info("Test testConcurrentJobs started.");
- long blockSize = 8192L;
- int stripeLength = 3;
- mySetup(stripeLength, -1); // never har
- Path file1 = new Path("/user/dhruba/raidtest/file1");
- Path file2 = new Path("/user/dhruba/raidtest/file2");
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- long crc1 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 20, blockSize);
- long crc2 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file2,
- 1, 20, blockSize);
- long file1Len = fileSys.getFileStatus(file1).getLen();
- long file2Len = fileSys.getFileStatus(file2).getLen();
- LOG.info("Test testConcurrentJobs created test files");
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.setInt("raid.blockfix.interval", 1000);
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.DistBlockFixer");
- localConf.setLong("raid.blockfix.filespertask", 2L);
-
- try {
- cnode = RaidNode.createRaidNode(null, localConf);
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file1, destPath);
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file2, destPath);
- cnode.stop(); cnode.join();
-
- FileStatus file1Stat = fileSys.getFileStatus(file1);
- FileStatus file2Stat = fileSys.getFileStatus(file2);
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- LocatedBlocks file1Loc =
- RaidDFSUtil.getBlockLocations(dfs, file1.toUri().getPath(),
- 0, file1Stat.getLen());
- LocatedBlocks file2Loc =
- RaidDFSUtil.getBlockLocations(dfs, file2.toUri().getPath(),
- 0, file2Stat.getLen());
-
- String[] corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("no corrupt files expected", 0, corruptFiles.length);
- assertEquals("filesFixed() should return 0 before fixing files",
- 0, cnode.blockFixer.filesFixed());
-
- // corrupt file1
- int[] corruptBlockIdxs = new int[]{0, 4, 6};
- for (int idx: corruptBlockIdxs)
- corruptBlock(file1Loc.get(idx).getBlock());
- reportCorruptBlocks(dfs, file1, corruptBlockIdxs, blockSize);
-
- cnode = RaidNode.createRaidNode(null, localConf);
- DistBlockFixer blockFixer = (DistBlockFixer) cnode.blockFixer;
- long start = Time.now();
-
- while (blockFixer.jobsRunning() < 1 &&
- Time.now() - start < 240000) {
- LOG.info("Test testBlockFix waiting for fixing job 1 to start");
- Thread.sleep(10);
- }
- assertEquals("job 1 not running", 1, blockFixer.jobsRunning());
-
- // corrupt file2
- for (int idx: corruptBlockIdxs)
- corruptBlock(file2Loc.get(idx).getBlock());
- reportCorruptBlocks(dfs, file2, corruptBlockIdxs, blockSize);
-
- while (blockFixer.jobsRunning() < 2 &&
- Time.now() - start < 240000) {
- LOG.info("Test testBlockFix waiting for fixing job 2 to start");
- Thread.sleep(10);
- }
- assertEquals("2 jobs not running", 2, blockFixer.jobsRunning());
-
- while (blockFixer.filesFixed() < 2 &&
- Time.now() - start < 240000) {
- LOG.info("Test testBlockFix waiting for files to be fixed.");
- Thread.sleep(10);
- }
- assertEquals("files not fixed", 2, blockFixer.filesFixed());
-
- dfs = getDFS(conf, dfs);
-
- try {
- Thread.sleep(5*1000);
- } catch (InterruptedException ignore) {
- }
- assertTrue("file not fixed",
- TestRaidDfs.validateFile(dfs, file1, file1Len, crc1));
- assertTrue("file not fixed",
- TestRaidDfs.validateFile(dfs, file2, file2Len, crc2));
- } catch (Exception e) {
- LOG.info("Test testConcurrentJobs exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
-
- }
-
- /**
- * tests that the distributed block fixer obeys
- * the limit on how many files to fix simultaneously
- */
- @Test
- public void testMaxPendingFiles() throws Exception {
- LOG.info("Test testMaxPendingFiles started.");
- long blockSize = 8192L;
- int stripeLength = 3;
- mySetup(stripeLength, -1); // never har
- Path file1 = new Path("/user/dhruba/raidtest/file1");
- Path file2 = new Path("/user/dhruba/raidtest/file2");
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- long crc1 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 20, blockSize);
- long crc2 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file2,
- 1, 20, blockSize);
- long file1Len = fileSys.getFileStatus(file1).getLen();
- long file2Len = fileSys.getFileStatus(file2).getLen();
- LOG.info("Test testMaxPendingFiles created test files");
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.setInt("raid.blockfix.interval", 1000);
- localConf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.DistBlockFixer");
- localConf.setLong("raid.blockfix.filespertask", 2L);
- localConf.setLong("raid.blockfix.maxpendingfiles", 1L);
-
- try {
- cnode = RaidNode.createRaidNode(null, localConf);
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file1, destPath);
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file2, destPath);
- cnode.stop(); cnode.join();
-
- FileStatus file1Stat = fileSys.getFileStatus(file1);
- FileStatus file2Stat = fileSys.getFileStatus(file2);
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- LocatedBlocks file1Loc =
- RaidDFSUtil.getBlockLocations(dfs, file1.toUri().getPath(),
- 0, file1Stat.getLen());
- LocatedBlocks file2Loc =
- RaidDFSUtil.getBlockLocations(dfs, file2.toUri().getPath(),
- 0, file2Stat.getLen());
-
- String[] corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals("no corrupt files expected", 0, corruptFiles.length);
- assertEquals("filesFixed() should return 0 before fixing files",
- 0, cnode.blockFixer.filesFixed());
-
- // corrupt file1
- int[] corruptBlockIdxs = new int[]{0, 4, 6};
- for (int idx: corruptBlockIdxs)
- corruptBlock(file1Loc.get(idx).getBlock());
- reportCorruptBlocks(dfs, file1, corruptBlockIdxs, blockSize);
- corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
-
- cnode = RaidNode.createRaidNode(null, localConf);
- DistBlockFixer blockFixer = (DistBlockFixer) cnode.blockFixer;
- long start = Time.now();
-
- while (blockFixer.jobsRunning() < 1 &&
- Time.now() - start < 240000) {
- LOG.info("Test testBlockFix waiting for fixing job 1 to start");
- Thread.sleep(10);
- }
- assertEquals("job not running", 1, blockFixer.jobsRunning());
-
- // corrupt file2
- for (int idx: corruptBlockIdxs)
- corruptBlock(file2Loc.get(idx).getBlock());
- reportCorruptBlocks(dfs, file2, corruptBlockIdxs, blockSize);
- corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
-
- // wait until both files are fixed
- while (blockFixer.filesFixed() < 2 &&
- Time.now() - start < 240000) {
- // make sure the block fixer does not start a second job while
- // the first one is still running
- assertTrue("too many jobs running", blockFixer.jobsRunning() <= 1);
- Thread.sleep(10);
- }
- assertEquals("files not fixed", 2, blockFixer.filesFixed());
-
- dfs = getDFS(conf, dfs);
-
- try {
- Thread.sleep(5*1000);
- } catch (InterruptedException ignore) {
- }
- assertTrue("file not fixed",
- TestRaidDfs.validateFile(dfs, file1, file1Len, crc1));
- assertTrue("file not fixed",
- TestRaidDfs.validateFile(dfs, file2, file2Len, crc2));
- } catch (Exception e) {
- LOG.info("Test testMaxPendingFiles exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
-
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerGeneratedBlockDist.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerGeneratedBlockDist.java
deleted file mode 100644
index bb061a004b6..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerGeneratedBlockDist.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * 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.raid;
-
-import org.junit.Test;
-
-public class TestBlockFixerGeneratedBlockDist extends TestBlockFixer {
- /**
- * Tests integrity of generated block.
- * Create a file and delete a block entirely. Wait for the block to be
- * regenerated. Now stop RaidNode and corrupt the generated block.
- * Test that corruption in the generated block can be detected by clients.
- */
- @Test
- public void testGeneratedBlockDist() throws Exception {
- generatedBlockTestCommon("testGeneratedBlock", 3, false);
- }
-
- /**
- * Tests integrity of generated last block.
- * Create a file and delete a block entirely. Wait for the block to be
- * regenerated. Now stop RaidNode and corrupt the generated block.
- * Test that corruption in the generated block can be detected by clients.
- */
- @Test
- public void testGeneratedLastBlockDist() throws Exception {
- generatedBlockTestCommon("testGeneratedLastBlock", 6, false);
- }
-
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerParityBlockFixDist.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerParityBlockFixDist.java
deleted file mode 100644
index 91d2ae54c29..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestBlockFixerParityBlockFixDist.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * 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.raid;
-
-import org.junit.Test;
-
-public class TestBlockFixerParityBlockFixDist extends TestBlockFixer {
- @Test
- public void testParityBlockFixDist() throws Exception {
- implParityBlockFix("testParityBlockFixDist", false);
- }
-
- @Test
- public void testParityHarBlockFixDist() throws Exception {
- implParityHarBlockFix("testParityHarBlockFixDist", false);
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestDirectoryTraversal.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestDirectoryTraversal.java
deleted file mode 100644
index 89cb6334fe0..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestDirectoryTraversal.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hdfs.MiniDFSCluster;
-import org.apache.hadoop.mapred.Reporter;
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.util.Time;
-import org.junit.Test;
-
-public class TestDirectoryTraversal {
- final static Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.TestDirectoryTraversal");
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
-
- MiniDFSCluster dfs = null;
- FileSystem fs = null;
- Configuration conf = null;
-
- /**
- * Test basic enumeration.
- */
- @Test
- public void testEnumeration() throws IOException {
- mySetup();
-
- try {
- Path topDir = new Path(TEST_DIR + "/testenumeration");
-
- createTestTree(topDir);
-
- LOG.info("Enumerating files");
- List startPaths = new LinkedList();
- startPaths.add(fs.getFileStatus(topDir));
- DirectoryTraversal dt = new DirectoryTraversal(fs, startPaths, 2);
-
- List selected = new LinkedList();
- while (true) {
- FileStatus f = dt.getNextFile();
- if (f == null) break;
- assertEquals(false, f.isDir());
- LOG.info(f.getPath());
- selected.add(f);
- }
- assertEquals(5, selected.size());
-
- LOG.info("Enumerating directories");
- startPaths.clear();
- startPaths.add(fs.getFileStatus(topDir));
- dt = new DirectoryTraversal(fs, startPaths);
- selected.clear();
- while (true) {
- FileStatus dir = dt.getNextDirectory();
- if (dir == null) break;
- assertEquals(true, dir.isDir());
- LOG.info(dir.getPath());
- selected.add(dir);
- }
- assertEquals(4, selected.size());
- } finally {
- myTearDown();
- }
- }
-
- @Test
- public void testSuspension() throws IOException {
- LOG.info("Starting testSuspension");
- mySetup();
-
- try {
- Path topDir = new Path(TEST_DIR + "/testenumeration");
-
- createTestTree(topDir);
-
- String top = topDir.toString();
- List startPaths = new LinkedList();
- startPaths.add(fs.getFileStatus(new Path(top + "/a")));
- startPaths.add(fs.getFileStatus(new Path(top + "/b")));
- DirectoryTraversal dt = new DirectoryTraversal(fs, startPaths);
-
- int limit = 2;
- short targetRepl = 1;
- Path raid = new Path("/raid");
- DirectoryTraversal.FileFilter filter =
- new RaidFilter.TimeBasedFilter(conf,
- RaidNode.xorDestinationPath(conf), 1, Time.now(), 0);
- List selected = dt.getFilteredFiles(filter, limit);
- for (FileStatus f: selected) {
- LOG.info(f.getPath());
- }
- assertEquals(limit, selected.size());
-
- selected = dt.getFilteredFiles(filter, limit);
- for (FileStatus f: selected) {
- LOG.info(f.getPath());
- }
- assertEquals(limit, selected.size());
- } finally {
- myTearDown();
- }
- }
-
- @Test
- public void testFileFilter() throws IOException {
- mySetup();
-
- try {
- Path topDir = new Path(TEST_DIR + "/testFileFilter");
- int targetRepl = 1;
- createTestTree(topDir);
- Path file = new Path(topDir.toString() + "/a/f1");
- FileStatus stat = fs.getFileStatus(file);
- PolicyInfo info = new PolicyInfo("testFileFilter", conf);
- info.setSrcPath(topDir.toString());
- info.setErasureCode("rs");
- info.setDescription("test policy");
- info.setProperty("targetReplication", "1");
- info.setProperty("metaReplication", "1");
-
- DirectoryTraversal.FileFilter timeBasedXORFilter =
- new RaidFilter.TimeBasedFilter(conf,
- RaidNode.xorDestinationPath(conf), targetRepl,
- Time.now(), 0);
- DirectoryTraversal.FileFilter timeBasedRSFilter =
- new RaidFilter.TimeBasedFilter(conf,
- RaidNode.rsDestinationPath(conf), targetRepl,
- Time.now(), 0);
- DirectoryTraversal.FileFilter preferenceForRSFilter =
- new RaidFilter.PreferenceFilter(
- conf, RaidNode.rsDestinationPath(conf),
- RaidNode.xorDestinationPath(conf), 1, Time.now(), 0);
-
- assertTrue(timeBasedXORFilter.check(stat));
- assertTrue(timeBasedRSFilter.check(stat));
- assertTrue(preferenceForRSFilter.check(stat));
-
- RaidNode.doRaid(
- conf, info, stat, new RaidNode.Statistics(), Reporter.NULL);
-
- assertTrue(timeBasedXORFilter.check(stat));
- assertFalse(timeBasedRSFilter.check(stat));
- assertFalse(preferenceForRSFilter.check(stat));
- } finally {
- myTearDown();
- }
- }
-
- /**
- * Creates a test directory tree.
- * top
- * / | \
- * / | f5
- * a b___
- * / \ |\ \
- * f1 f2 f3f4 c
- */
- private void createTestTree(Path topDir) throws IOException {
- String top = topDir.toString();
- fs.delete(topDir, true);
-
- fs.mkdirs(topDir);
- fs.create(new Path(top + "/f5")).close();
-
- fs.mkdirs(new Path(top + "/a"));
- createTestFile(new Path(top + "/a/f1"));
- createTestFile(new Path(top + "/a/f2"));
-
- fs.mkdirs(new Path(top + "/b"));
- fs.mkdirs(new Path(top + "/b/c"));
- createTestFile(new Path(top + "/b/f3"));
- createTestFile(new Path(top + "/b/f4"));
- }
-
- private void createTestFile(Path file) throws IOException {
- long blockSize = 8192;
- byte[] bytes = new byte[(int)blockSize];
- FSDataOutputStream stm = fs.create(file, false, 4096, (short)1, blockSize);
- stm.write(bytes);
- stm.write(bytes);
- stm.write(bytes);
- stm.close();
- FileStatus stat = fs.getFileStatus(file);
- assertEquals(blockSize, stat.getBlockSize());
- }
-
- private void mySetup() throws IOException {
- conf = new Configuration();
- dfs = new MiniDFSCluster.Builder(conf).numDataNodes(3).build();
- dfs.waitActive();
- fs = dfs.getFileSystem();
- }
-
- private void myTearDown() {
- if (dfs != null) { dfs.shutdown(); }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestErasureCodes.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestErasureCodes.java
deleted file mode 100644
index d5e4b8e9fdb..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestErasureCodes.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.HashSet;
-import java.util.Random;
-import java.util.Set;
-
-import org.apache.hadoop.util.Time;
-import org.junit.Test;
-
-public class TestErasureCodes {
- final int TEST_CODES = 100;
- final int TEST_TIMES = 1000;
- final Random RAND = new Random();
-
- @Test
- public void testEncodeDecode() {
- for (int n = 0; n < TEST_CODES; n++) {
- int stripeSize = RAND.nextInt(99) + 1; // 1, 2, 3, ... 100
- int paritySize = RAND.nextInt(9) + 1; //1, 2, 3, 4, ... 10
- ErasureCode ec = new ReedSolomonCode(stripeSize, paritySize);
- for (int m = 0; m < TEST_TIMES; m++) {
- int symbolMax = (int) Math.pow(2, ec.symbolSize());
- int[] message = new int[stripeSize];
- for (int i = 0; i < stripeSize; i++) {
- message[i] = RAND.nextInt(symbolMax);
- }
- int[] parity = new int[paritySize];
- ec.encode(message, parity);
- int[] data = new int[stripeSize + paritySize];
- int[] copy = new int[data.length];
- for (int i = 0; i < paritySize; i++) {
- data[i] = parity[i];
- copy[i] = parity[i];
- }
- for (int i = 0; i < stripeSize; i++) {
- data[i + paritySize] = message[i];
- copy[i + paritySize] = message[i];
- }
- int erasedLen = paritySize == 1 ? 1 : RAND.nextInt(paritySize - 1) + 1;
- int[] erasedLocations = randomErasedLocation(erasedLen, data.length);
- for (int i = 0; i < erasedLocations.length; i++) {
- data[erasedLocations[i]] = 0;
- }
- int[] erasedValues = new int[erasedLen];
- ec.decode(data, erasedLocations, erasedValues);
- for (int i = 0; i < erasedLen; i++) {
- assertEquals("Decode failed", copy[erasedLocations[i]], erasedValues[i]);
- }
- }
- }
- }
-
- @Test
- public void testRSPerformance() {
- int stripeSize = 10;
- int paritySize = 4;
- ErasureCode ec = new ReedSolomonCode(stripeSize, paritySize);
- int symbolMax = (int) Math.pow(2, ec.symbolSize());
- byte[][] message = new byte[stripeSize][];
- int bufsize = 1024 * 1024 * 10;
- for (int i = 0; i < stripeSize; i++) {
- message[i] = new byte[bufsize];
- for (int j = 0; j < bufsize; j++) {
- message[i][j] = (byte) RAND.nextInt(symbolMax);
- }
- }
- byte[][] parity = new byte[paritySize][];
- for (int i = 0; i < paritySize; i++) {
- parity[i] = new byte[bufsize];
- }
- long encodeStart = Time.now();
- int[] tmpIn = new int[stripeSize];
- int[] tmpOut = new int[paritySize];
- for (int i = 0; i < bufsize; i++) {
- // Copy message.
- for (int j = 0; j < stripeSize; j++) tmpIn[j] = 0x000000FF & message[j][i];
- ec.encode(tmpIn, tmpOut);
- // Copy parity.
- for (int j = 0; j < paritySize; j++) parity[j][i] = (byte)tmpOut[j];
- }
- long encodeEnd = Time.now();
- float encodeMSecs = (encodeEnd - encodeStart);
- System.out.println("Time to encode rs = " + encodeMSecs +
- "msec (" + message[0].length / (1000 * encodeMSecs) + " MB/s)");
-
- // Copy erased array.
- int[] data = new int[paritySize + stripeSize];
- // 4th location is the 0th symbol in the message
- int[] erasedLocations = new int[]{4, 1, 5, 7};
- int[] erasedValues = new int[erasedLocations.length];
- byte[] copy = new byte[bufsize];
- for (int j = 0; j < bufsize; j++) {
- copy[j] = message[0][j];
- message[0][j] = 0;
- }
-
- long decodeStart = Time.now();
- for (int i = 0; i < bufsize; i++) {
- // Copy parity first.
- for (int j = 0; j < paritySize; j++) {
- data[j] = 0x000000FF & parity[j][i];
- }
- // Copy message. Skip 0 as the erased symbol
- for (int j = 1; j < stripeSize; j++) {
- data[j + paritySize] = 0x000000FF & message[j][i];
- }
- // Use 0, 2, 3, 6, 8, 9, 10, 11, 12, 13th symbol to reconstruct the data
- ec.decode(data, erasedLocations, erasedValues);
- message[0][i] = (byte)erasedValues[0];
- }
- long decodeEnd = Time.now();
- float decodeMSecs = (decodeEnd - decodeStart);
- System.out.println("Time to decode = " + decodeMSecs +
- "msec (" + message[0].length / (1000 * decodeMSecs) + " MB/s)");
- assertTrue("Decode failed", java.util.Arrays.equals(copy, message[0]));
- }
-
- @Test
- public void testXorPerformance() {
- java.util.Random RAND = new java.util.Random();
- int stripeSize = 10;
- byte[][] message = new byte[stripeSize][];
- int bufsize = 1024 * 1024 * 10;
- for (int i = 0; i < stripeSize; i++) {
- message[i] = new byte[bufsize];
- for (int j = 0; j < bufsize; j++) {
- message[i][j] = (byte)RAND.nextInt(256);
- }
- }
- byte[] parity = new byte[bufsize];
-
- long encodeStart = Time.now();
- for (int i = 0; i < bufsize; i++) {
- for (int j = 0; j < stripeSize; j++) parity[i] ^= message[j][i];
- }
- long encodeEnd = Time.now();
- float encodeMSecs = encodeEnd - encodeStart;
- System.out.println("Time to encode xor = " + encodeMSecs +
- " msec (" + message[0].length / (1000 * encodeMSecs) + "MB/s)");
-
- byte[] copy = new byte[bufsize];
- for (int j = 0; j < bufsize; j++) {
- copy[j] = message[0][j];
- message[0][j] = 0;
- }
-
- long decodeStart = Time.now();
- for (int i = 0; i < bufsize; i++) {
- for (int j = 1; j < stripeSize; j++) message[0][i] ^= message[j][i];
- message[0][i] ^= parity[i];
- }
- long decodeEnd = Time.now();
- float decodeMSecs = decodeEnd - decodeStart;
- System.out.println("Time to decode xor = " + decodeMSecs +
- " msec (" + message[0].length / (1000 * decodeMSecs) + "MB/s)");
- assertTrue("Decode failed", java.util.Arrays.equals(copy, message[0]));
- }
-
- @Test
- public void testComputeErrorLocations() {
- for (int i = 0; i < TEST_TIMES; ++i) {
- verifyErrorLocations(10, 4, 1);
- verifyErrorLocations(10, 4, 2);
- }
- }
-
- public void verifyErrorLocations(int stripeSize, int paritySize, int errors) {
- int[] message = new int[stripeSize];
- int[] parity = new int[paritySize];
- Set errorLocations = new HashSet();
- for (int i = 0; i < message.length; ++i) {
- message[i] = RAND.nextInt(256);
- }
- while (errorLocations.size() < errors) {
- int loc = RAND.nextInt(stripeSize + paritySize);
- errorLocations.add(loc);
- }
- ReedSolomonCode codec = new ReedSolomonCode(stripeSize, paritySize);
- codec.encode(message, parity);
- int[] data = combineArrays(parity, message);
- for (Integer i : errorLocations) {
- data[i] = randError(data[i]);
- }
- Set recoveredLocations = new HashSet();
- boolean resolved = codec.computeErrorLocations(data, recoveredLocations);
- if (resolved) {
- assertEquals(errorLocations, recoveredLocations);
- }
- }
-
- private int randError(int actual) {
- while (true) {
- int r = RAND.nextInt(256);
- if (r != actual) {
- return r;
- }
- }
- }
-
- private int[] combineArrays(int[] array1, int[] array2) {
- int[] result = new int[array1.length + array2.length];
- for (int i = 0; i < array1.length; ++i) {
- result[i] = array1[i];
- }
- for (int i = 0; i < array2.length; ++i) {
- result[i + array1.length] = array2[i];
- }
- return result;
- }
-
- private int[] randomErasedLocation(int erasedLen, int dataLen) {
- int[] erasedLocations = new int[erasedLen];
- for (int i = 0; i < erasedLen; i++) {
- Set s = new HashSet();
- while (s.size() != erasedLen) {
- s.add(RAND.nextInt(dataLen));
- }
- int t = 0;
- for (int erased : s) {
- erasedLocations[t++] = erased;
- }
- }
- return erasedLocations;
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestGaloisField.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestGaloisField.java
deleted file mode 100644
index 523a79e8018..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestGaloisField.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertTrue;
-
-import java.util.HashSet;
-import java.util.Random;
-import java.util.Set;
-
-import org.junit.Test;
-
-public class TestGaloisField {
-
- final int TEST_TIMES = 10000;
- final Random RAND = new Random();
- final static GaloisField GF = GaloisField.getInstance();
-
- private int randGF() {
- return 0x000000FF & RAND.nextInt(GF.getFieldSize());
- }
- private int[] randGFPoly(int len) {
- int[] result = new int[len];
- for (int i = 0; i < len; i++) {
- result[i] = randGF();
- }
- return result;
- }
-
- @Test
- public void testGetInstance() {
- GaloisField gf1 = GaloisField.getInstance(256, 285);
- GaloisField gf2 = GaloisField.getInstance();
- GaloisField gf3 = GaloisField.getInstance(128, 137);
- GaloisField gf4 = GaloisField.getInstance(128, 137);
- GaloisField gf5 = GaloisField.getInstance(512, 529);
- GaloisField gf6 = GaloisField.getInstance(512, 529);
- assertTrue(gf1 == gf2);
- assertTrue(gf3 == gf4);
- assertTrue(gf5 == gf6);
- }
-
- @Test
- public void testDistributivity() {
- for (int i = 0; i < TEST_TIMES; i++) {
- int a = RAND.nextInt(GF.getFieldSize());
- int b = RAND.nextInt(GF.getFieldSize());
- int c = RAND.nextInt(GF.getFieldSize());
- int result1 = GF.multiply(a, GF.add(b, c));
- int result2 = GF.add(GF.multiply(a, b), GF.multiply(a, c));
- assertTrue("Distributivity test #" + i + " failed: " + a + ", " + b + ", "
- + c, result1 == result2);
- }
- }
-
- @Test
- public void testDevision() {
- for (int i = 0; i < TEST_TIMES; i++) {
- int a = RAND.nextInt(GF.getFieldSize());
- int b = RAND.nextInt(GF.getFieldSize());
- if (b == 0) {
- continue;
- }
- int c = GF.divide(a, b);
- assertTrue("Division test #" + i + " failed: " + a + "/" + b + " = " + c,
- a == GF.multiply(c, b));
- }
- }
-
- @Test
- public void testPower() {
- for (int i = 0; i < TEST_TIMES; i++) {
- int a = randGF();
- int n = RAND.nextInt(10);
- int result1 = GF.power(a, n);
- int result2 = 1;
- for (int j = 0; j < n; j++) {
- result2 = GF.multiply(result2, a);
- }
- assert(result1 == result2);
- }
- }
-
- @Test
- public void testPolynomialDistributivity() {
- final int TEST_LEN = 15;
- for (int i = 0; i < TEST_TIMES; i++) {
- int[] a = randGFPoly(RAND.nextInt(TEST_LEN - 1) + 1);
- int[] b = randGFPoly(RAND.nextInt(TEST_LEN - 1) + 1);
- int[] c = randGFPoly(RAND.nextInt(TEST_LEN - 1) + 1);
- int[] result1 = GF.multiply(a, GF.add(b, c));
- int[] result2 = GF.add(GF.multiply(a, b), GF.multiply(a, c));
- assertTrue("Distributivity test on polynomials failed",
- java.util.Arrays.equals(result1, result2));
- }
- }
-
- @Test
- public void testSubstitute() {
- final int TEST_LEN = 15;
- for (int i = 0; i < TEST_TIMES; i++) {
- int[] a = randGFPoly(RAND.nextInt(TEST_LEN - 1) + 1);
- int[] b = randGFPoly(RAND.nextInt(TEST_LEN - 1) + 1);
- int[] c = randGFPoly(RAND.nextInt(TEST_LEN - 1) + 1);
- int x = randGF();
- // (a * b * c)(x)
- int result1 = GF.substitute(GF.multiply(GF.multiply(a, b), c), x);
- // a(x) * b(x) * c(x)
- int result2 =
- GF.multiply(GF.multiply(GF.substitute(a, x), GF.substitute(b, x)),
- GF.substitute(c, x));
- assertTrue("Substitute test on polynomial failed",
- result1 == result2);
- }
- }
-
- @Test
- public void testSolveVandermondeSystem() {
- final int TEST_LEN = 15;
- for (int i = 0; i < TEST_TIMES; i++) {
- int[] z = randGFPoly(RAND.nextInt(TEST_LEN - 1) + 1);
- // generate distinct values for x
- int[] x = new int[z.length];
- Set s = new HashSet();
- while (s.size() != z.length) {
- s.add(randGF());
- }
- int t = 0;
- for (int v : s) {
- x[t++] = v;
- }
- // compute the output for the Vandermonde system
- int[] y = new int[x.length];
- for (int j = 0; j < x.length; j++) {
- y[j] = 0;
- for (int k = 0; k < x.length; k++) {
- //y[j] = y[j] + z[k] * pow(x[k], j);
- y[j] = GF.add(y[j], GF.multiply(GF.power(x[k], j), z[k]));
- }
- }
-
- GF.solveVandermondeSystem(x, y);
- assertTrue("Solving Vandermonde system failed",
- java.util.Arrays.equals(y, z));
- }
- }
-
- @Test
- public void testRemainder() {
- final int TEST_LEN = 15;
- for (int i = 0; i < TEST_TIMES; i++) {
- int[] quotient = null;
- int[] divisor = null;
- int[] remainder = null;
- int[] dividend = null;
- while (true) {
- quotient = randGFPoly(RAND.nextInt(TEST_LEN - 3) + 3);
- divisor = randGFPoly(RAND.nextInt(quotient.length - 2) + 2);
- remainder = randGFPoly(RAND.nextInt(divisor.length - 1) + 1);
- dividend = GF.add(remainder, GF.multiply(quotient, divisor));
- if (quotient[quotient.length - 1] != 0 &&
- divisor[divisor.length - 1] != 0 &&
- remainder[remainder.length - 1] != 0) {
- // make sure all the leading terms are not zero
- break;
- }
- }
- GF.remainder(dividend, divisor);
- for (int j = 0; j < remainder.length; j++) {
- assertTrue("Distributivity test on polynomials failed",
- dividend[j] == remainder[j]);
- }
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestHarIndexParser.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestHarIndexParser.java
deleted file mode 100644
index 791280ce881..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestHarIndexParser.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TestHarIndexParser {
- final static Log LOG = LogFactory.getLog(TestHarIndexParser.class);
- File indexFile = null;
-
- @Before
- public void setUp() throws FileNotFoundException, IOException {
- LOG.info("TestHarIndexParser.setUp()");
- indexFile = File.createTempFile("harindex", ".tmp");
- indexFile.deleteOnExit();
- OutputStreamWriter out = new OutputStreamWriter(
- new FileOutputStream(indexFile),
- Charset.forName("UTF-8"));
- out.write("%2F dir 1282018162460+0+493+hadoop+hadoop 0 0 f1 f2 f3 f4\n");
- out.write("%2Ff1 file part-0 0 1024 1282018141145+1282018140822+420+hadoop+hadoop\n");
- out.write("%2Ff3 file part-0 2048 1024 1282018148590+1282018148255+420+hadoop+hadoop\n");
- out.write("%2Ff2 file part-0 1024 1024 1282018144198+1282018143852+420+hadoop+hadoop\n");
- out.write("%2Ff4 file part-1 0 1024000 1282018162959+1282018162460+420+hadoop+hadoop\n");
- out.flush();
- out.close();
- }
-
- @After
- public void tearDown() {
- LOG.info("TestHarIndexParser.tearDown()");
- if (indexFile != null)
- indexFile.delete();
- }
-
- @Test
- public void testHarIndexParser()
- throws UnsupportedEncodingException, IOException {
- LOG.info("testHarIndexParser started.");
- InputStream in = new FileInputStream(indexFile);
- long size = indexFile.length();
- HarIndex parser = new HarIndex(in, size);
-
- HarIndex.IndexEntry entry = parser.findEntry("part-0", 2100);
- assertEquals("/f3", entry.fileName);
-
- LOG.info("testHarIndexParser finished.");
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidFilter.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidFilter.java
deleted file mode 100644
index e22339d4095..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidFilter.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.util.ArrayList;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hdfs.MiniDFSCluster;
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.util.Time;
-import org.junit.Test;
-
-public class TestRaidFilter {
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
- final static Log LOG =
- LogFactory.getLog("org.apache.hadoop.raid.TestRaidFilter");
-
- Configuration conf;
- MiniDFSCluster dfs = null;
- FileSystem fs = null;
-
- private void mySetup() throws Exception {
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
- dfs = new MiniDFSCluster(conf, 2, true, null);
- dfs.waitActive();
- fs = dfs.getFileSystem();
- String namenode = fs.getUri().toString();
- FileSystem.setDefaultUri(conf, namenode);
- }
-
- private void myTearDown() throws Exception {
- if (dfs != null) { dfs.shutdown(); }
- }
-
- @Test
- public void testLayeredPolicies() throws Exception {
- mySetup();
- Path src1 = new Path("/user/foo");
- Path src2 = new Path("/user/foo/bar");
-
- PolicyInfo info1 = new PolicyInfo("p1", conf);
- info1.setSrcPath(src1.toString());
- info1.setErasureCode("xor");
- info1.setDescription("test policy");
- info1.setProperty("targetReplication", "1");
- info1.setProperty("metaReplication", "1");
- info1.setProperty("modTimePeriod", "0");
-
- PolicyInfo info2 = new PolicyInfo("p2", conf);
- info2.setSrcPath(src2.toString());
- info2.setErasureCode("xor");
- info2.setDescription("test policy");
- info2.setProperty("targetReplication", "1");
- info2.setProperty("metaReplication", "1");
- info2.setProperty("modTimePeriod", "0");
-
- ArrayList all = new ArrayList();
- all.add(info1);
- all.add(info2);
-
- try {
- long blockSize = 1024;
- byte[] bytes = new byte[(int)blockSize];
- Path f1 = new Path(src1, "f1");
- Path f2 = new Path(src2, "f2");
- FSDataOutputStream stm1 = fs.create(f1, false, 4096, (short)1, blockSize);
- FSDataOutputStream stm2 = fs.create(f2, false, 4096, (short)1, blockSize);
- FSDataOutputStream[] stms = new FSDataOutputStream[]{stm1, stm2};
- for (FSDataOutputStream stm: stms) {
- stm.write(bytes);
- stm.write(bytes);
- stm.write(bytes);
- stm.close();
- }
-
- Thread.sleep(1000);
-
- FileStatus stat1 = fs.getFileStatus(f1);
- FileStatus stat2 = fs.getFileStatus(f2);
-
- RaidFilter.Statistics stats = new RaidFilter.Statistics();
- RaidFilter.TimeBasedFilter filter = new RaidFilter.TimeBasedFilter(
- conf, RaidNode.xorDestinationPath(conf), info1, all,
- Time.now(), stats);
- System.out.println("Stats " + stats);
-
- assertTrue(filter.check(stat1));
- assertFalse(filter.check(stat2));
-
- } finally {
- myTearDown();
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidHar.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidHar.java
deleted file mode 100644
index 9df30b39a60..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidHar.java
+++ /dev/null
@@ -1,315 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.util.Random;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.logging.impl.Log4JLogger;
-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.MiniDFSCluster;
-import org.apache.hadoop.mapred.JobConf;
-import org.apache.hadoop.mapred.MiniMRCluster;
-import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.log4j.Level;
-import org.junit.Test;
-
-/**
- * If a file gets deleted, then verify that the parity file gets deleted too.
- */
-public class TestRaidHar {
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).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.TestRaidNode");
- final Random rand = new Random();
-
- {
- ((Log4JLogger)RaidNode.LOG).getLogger().setLevel(Level.ALL);
- }
-
-
- Configuration conf;
- String namenode = null;
- String hftp = null;
- MiniDFSCluster dfs = null;
- MiniMRCluster mr = null;
- FileSystem fileSys = null;
- String jobTrackerName = null;
-
- /**
- * create mapreduce and dfs clusters
- */
- private void createClusters(boolean local) throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
- conf.set("raid.config.file", CONFIG_FILE);
- conf.setBoolean("raid.config.reload", true);
- conf.setLong("raid.config.reload.interval", RELOAD_INTERVAL);
-
- // scan all policies once every 5 second
- conf.setLong("raid.policy.rescan.interval", 5000);
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- // the RaidNode does the raiding inline (instead of submitting to map/reduce)
- if (local) {
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- } else {
- conf.set("raid.classname", "org.apache.hadoop.raid.DistRaidNode");
- }
-
- conf.set("raid.server.address", "localhost:0");
- conf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
-
- // create a dfs and map-reduce cluster
- final int taskTrackers = 4;
-
- dfs = new MiniDFSCluster(conf, 3, true, null);
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
- namenode = fileSys.getUri().toString();
- mr = new MiniMRCluster(taskTrackers, namenode, 3);
- JobConf jobConf = mr.createJobConf();
- jobTrackerName = "localhost:" + jobConf.get(JTConfig.JT_IPC_ADDRESS);
- hftp = "hftp://localhost.localdomain:" + dfs.getNameNodePort();
-
- FileSystem.setDefaultUri(conf, namenode);
- conf.set("mapred.job.tracker", jobTrackerName);
- conf.set("mapreduce.framework.name", "yarn");
- String rmAdress = jobConf.get("yarn.resourcemanager.address");
- if (rmAdress != null) {
- conf.set("yarn.resourcemanager.address", rmAdress);
- }
- String schedulerAdress =
- jobConf.get("yarn.resourcemanager.scheduler.address");
- if (schedulerAdress != null) {
- conf.set("yarn.resourcemanager.scheduler.address", schedulerAdress);
- }
- String jobHistoryAddress =
- jobConf.get("mapreduce.jobhistory.address");
- if (jobHistoryAddress != null) {
- conf.set("mapreduce.jobhistory.address", jobHistoryAddress);
- }
- }
-
- /**
- * create raid.xml file for RaidNode
- */
- private void mySetup(long targetReplication,
- long metaReplication, long stripeLength) throws Exception {
- FileWriter fileWriter = new FileWriter(CONFIG_FILE);
- fileWriter.write("\n");
- String str = " " +
- " " +
- " " +
- "xor " +
- " " +
- "targetReplication " +
- "" + targetReplication + " " +
- "after RAIDing, decrease the replication factor of a file to this value." +
- " " +
- " " +
- " " +
- "metaReplication " +
- "" + metaReplication + " " +
- " replication factor of parity file" +
- " " +
- " " +
- " " +
- "stripeLength " +
- "" + stripeLength + " " +
- " the max number of blocks in a file to RAID together " +
- " " +
- " " +
- " " +
- "time_before_har " +
- "0 " +
- " amount of time waited before har'ing parity files" +
- " " +
- " " +
- " " +
- "modTimePeriod " +
- "2000 " +
- " time (milliseconds) after a file is modified to make it " +
- "a candidate for RAIDing " +
- " " +
- " " +
- "" +
- "" +
- "";
- fileWriter.write(str);
- fileWriter.close();
- }
-
- /**
- * stop clusters created earlier
- */
- private void stopClusters() throws Exception {
- if (mr != null) { mr.shutdown(); }
- if (dfs != null) { dfs.shutdown(); }
- }
-
- /**
- * Test that parity files that do not have an associated master file
- * get deleted.
- */
- @Test
- public void testRaidHar() throws Exception {
- LOG.info("Test testRaidHar started.");
-
- long blockSizes [] = {1024L};
- long stripeLengths [] = {5};
- long targetReplication = 1;
- long metaReplication = 1;
- int numBlock = 9;
- int iter = 0;
-
- createClusters(true);
- try {
- for (long blockSize : blockSizes) {
- for (long stripeLength : stripeLengths) {
- doTestHar(iter, targetReplication, metaReplication,
- stripeLength, blockSize, numBlock);
- iter++;
- }
- }
- } finally {
- stopClusters();
- }
- LOG.info("Test testRaidHar completed.");
- }
-
- /**
- * Create parity file, delete original file and then validate that
- * parity file is automatically deleted.
- */
- private void doTestHar(int iter, long targetReplication,
- long metaReplication, long stripeLength,
- long blockSize, int numBlock) throws Exception {
- LOG.info("doTestHar started---------------------------:" + " iter " + iter +
- " blockSize=" + blockSize + " stripeLength=" + stripeLength);
- mySetup(targetReplication, metaReplication, stripeLength);
- Path dir = new Path("/user/test/raidtest/subdir/");
- Path file1 = new Path(dir + "/file" + iter);
- RaidNode cnode = null;
- try {
- Path destPath = new Path("/destraid/user/test/raidtest/subdir");
- fileSys.delete(dir, true);
- fileSys.delete(destPath, true);
- for (int i = 0; i < 10; i++) {
- Path file = new Path(dir + "/file" + i);
- TestRaidNode.createOldFile(fileSys, file, 1, numBlock, blockSize);
- }
- LOG.info("doTestHar created test files for iteration " + iter);
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- cnode = RaidNode.createRaidNode(null, localConf);
- FileStatus[] listPaths = null;
-
- int maxFilesFound = 0;
- // wait till file is raided
- while (true) {
- try {
- listPaths = fileSys.listStatus(destPath);
- int count = 0;
- Path harPath = null;
- int filesFound = 0;
- if (listPaths != null) {
- for (FileStatus s : listPaths) {
- LOG.info("doTestHar found path " + s.getPath());
-
- if (!s.isDir())
- filesFound++;
- if (filesFound > maxFilesFound)
- maxFilesFound = filesFound;
-
- if (s.getPath().toString().endsWith(".har")) {
- // If a HAR directory is found, ensure that we have seen
- // 10 parity files. We have to keep track of the max # of
- // files since some parity files might get deleted by the
- // purge thread.
- assertEquals(10, maxFilesFound);
- harPath = s.getPath();
- count++;
- }
- }
- }
- if (count == 1 && listPaths.length == 1) {
- Path partfile = new Path(harPath, "part-0");
- assertEquals(fileSys.getFileStatus(partfile).getReplication(),
- targetReplication);
- break;
- }
- } catch (FileNotFoundException e) {
- //ignore
- }
- LOG.info("doTestHar waiting for files to be raided and parity files to be har'ed and deleted. Found " +
- (listPaths == null ? "none" : listPaths.length));
- Thread.sleep(1000); // keep waiting
-
- }
-
- fileSys.delete(dir, true);
- // wait till raid file is deleted
- int count = 1;
- while (count > 0) {
- count = 0;
- try {
- listPaths = fileSys.listStatus(destPath);
- if (listPaths != null) {
- for (FileStatus s : listPaths) {
- LOG.info("doTestHar found path " + s.getPath());
- if (s.getPath().toString().endsWith(".har")) {
- count++;
- }
- }
- }
- } catch (FileNotFoundException e) { } //ignoring
- LOG.info("doTestHar waiting for har file to be deleted. Found " +
- (listPaths == null ? "none" : listPaths.length) + " files");
- Thread.sleep(1000);
- }
-
- } catch (Exception e) {
- LOG.info("doTestHar Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- }
- LOG.info("doTestHar completed:" + " blockSize=" + blockSize +
- " stripeLength=" + stripeLength);
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidNode.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidNode.java
deleted file mode 100644
index aae0bcbab09..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidNode.java
+++ /dev/null
@@ -1,738 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.List;
-import java.util.Random;
-import java.util.zip.CRC32;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hdfs.MiniDFSCluster;
-import org.apache.hadoop.mapred.JobConf;
-import org.apache.hadoop.mapred.JobContext;
-import org.apache.hadoop.mapred.MiniMRCluster;
-import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig;
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.raid.protocol.PolicyList;
-import org.apache.hadoop.util.JarFinder;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-import org.junit.Test;
-
-/**
- * Test the generation of parity blocks for files with different block
- * sizes. Also test that a data block can be regenerated from a raid stripe
- * using the parity block
- */
-public class TestRaidNode {
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
- public static final String DistRaid_JAR = JarFinder.getJar(DistRaid.class);
- 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.TestRaidNode");
- final static Random rand = new Random();
-
- Configuration conf;
- String namenode = null;
- String hftp = null;
- MiniDFSCluster dfs = null;
- MiniMRCluster mr = null;
- FileSystem fileSys = null;
- String jobTrackerName = null;
-
- /**
- * create mapreduce and dfs clusters
- */
- private void createClusters(boolean local) throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
- conf.set("raid.config.file", CONFIG_FILE);
- conf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- conf.setBoolean("raid.config.reload", true);
- conf.setLong("raid.config.reload.interval", RELOAD_INTERVAL);
- conf.setBoolean("dfs.permissions.enabled", true);
- conf.setLong(JobMonitor.JOBMONITOR_INTERVAL_KEY, 20000);
- conf.setLong(RaidNode.TRIGGER_MONITOR_SLEEP_TIME_KEY, 3000L);
-
- // scan all policies once every 5 second
- conf.setLong("raid.policy.rescan.interval", 5000);
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- // the RaidNode does the raiding inline (instead of submitting to map/reduce)
- if (local) {
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- } else {
- conf.set("raid.classname", "org.apache.hadoop.raid.DistRaidNode");
- }
-
- conf.set("raid.server.address", "localhost:0");
-
- // create a dfs and map-reduce cluster
- MiniDFSCluster.Builder builder = new MiniDFSCluster.Builder(conf);
- builder.numDataNodes(6);
- builder.format(true);
- dfs = builder.build();
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
-
- namenode = fileSys.getUri().toString();
- final int taskTrackers = 4;
- mr = new MiniMRCluster(taskTrackers, namenode, 3);
- JobConf jobConf = mr.createJobConf();
- jobTrackerName = "localhost:" + jobConf.get(JTConfig.JT_IPC_ADDRESS);
- hftp = "hftp://localhost.localdomain:" + dfs.getNameNodePort();
-
- FileSystem.setDefaultUri(conf, namenode);
- conf.set("mapred.job.tracker", jobTrackerName);
- conf.set("mapreduce.framework.name", "yarn");
- String rmAdress = jobConf.get("yarn.resourcemanager.address");
- if (rmAdress != null) {
- conf.set("yarn.resourcemanager.address", rmAdress);
- }
- String schedulerAdress =
- jobConf.get("yarn.resourcemanager.scheduler.address");
- if (schedulerAdress != null) {
- conf.set("yarn.resourcemanager.scheduler.address", schedulerAdress);
- }
- String jobHistoryAddress =
- jobConf.get("mapreduce.jobhistory.address");
- if (jobHistoryAddress != null) {
- conf.set("mapreduce.jobhistory.address", jobHistoryAddress);
- }
- }
-
- class ConfigBuilder {
- private List policies;
-
- public ConfigBuilder() {
- policies = new java.util.ArrayList();
- }
-
- public void addPolicy(String name, String path, String parent) {
- String str =
- " " +
- " " +
- "" + parent + "" +
- "" +
- "";
- policies.add(str);
- }
-
- public void addPolicy(String name, short srcReplication,
- long targetReplication, long metaReplication, long stripeLength) {
- String str =
- " " +
- " " +
- "xor " +
- " " +
- "srcReplication " +
- "" + srcReplication + " " +
- " pick only files whole replFactor is greater than or equal to " +
- " " +
- " " +
- " " +
- "targetReplication " +
- "" + targetReplication + " " +
- "after RAIDing, decrease the replication factor of a file to this value." +
- " " +
- " " +
- " " +
- "metaReplication " +
- "" + metaReplication + " " +
- " replication factor of parity file" +
- " " +
- " " +
- " " +
- "stripeLength " +
- "" + stripeLength + " " +
- " the max number of blocks in a file to RAID together " +
- " " +
- " " +
- " " +
- "modTimePeriod " +
- "2000 " +
- " time (milliseconds) after a file is modified to make it " +
- "a candidate for RAIDing " +
- " " +
- " " +
- "" +
- "";
- policies.add(str);
- }
-
- public void addPolicy(String name, String path, short srcReplication,
- long targetReplication, long metaReplication, long stripeLength) {
- String str =
- " " +
- " " +
- "xor " +
- " " +
- "srcReplication " +
- "" + srcReplication + " " +
- " pick only files whole replFactor is greater than or equal to " +
- " " +
- " " +
- " " +
- "targetReplication " +
- "" + targetReplication + " " +
- "after RAIDing, decrease the replication factor of a file to this value." +
- " " +
- " " +
- " " +
- "metaReplication " +
- "" + metaReplication + " " +
- " replication factor of parity file" +
- " " +
- " " +
- " " +
- "stripeLength " +
- "" + stripeLength + " " +
- " the max number of blocks in a file to RAID together " +
- " " +
- " " +
- " " +
- "modTimePeriod " +
- "2000 " +
- " time (milliseconds) after a file is modified to make it " +
- "a candidate for RAIDing " +
- " " +
- " " +
- "" +
- "";
- policies.add(str);
- }
-
- public void persist() throws IOException {
- FileWriter fileWriter = new FileWriter(CONFIG_FILE);
- fileWriter.write("\n");
- fileWriter.write("");
- for (String policy: policies) {
- fileWriter.write(policy);
- }
- fileWriter.write("");
- fileWriter.close();
- }
- }
-
- /**
- * stop clusters created earlier
- */
- private void stopClusters() throws Exception {
- if (mr != null) { mr.shutdown(); }
- if (dfs != null) { dfs.shutdown(); }
- }
-
- /**
- * Test to run a filter
- */
- @Test
- public void testPathFilter() throws Exception {
- LOG.info("Test testPathFilter started.");
-
- long blockSizes [] = {1024L};
- int stripeLengths [] = {5, 6, 10, 11, 12};
- int targetReplication = 1;
- int metaReplication = 1;
- int numBlock = 11;
- int iter = 0;
-
- createClusters(true);
- try {
- for (long blockSize : blockSizes) {
- for (long stripeLength : stripeLengths) {
- doTestPathFilter(iter, targetReplication, metaReplication,
- stripeLength, blockSize, numBlock);
- iter++;
- }
- }
- doCheckPolicy();
- } finally {
- stopClusters();
- }
- LOG.info("Test testPathFilter completed.");
- }
-
- /**
- * Test to run a filter
- */
- private void doTestPathFilter(int iter, long targetReplication,
- long metaReplication, long stripeLength,
- long blockSize, int numBlock) throws Exception {
- LOG.info("doTestPathFilter started---------------------------:" + " iter " + iter +
- " blockSize=" + blockSize + " stripeLength=" + stripeLength);
- ConfigBuilder cb = new ConfigBuilder();
- cb.addPolicy("policy1", "/user/dhruba/raidtest", (short)1, targetReplication, metaReplication, stripeLength);
- cb.persist();
-
- RaidShell shell = null;
- Path dir = new Path("/user/dhruba/raidtest/");
- Path file1 = new Path(dir + "/file" + iter);
- RaidNode cnode = null;
- try {
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- fileSys.delete(dir, true);
- fileSys.delete(destPath, true);
- long crc1 = createOldFile(fileSys, file1, 1, numBlock, blockSize);
- LOG.info("doTestPathFilter created test files for iteration " + iter);
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- cnode = RaidNode.createRaidNode(null, localConf);
- FileStatus[] listPaths = null;
-
- // wait till file is raided
- while (true) {
- try {
- listPaths = fileSys.listStatus(destPath);
- int count = 0;
- if (listPaths != null && listPaths.length == 1) {
- for (FileStatus s : listPaths) {
- LOG.info("doTestPathFilter found path " + s.getPath());
- if (!s.getPath().toString().endsWith(".tmp") &&
- fileSys.getFileStatus(file1).getReplication() ==
- targetReplication) {
- count++;
- }
- }
- }
- if (count > 0) {
- break;
- }
- } catch (FileNotFoundException e) {
- //ignore
- }
- LOG.info("doTestPathFilter waiting for files to be raided. Found " +
- (listPaths == null ? "none" : listPaths.length));
- Thread.sleep(1000); // keep waiting
- }
- // assertEquals(listPaths.length, 1); // all files raided
- LOG.info("doTestPathFilter all files found in Raid.");
-
- // check for error at beginning of file
- shell = new RaidShell(conf);
- shell.initializeRpc(conf, cnode.getListenerAddress());
- if (numBlock >= 1) {
- LOG.info("doTestPathFilter Check error at beginning of file.");
- simulateError(shell, fileSys, file1, crc1, 0);
- }
-
- // check for error at the beginning of second block
- if (numBlock >= 2) {
- LOG.info("doTestPathFilter Check error at beginning of second block.");
- simulateError(shell, fileSys, file1, crc1, blockSize + 1);
- }
-
- // check for error at the middle of third block
- if (numBlock >= 3) {
- LOG.info("doTestPathFilter Check error at middle of third block.");
- simulateError(shell, fileSys, file1, crc1, 2 * blockSize + 10);
- }
-
- // check for error at the middle of second stripe
- if (numBlock >= stripeLength + 1) {
- LOG.info("doTestPathFilter Check error at middle of second stripe.");
- simulateError(shell, fileSys, file1, crc1,
- stripeLength * blockSize + 100);
- }
-
- } catch (Exception e) {
- LOG.info("doTestPathFilter Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (shell != null) shell.close();
- if (cnode != null) { cnode.stop(); cnode.join(); }
- LOG.info("doTestPathFilter delete file " + file1);
- fileSys.delete(file1, true);
- }
- LOG.info("doTestPathFilter completed:" + " blockSize=" + blockSize +
- " stripeLength=" + stripeLength);
- }
-
- // Check that raid occurs only on files that have a replication factor
- // greater than or equal to the specified value
- private void doCheckPolicy() throws Exception {
- LOG.info("doCheckPolicy started---------------------------:");
- short srcReplication = 1;
- long targetReplication = 2;
- long metaReplication = 1;
- long stripeLength = 2;
- long blockSize = 1024;
- int numBlock = 3;
- ConfigBuilder cb = new ConfigBuilder();
- cb.addPolicy("policy1", "/user/dhruba/policytest", srcReplication,
- targetReplication, metaReplication, stripeLength);
- cb.persist();
- Path dir = new Path("/user/dhruba/policytest/");
- Path file1 = new Path(dir + "/file1");
- Path file2 = new Path(dir + "/file2");
- RaidNode cnode = null;
- try {
- Path destPath = new Path("/destraid/user/dhruba/policytest");
- fileSys.delete(dir, true);
- fileSys.delete(destPath, true);
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- cnode = RaidNode.createRaidNode(null, localConf);
-
- // this file should be picked up RaidNode
- createOldFile(fileSys, file2, 2, numBlock, blockSize);
- FileStatus[] listPaths = null;
-
- long firstmodtime = 0;
- // wait till file is raided
- while (true) {
- Thread.sleep(1000); // waiting
- try {
- listPaths = fileSys.listStatus(destPath);
- } catch (FileNotFoundException e) {
- LOG.warn("File not found " + destPath);
- // The directory have been deleted by the purge thread.
- continue;
- }
- int count = 0;
- if (listPaths != null && listPaths.length == 1) {
- for (FileStatus s : listPaths) {
- LOG.info("doCheckPolicy found path " + s.getPath());
- if (!s.getPath().toString().endsWith(".tmp") &&
- fileSys.getFileStatus(file2).getReplication() ==
- targetReplication) {
- count++;
- firstmodtime = s.getModificationTime();
- }
- }
- }
- if (count > 0) {
- break;
- }
- LOG.info("doCheckPolicy waiting for files to be raided. Found " +
- (listPaths == null ? "none" : listPaths.length));
- }
- assertEquals(listPaths.length, 1);
-
- LOG.info("doCheckPolicy all files found in Raid the first time.");
-
- LOG.info("doCheckPolicy: recreating source file");
- createOldFile(fileSys, file2, 2, numBlock, blockSize);
-
- FileStatus st = fileSys.getFileStatus(file2);
- assertTrue(st.getModificationTime() > firstmodtime);
-
- // wait till file is raided
- while (true) {
- Thread.sleep(20000L); // waiting
- listPaths = fileSys.listStatus(destPath);
- int count = 0;
- if (listPaths != null && listPaths.length == 1) {
- for (FileStatus s : listPaths) {
- LOG.info("doCheckPolicy found path " + s.getPath() + " " + s.getModificationTime());
- if (!s.getPath().toString().endsWith(".tmp") &&
- s.getModificationTime() > firstmodtime &&
- fileSys.getFileStatus(file2).getReplication() ==
- targetReplication) {
- count++;
- }
- }
- }
- if (count > 0) {
- break;
- }
- LOG.info("doCheckPolicy waiting for files to be raided. Found " +
- (listPaths == null ? "none" : listPaths.length));
- }
- assertEquals(listPaths.length, 1);
-
- LOG.info("doCheckPolicy: file got re-raided as expected.");
-
- } catch (Exception e) {
- LOG.info("doCheckPolicy Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- LOG.info("doTestPathFilter delete file " + file1);
- fileSys.delete(file1, false);
- }
- LOG.info("doCheckPolicy completed:");
- }
-
- static public void createTestFiles(FileSystem fileSys,
- String path, String destpath, int nfile,
- int nblock) throws IOException {
- createTestFiles(fileSys, path, destpath, nfile, nblock, (short)1);
- }
-
- static void createTestFiles(FileSystem fileSys, String path, String destpath, int nfile,
- int nblock, short repl) throws IOException {
- long blockSize = 1024L;
- Path dir = new Path(path);
- Path destPath = new Path(destpath);
- fileSys.delete(dir, true);
- fileSys.delete(destPath, true);
-
- for(int i = 0 ; i < nfile; i++){
- Path file = new Path(path + "file" + i);
- createOldFile(fileSys, file, repl, nblock, blockSize);
- }
- }
-
- /**
- * Test dist Raid
- */
- @Test
- public void testDistRaid() throws Exception {
- LOG.info("Test testDistRaid started.");
- long targetReplication = 2;
- long metaReplication = 2;
- long stripeLength = 3;
- short srcReplication = 1;
-
- createClusters(false);
- ConfigBuilder cb = new ConfigBuilder();
- cb.addPolicy("policy1", "/user/dhruba/raidtest",
- srcReplication, targetReplication, metaReplication, stripeLength);
- cb.addPolicy("policy2", "/user/dhruba/raidtest2",
- srcReplication, targetReplication, metaReplication, stripeLength);
- cb.persist();
-
- RaidNode cnode = null;
- try {
- createTestFiles(fileSys, "/user/dhruba/raidtest/",
- "/destraid/user/dhruba/raidtest", 5, 7);
- createTestFiles(fileSys, "/user/dhruba/raidtest2/",
- "/destraid/user/dhruba/raidtest2", 5, 7);
- LOG.info("Test testDistRaid created test files");
-
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.set(JobContext.JAR, TestRaidNode.DistRaid_JAR);
- cnode = RaidNode.createRaidNode(null, localConf);
- // Verify the policies are parsed correctly
- for (PolicyList policyList : cnode.getAllPolicies()) {
- for (PolicyInfo p : policyList.getAll()) {
- if (p.getName().equals("policy1")) {
- Path srcPath = new Path("/user/dhruba/raidtest");
- FileSystem fs = srcPath.getFileSystem(conf);
- assertTrue(p.getSrcPath().equals(
- srcPath.makeQualified(fs.getUri(), fs.getWorkingDirectory())));
- } else {
- assertTrue(p.getName().equals("policy2"));
- Path srcPath = new Path("/user/dhruba/raidtest2");
- FileSystem fs = srcPath.getFileSystem(conf);
- assertTrue(p.getSrcPath().equals(
- srcPath.makeQualified(fs.getUri(), fs.getWorkingDirectory())));
- }
- assertEquals(targetReplication,
- Integer.parseInt(p.getProperty("targetReplication")));
- assertEquals(metaReplication,
- Integer.parseInt(p.getProperty("metaReplication")));
- assertEquals(stripeLength,
- Integer.parseInt(p.getProperty("stripeLength")));
- }
- }
-
- long start = Time.now();
- final int MAX_WAITTIME = 300000;
-
- assertTrue("cnode is not DistRaidNode", cnode instanceof DistRaidNode);
- DistRaidNode dcnode = (DistRaidNode) cnode;
-
- while (dcnode.jobMonitor.jobsMonitored() < 2 &&
- Time.now() - start < MAX_WAITTIME) {
- Thread.sleep(1000);
- }
-
- start = Time.now();
- while (dcnode.jobMonitor.jobsSucceeded() < 2 &&
- Time.now() - start < MAX_WAITTIME) {
- Thread.sleep(1000);
- }
- assertEquals(dcnode.jobMonitor.jobsSucceeded(), dcnode.jobMonitor.jobsMonitored());
- LOG.info("Test testDistRaid successful.");
-
- } catch (Exception e) {
- LOG.info("testDistRaid Exception " + e + StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- stopClusters();
- }
- LOG.info("Test testDistRaid completed.");
- }
-
- //
- // simulate a corruption at specified offset and verify that eveyrthing is good
- //
- void simulateError(RaidShell shell, FileSystem fileSys, Path file1,
- long crc, long corruptOffset) throws IOException {
- // recover the file assuming that we encountered a corruption at offset 0
- String[] args = new String[3];
- args[0] = "-recover";
- args[1] = file1.toString();
- args[2] = Long.toString(corruptOffset);
- Path recover1 = shell.recover(args[0], args, 1)[0];
-
- // compare that the recovered file is identical to the original one
- LOG.info("Comparing file " + file1 + " with recovered file " + recover1);
- validateFile(fileSys, file1, recover1, crc);
- fileSys.delete(recover1, false);
- }
-
- //
- // creates a file and populate it with random data. Returns its crc.
- //
- static long createOldFile(FileSystem fileSys, Path name, int repl, int numBlocks, long blocksize)
- throws IOException {
- CRC32 crc = new CRC32();
- FSDataOutputStream stm = fileSys.create(name, true,
- fileSys.getConf().getInt("io.file.buffer.size", 4096),
- (short)repl, blocksize);
- // fill random data into file
- byte[] b = new byte[(int)blocksize];
- for (int i = 0; i < numBlocks; i++) {
- if (i == (numBlocks-1)) {
- b = new byte[(int)blocksize/2];
- }
- rand.nextBytes(b);
- stm.write(b);
- crc.update(b);
- }
-
- stm.close();
- return crc.getValue();
- }
-
- //
- // validates that file matches the crc.
- //
- private void validateFile(FileSystem fileSys, Path name1, Path name2, long crc)
- throws IOException {
-
- FileStatus stat1 = fileSys.getFileStatus(name1);
- FileStatus stat2 = fileSys.getFileStatus(name2);
- assertTrue(" Length of file " + name1 + " is " + stat1.getLen() +
- " is different from length of file " + name1 + " " + stat2.getLen(),
- stat1.getLen() == stat2.getLen());
-
- CRC32 newcrc = new CRC32();
- FSDataInputStream stm = fileSys.open(name2);
- final byte[] b = new byte[4192];
- int num = 0;
- while (num >= 0) {
- num = stm.read(b);
- if (num < 0) {
- break;
- }
- newcrc.update(b, 0, num);
- }
- stm.close();
- if (newcrc.getValue() != crc) {
- fail("CRC mismatch of files " + name1 + " with file " + name2);
- }
- }
-
- @Test
- public void testSuspendTraversal() throws Exception {
- LOG.info("Test testSuspendTraversal started.");
- long targetReplication = 2;
- long metaReplication = 2;
- long stripeLength = 3;
- short srcReplication = 1;
-
- createClusters(false);
- ConfigBuilder cb = new ConfigBuilder();
- cb.addPolicy("policy1", "/user/dhruba/raidtest",
- srcReplication, targetReplication, metaReplication, stripeLength);
- cb.persist();
-
- RaidNode cnode = null;
- try {
- for(int i = 0; i < 4; i++){
- Path file = new Path("/user/dhruba/raidtest/dir" + i + "/file" + i);
- createOldFile(fileSys, file, 1, 7, 1024L);
- }
-
- LOG.info("Test testSuspendTraversal created test files");
-
- Configuration localConf = new Configuration(conf);
- localConf.setInt("raid.distraid.max.jobs", 2);
- localConf.setInt("raid.distraid.max.files", 2);
- localConf.setInt("raid.directorytraversal.threads", 1);
- localConf.set(JobContext.JAR, TestRaidNode.DistRaid_JAR);
- // 4 test files: 2 jobs with 2 files each.
- final int numJobsExpected = 2;
- cnode = RaidNode.createRaidNode(null, localConf);
-
- long start = Time.now();
- final int MAX_WAITTIME = 300000;
-
- assertTrue("cnode is not DistRaidNode", cnode instanceof DistRaidNode);
- DistRaidNode dcnode = (DistRaidNode) cnode;
-
- start = Time.now();
- while (dcnode.jobMonitor.jobsSucceeded() < numJobsExpected &&
- Time.now() - start < MAX_WAITTIME) {
- LOG.info("Waiting for num jobs succeeded " + dcnode.jobMonitor.jobsSucceeded() +
- " to reach " + numJobsExpected);
- Thread.sleep(3000);
- }
- // Wait for any running jobs to finish.
- start = Time.now();
- while (dcnode.jobMonitor.runningJobsCount() > 0 &&
- Time.now() - start < MAX_WAITTIME) {
- LOG.info("Waiting for zero running jobs: " +
- dcnode.jobMonitor.runningJobsCount());
- Thread.sleep(1000);
- }
- assertEquals(numJobsExpected, dcnode.jobMonitor.jobsMonitored());
- assertEquals(numJobsExpected, dcnode.jobMonitor.jobsSucceeded());
-
- LOG.info("Test testSuspendTraversal successful.");
-
- } catch (Exception e) {
- LOG.info("testSuspendTraversal Exception " + e + StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- stopClusters();
- }
- LOG.info("Test testSuspendTraversal completed.");
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidPurge.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidPurge.java
deleted file mode 100644
index 5010dcf9fca..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidPurge.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.util.Random;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.logging.impl.Log4JLogger;
-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.MiniDFSCluster;
-import org.apache.hadoop.hdfs.TestRaidDfs;
-import org.apache.hadoop.mapred.JobConf;
-import org.apache.hadoop.mapred.MiniMRCluster;
-import org.apache.hadoop.mapred.Reporter;
-import org.apache.hadoop.mapreduce.server.jobtracker.JTConfig;
-import org.apache.hadoop.raid.protocol.PolicyInfo;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-import org.apache.log4j.Level;
-import org.junit.Test;
-
-/**
- * If a file gets deleted, then verify that the parity file gets deleted too.
- */
-public class TestRaidPurge {
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).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.TestRaidNode");
- final Random rand = new Random();
-
- {
- ((Log4JLogger)RaidNode.LOG).getLogger().setLevel(Level.ALL);
- }
-
-
- Configuration conf;
- String namenode = null;
- String hftp = null;
- MiniDFSCluster dfs = null;
- MiniMRCluster mr = null;
- FileSystem fileSys = null;
- String jobTrackerName = null;
-
- /**
- * create mapreduce and dfs clusters
- */
- private void createClusters(boolean local) throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
- conf.set("raid.config.file", CONFIG_FILE);
- conf.setBoolean("raid.config.reload", true);
- conf.setLong("raid.config.reload.interval", RELOAD_INTERVAL);
-
- // scan all policies once every 5 second
- conf.setLong("raid.policy.rescan.interval", 5000);
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.dfs.DFSClient");
-
- // the RaidNode does the raiding inline (instead of submitting to map/reduce)
- if (local) {
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- } else {
- conf.set("raid.classname", "org.apache.hadoop.raid.DistRaidNode");
- }
-
- conf.set("raid.server.address", "localhost:0");
-
- // create a dfs and map-reduce cluster
- final int taskTrackers = 4;
- final int jobTrackerPort = 60050;
-
- dfs = new MiniDFSCluster(conf, 3, true, null);
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
- namenode = fileSys.getUri().toString();
- mr = new MiniMRCluster(taskTrackers, namenode, 3);
- JobConf jobConf = mr.createJobConf();
- jobTrackerName = "localhost:" + jobConf.get(JTConfig.JT_IPC_ADDRESS);
- hftp = "hftp://localhost.localdomain:" + dfs.getNameNodePort();
-
- FileSystem.setDefaultUri(conf, namenode);
- conf.set("mapred.job.tracker", jobTrackerName);
- conf.set("mapreduce.framework.name", "yarn");
- String rmAdress = jobConf.get("yarn.resourcemanager.address");
- if (rmAdress != null) {
- conf.set("yarn.resourcemanager.address", rmAdress);
- }
- String schedulerAdress =
- jobConf.get("yarn.resourcemanager.scheduler.address");
- if (schedulerAdress != null) {
- conf.set("yarn.resourcemanager.scheduler.address", schedulerAdress);
- }
- String jobHistoryAddress =
- jobConf.get("mapreduce.jobhistory.address");
- if (jobHistoryAddress != null) {
- conf.set("mapreduce.jobhistory.address", jobHistoryAddress);
- }
- }
-
- /**
- * create raid.xml file for RaidNode
- */
- private void mySetup(long targetReplication,
- long metaReplication, long stripeLength) throws Exception {
- int harDelay = 1; // 1 day.
- mySetup(targetReplication, metaReplication, stripeLength, harDelay);
- }
-
- private void mySetup(long targetReplication,
- long metaReplication, long stripeLength, int harDelay) throws Exception {
- FileWriter fileWriter = new FileWriter(CONFIG_FILE);
- fileWriter.write("\n");
- String str = " " +
- " " +
- " " +
- "xor " +
- " /destraid " +
- " " +
- "targetReplication " +
- "" + targetReplication + " " +
- "after RAIDing, decrease the replication factor of a file to this value." +
- " " +
- " " +
- " " +
- "metaReplication " +
- "" + metaReplication + " " +
- " replication factor of parity file" +
- " " +
- " " +
- " " +
- "stripeLength " +
- "" + stripeLength + " " +
- " the max number of blocks in a file to RAID together " +
- " " +
- " " +
- " " +
- "modTimePeriod " +
- "2000 " +
- " time (milliseconds) after a file is modified to make it " +
- "a candidate for RAIDing " +
- " " +
- " " +
- " " +
- "time_before_har " +
- " " + harDelay + " " +
- " amount of time waited before har'ing parity files" +
- " " +
- " " +
- "" +
- "" +
- "";
- fileWriter.write(str);
- fileWriter.close();
- }
-
- /**
- * stop clusters created earlier
- */
- private void stopClusters() throws Exception {
- if (mr != null) { mr.shutdown(); }
- if (dfs != null) { dfs.shutdown(); }
- }
-
- /**
- * Test that parity files that do not have an associated master file
- * get deleted.
- */
- @Test
- public void testPurge() throws Exception {
- LOG.info("Test testPurge started.");
-
- long blockSizes [] = {1024L};
- long stripeLengths [] = {5};
- long targetReplication = 1;
- long metaReplication = 1;
- int numBlock = 9;
- int iter = 0;
-
- createClusters(true);
- try {
- for (long blockSize : blockSizes) {
- for (long stripeLength : stripeLengths) {
- doTestPurge(iter, targetReplication, metaReplication,
- stripeLength, blockSize, numBlock);
- iter++;
- }
- }
- } finally {
- stopClusters();
- }
- LOG.info("Test testPurge completed.");
- }
-
- /**
- * Create parity file, delete original file and then validate that
- * parity file is automatically deleted.
- */
- private void doTestPurge(int iter, long targetReplication,
- long metaReplication, long stripeLength,
- long blockSize, int numBlock) throws Exception {
- LOG.info("doTestPurge started---------------------------:" + " iter " + iter +
- " blockSize=" + blockSize + " stripeLength=" + stripeLength);
- mySetup(targetReplication, metaReplication, stripeLength);
- Path dir = new Path("/user/dhruba/raidtest/");
- Path file1 = new Path(dir + "/file" + iter);
- RaidNode cnode = null;
- try {
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- fileSys.delete(dir, true);
- fileSys.delete(destPath, true);
- TestRaidNode.createOldFile(fileSys, file1, 1, numBlock, blockSize);
- LOG.info("doTestPurge created test files for iteration " + iter);
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
-
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- cnode = RaidNode.createRaidNode(null, localConf);
- FileStatus[] listPaths = null;
-
- // wait till file is raided
- while (true) {
- try {
- listPaths = fileSys.listStatus(destPath);
- int count = 0;
- if (listPaths != null && listPaths.length == 1) {
- for (FileStatus s : listPaths) {
- LOG.info("doTestPurge found path " + s.getPath());
- if (!s.getPath().toString().endsWith(".tmp")) {
- count++;
- }
- }
- }
- if (count > 0) {
- break;
- }
- } catch (FileNotFoundException e) {
- //ignore
- }
- LOG.info("doTestPurge waiting for files to be raided. Found " +
- (listPaths == null ? "none" : listPaths.length));
- Thread.sleep(1000); // keep waiting
- }
- // assertEquals(listPaths.length, 1); // all files raided
- LOG.info("doTestPurge all files found in Raid.");
-
- // delete original file
- assertTrue("Unable to delete original file " + file1 ,
- fileSys.delete(file1, true));
- LOG.info("deleted file " + file1);
-
- // wait till parity file and directory are automatically deleted
- while (fileSys.exists(destPath)) {
- LOG.info("doTestPurge waiting for parity files to be removed.");
- Thread.sleep(1000); // keep waiting
- }
-
- } catch (Exception e) {
- LOG.info("doTestPurge Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- LOG.info("doTestPurge delete file " + file1);
- fileSys.delete(file1, true);
- }
- LOG.info("doTestPurge completed:" + " blockSize=" + blockSize +
- " stripeLength=" + stripeLength);
- }
-
- /**
- * Create a file, wait for parity file to get HARed. Then modify the file,
- * wait for the HAR to get purged.
- */
- @Test
- public void testPurgeHar() throws Exception {
- LOG.info("testPurgeHar started");
- int harDelay = 0;
- createClusters(true);
- mySetup(1, 1, 5, harDelay);
- Path dir = new Path("/user/dhruba/raidtest/");
- Path destPath = new Path("/raid/user/dhruba/raidtest");
- Path file1 = new Path(dir + "/file");
- RaidNode cnode = null;
- try {
- TestRaidNode.createOldFile(fileSys, file1, 1, 8, 8192L);
- LOG.info("testPurgeHar created test files");
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- cnode = RaidNode.createRaidNode(null, localConf);
-
- // Wait till har is created.
- while (true) {
- try {
- FileStatus[] listPaths = listPaths = fileSys.listStatus(destPath);
- if (listPaths != null && listPaths.length == 1) {
- FileStatus s = listPaths[0];
- LOG.info("testPurgeHar found path " + s.getPath());
- if (s.getPath().toString().endsWith(".har")) {
- break;
- }
- }
- } catch (FileNotFoundException e) {
- //ignore
- }
- Thread.sleep(1000); // keep waiting
- }
-
- // Set an old timestamp.
- fileSys.setTimes(file1, 0, 0);
-
- boolean found = false;
- FileStatus[] listPaths = null;
- while (!found || listPaths == null || listPaths.length > 1) {
- listPaths = fileSys.listStatus(destPath);
- if (listPaths != null) {
- for (FileStatus s: listPaths) {
- LOG.info("testPurgeHar waiting for parity file to be recreated" +
- " and har to be deleted found " + s.getPath());
- if (s.getPath().toString().endsWith("file") &&
- s.getModificationTime() == 0) {
- found = true;
- }
- }
- }
- Thread.sleep(1000);
- }
- } catch (Exception e) {
- LOG.info("testPurgeHar Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- fileSys.delete(dir, true);
- fileSys.delete(destPath, true);
- stopClusters();
- }
- }
-
- /**
- * Create parity file, delete original file's directory and then validate that
- * parity directory is automatically deleted.
- */
- @Test
- public void testPurgeDirectory() throws Exception {
- long stripeLength = 5;
- long blockSize = 8192;
- long targetReplication = 1;
- long metaReplication = 1;
- int numBlock = 9;
-
- createClusters(true);
- mySetup(targetReplication, metaReplication, stripeLength);
- Path dir = new Path("/user/dhruba/raidtest/");
- Path file1 = new Path(dir + "/file1");
- RaidNode cnode = null;
- try {
- TestRaidNode.createOldFile(fileSys, file1, 1, numBlock, blockSize);
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- cnode = RaidNode.createRaidNode(null, localConf);
-
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file1, destPath);
-
- // delete original directory.
- assertTrue("Unable to delete original directory " + file1 ,
- fileSys.delete(file1.getParent(), true));
- LOG.info("deleted file " + file1);
-
- // wait till parity file and directory are automatically deleted
- long start = Time.now();
- while (fileSys.exists(destPath) &&
- Time.now() - start < 120000) {
- LOG.info("testPurgeDirectory waiting for parity files to be removed.");
- Thread.sleep(1000); // keep waiting
- }
- assertFalse(fileSys.exists(destPath));
-
- } catch (Exception e) {
- LOG.info("testPurgeDirectory Exception " + e +
- StringUtils.stringifyException(e));
- throw e;
- } finally {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- LOG.info("testPurgeDirectory delete file " + file1);
- fileSys.delete(file1, true);
- stopClusters();
- }
- }
-
- /**
- * Test that an XOR parity file is removed when a RS parity file is detected.
- */
- @Test
- public void testPurgePreference() throws Exception {
- createClusters(true);
- Path dir = new Path("/user/test/raidtest/");
- Path file1 = new Path(dir + "/file1");
-
- PolicyInfo infoXor = new PolicyInfo("testPurgePreference", conf);
- infoXor.setSrcPath("/user/test/raidtest");
- infoXor.setErasureCode("xor");
- infoXor.setDescription("test policy");
- infoXor.setProperty("targetReplication", "2");
- infoXor.setProperty("metaReplication", "2");
-
- PolicyInfo infoRs = new PolicyInfo("testPurgePreference", conf);
- infoRs.setSrcPath("/user/test/raidtest");
- infoRs.setErasureCode("rs");
- infoRs.setDescription("test policy");
- infoRs.setProperty("targetReplication", "1");
- infoRs.setProperty("metaReplication", "1");
- try {
- TestRaidNode.createOldFile(fileSys, file1, 1, 9, 8192L);
- FileStatus stat = fileSys.getFileStatus(file1);
-
- // Create the parity files.
- RaidNode.doRaid(
- conf, infoXor, stat, new RaidNode.Statistics(), Reporter.NULL);
- RaidNode.doRaid(
- conf, infoRs, stat, new RaidNode.Statistics(), Reporter.NULL);
- Path xorParity =
- new Path(RaidNode.DEFAULT_RAID_LOCATION, "user/test/raidtest/file1");
- Path rsParity =
- new Path(RaidNode.DEFAULT_RAIDRS_LOCATION, "user/test/raidtest/file1");
- assertTrue(fileSys.exists(xorParity));
- assertTrue(fileSys.exists(rsParity));
-
- // Check purge of a single parity file.
- RaidNode cnode = RaidNode.createRaidNode(conf);
- FileStatus raidRsStat =
- fileSys.getFileStatus(new Path(RaidNode.DEFAULT_RAIDRS_LOCATION));
- cnode.purgeMonitor.recursePurge(infoRs.getErasureCode(), fileSys, fileSys,
- RaidNode.DEFAULT_RAIDRS_LOCATION, raidRsStat);
-
- // Calling purge under the RS path has no effect.
- assertTrue(fileSys.exists(xorParity));
- assertTrue(fileSys.exists(rsParity));
-
- FileStatus raidStat =
- fileSys.getFileStatus(new Path(RaidNode.DEFAULT_RAID_LOCATION));
- cnode.purgeMonitor.recursePurge(infoXor.getErasureCode(), fileSys, fileSys,
- RaidNode.DEFAULT_RAID_LOCATION, raidStat);
- // XOR parity must have been purged by now.
- assertFalse(fileSys.exists(xorParity));
- assertTrue(fileSys.exists(rsParity));
-
- // Now check the purge of a parity har.
- // Delete the RS parity for now.
- fileSys.delete(rsParity);
- // Recreate the XOR parity.
- Path xorHar =
- new Path(RaidNode.DEFAULT_RAID_LOCATION, "user/test/raidtest/raidtest" +
- RaidNode.HAR_SUFFIX);
- RaidNode.doRaid(
- conf, infoXor, stat, new RaidNode.Statistics(), Reporter.NULL);
- assertTrue(fileSys.exists(xorParity));
- assertFalse(fileSys.exists(xorHar));
-
- // Create the har.
- long cutoff = Time.now();
- cnode.recurseHar(infoXor, fileSys, raidStat,
- RaidNode.DEFAULT_RAID_LOCATION, fileSys, cutoff,
- RaidNode.tmpHarPathForCode(conf, infoXor.getErasureCode()));
-
- // Call purge to get rid of the parity file. The har should remain.
- cnode.purgeMonitor.recursePurge(infoXor.getErasureCode(), fileSys, fileSys,
- RaidNode.DEFAULT_RAID_LOCATION, raidStat);
- // XOR har should exist but xor parity file should have been purged.
- assertFalse(fileSys.exists(xorParity));
- assertTrue(fileSys.exists(xorHar));
-
- // Now create the RS parity.
- RaidNode.doRaid(
- conf, infoRs, stat, new RaidNode.Statistics(), Reporter.NULL);
- cnode.purgeMonitor.recursePurge(infoXor.getErasureCode(), fileSys, fileSys,
- RaidNode.DEFAULT_RAID_LOCATION, raidStat);
- // XOR har should get deleted.
- assertTrue(fileSys.exists(rsParity));
- assertFalse(fileSys.exists(xorParity));
- assertFalse(fileSys.exists(xorHar));
-
- } finally {
- stopClusters();
- }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidShell.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidShell.java
deleted file mode 100644
index 1245e90b24f..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidShell.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Random;
-import java.util.zip.CRC32;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataInputStream;
-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.MiniDFSCluster;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-import org.apache.hadoop.hdfs.TestRaidDfs;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.util.StringUtils;
-import org.apache.hadoop.util.Time;
-import org.apache.hadoop.util.ToolRunner;
-import org.junit.Test;
-
-
-public class TestRaidShell {
- final static Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.TestRaidShell");
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
- final static String CONFIG_FILE = new File(TEST_DIR,
- "test-raid.xml").getAbsolutePath();
- final static long RELOAD_INTERVAL = 1000;
- final static int NUM_DATANODES = 3;
- Configuration conf;
- String namenode = null;
- MiniDFSCluster dfs = null;
- String hftp = null;
- FileSystem fileSys = null;
- RaidNode cnode = null;
- Random rand = new Random();
-
- /**
- * Create a file with three stripes, corrupt a block each in two stripes,
- * and wait for the the file to be fixed.
- */
- @Test
- public void testBlockFix() throws Exception {
- LOG.info("Test testBlockFix started.");
- long blockSize = 8192L;
- int stripeLength = 3;
- mySetup(stripeLength, -1);
- Path file1 = new Path("/user/dhruba/raidtest/file1");
- Path destPath = new Path("/destraid/user/dhruba/raidtest");
- Path parityFile = new Path(destPath, "file1");
- long crc1 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 7, blockSize);
- long file1Len = fileSys.getFileStatus(file1).getLen();
- LOG.info("Test testBlockFix created test files");
-
- // create an instance of the RaidNode
- Configuration localConf = new Configuration(conf);
- localConf.set(RaidNode.RAID_LOCATION_KEY, "/destraid");
- localConf.setInt("raid.blockfix.interval", 1000);
- // the RaidNode does the raiding inline (instead of submitting to map/reduce)
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- conf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.LocalBlockFixer");
- cnode = RaidNode.createRaidNode(null, localConf);
-
- try {
- TestRaidDfs.waitForFileRaided(LOG, fileSys, file1, destPath);
- cnode.stop();
- cnode.join();
- cnode = null;
-
- FileStatus srcStat = fileSys.getFileStatus(file1);
- LocatedBlocks locations = RaidDFSUtil.getBlockLocations(
- (DistributedFileSystem) fileSys, file1.toUri().getPath(),
- 0, srcStat.getLen());
-
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
-
- // Corrupt blocks in different stripes. We can fix them.
- int[] corruptBlockIdxs = new int[]{0, 4, 6};
- for (int idx: corruptBlockIdxs) {
- LOG.info("Corrupting block " + locations.get(idx).getBlock());
- corruptBlock(locations.get(idx).getBlock());
- }
- TestBlockFixer.reportCorruptBlocks(fileSys, file1, corruptBlockIdxs,
- srcStat.getBlockSize());
-
- waitForCorruptBlocks(corruptBlockIdxs.length, dfs, file1);
-
- // Create RaidShell and fix the file.
- RaidShell shell = new RaidShell(conf);
- String[] args = new String[2];
- args[0] = "-recoverBlocks";
- args[1] = file1.toUri().getPath();
- ToolRunner.run(shell, args);
-
- waitForCorruptBlocks(0, dfs, file1);
-
- assertTrue(TestRaidDfs.validateFile(dfs, file1, file1Len, crc1));
-
- // Now corrupt and fix the parity file.
- FileStatus parityStat = fileSys.getFileStatus(parityFile);
- long parityCrc = getCRC(fileSys, parityFile);
- locations = RaidDFSUtil.getBlockLocations(
- dfs, parityFile.toUri().getPath(), 0, parityStat.getLen());
- corruptBlock(locations.get(0).getBlock());
- TestBlockFixer.reportCorruptBlocks(fileSys, parityFile, new int[]{0},
- srcStat.getBlockSize());
- waitForCorruptBlocks(1, dfs, parityFile);
-
- args[1] = parityFile.toUri().getPath();
- ToolRunner.run(shell, args);
-
- waitForCorruptBlocks(0, dfs, file1);
- assertEquals(parityCrc, getCRC(fileSys, parityFile));
-
- } catch (Exception e) {
- LOG.info("Test testBlockFix Exception " + e + StringUtils.stringifyException(e));
- throw e;
- } finally {
- myTearDown();
- }
- LOG.info("Test testBlockFix completed.");
- }
-
- private void waitForCorruptBlocks(
- int numCorruptBlocks, DistributedFileSystem dfs, Path file)
- throws Exception {
- String path = file.toUri().getPath();
- FileStatus stat = dfs.getFileStatus(file);
- long start = Time.now();
- long actual = 0;
- do {
- actual = RaidDFSUtil.corruptBlocksInFile(
- dfs, path, 0, stat.getLen()).size();
- if (actual == numCorruptBlocks) break;
- if (Time.now() - start > 120000) break;
- LOG.info("Waiting for " + numCorruptBlocks + " corrupt blocks in " +
- path + ", found " + actual);
- Thread.sleep(1000);
- } while (true);
- assertEquals(numCorruptBlocks, actual);
- }
-
- private void mySetup(int stripeLength, int timeBeforeHar) throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
-
- conf.set("raid.config.file", CONFIG_FILE);
- conf.setBoolean("raid.config.reload", true);
- conf.setLong("raid.config.reload.interval", RELOAD_INTERVAL);
-
- // scan all policies once every 5 second
- conf.setLong("raid.policy.rescan.interval", 5000);
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- // do not use map-reduce cluster for Raiding
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- conf.set("raid.server.address", "localhost:0");
- conf.setInt("hdfs.raid.stripeLength", stripeLength);
- conf.set("hdfs.raid.locations", "/destraid");
-
- dfs = new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATANODES).build();
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
- namenode = fileSys.getUri().toString();
-
- FileSystem.setDefaultUri(conf, namenode);
- hftp = "hftp://localhost.localdomain:" + dfs.getNameNodePort();
-
- FileSystem.setDefaultUri(conf, namenode);
-
- FileWriter fileWriter = new FileWriter(CONFIG_FILE);
- fileWriter.write("\n");
- String str = " " +
- " " +
- " " +
- "xor " +
- " /destraid " +
- " " +
- "targetReplication " +
- "1 " +
- "after RAIDing, decrease the replication factor of a file to this value." +
- " " +
- " " +
- " " +
- "metaReplication " +
- "1 " +
- " replication factor of parity file" +
- " " +
- " " +
- " " +
- "modTimePeriod " +
- "2000 " +
- " time (milliseconds) after a file is modified to make it " +
- "a candidate for RAIDing " +
- " " +
- " ";
- if (timeBeforeHar >= 0) {
- str +=
- " " +
- "time_before_har " +
- "" + timeBeforeHar + " " +
- " amount of time waited before har'ing parity files" +
- " " +
- " ";
- }
-
- str +=
- "" +
- "" +
- "";
- fileWriter.write(str);
- fileWriter.close();
- }
-
- private void myTearDown() throws Exception {
- if (cnode != null) { cnode.stop(); cnode.join(); }
- if (dfs != null) { dfs.shutdown(); }
- }
-
- private long getCRC(FileSystem fs, Path p) throws IOException {
- CRC32 crc = new CRC32();
- FSDataInputStream stm = fs.open(p);
- int b;
- while ((b = stm.read())>=0) {
- crc.update(b);
- }
- stm.close();
- return crc.getValue();
- }
-
- void corruptBlock(ExtendedBlock block) throws IOException {
- assertTrue("Could not corrupt block",
- dfs.corruptBlockOnDataNodes(block) > 0);
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidShellFsck.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidShellFsck.java
deleted file mode 100644
index bf7cdc05ebc..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestRaidShellFsck.java
+++ /dev/null
@@ -1,724 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.Random;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FSDataOutputStream;
-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.MiniDFSCluster;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-import org.apache.hadoop.hdfs.TestRaidDfs;
-import org.apache.hadoop.hdfs.protocol.LocatedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.util.Time;
-import org.apache.hadoop.util.ToolRunner;
-import org.junit.After;
-import org.junit.Test;
-
-
-public class TestRaidShellFsck {
- final static Log LOG =
- LogFactory.getLog("org.apache.hadoop.raid.TestRaidShellFsck");
- final static String TEST_DIR =
- new File(System.
- getProperty("test.build.data", "target/test-data")).getAbsolutePath();
-
- final static String CONFIG_FILE = new File(TEST_DIR, "test-raid.xml").
- getAbsolutePath();
- final static long RELOAD_INTERVAL = 1000;
- final static int NUM_DATANODES = 4;
- final static int STRIPE_BLOCKS = 3; // number of blocks per stripe
- final static int FILE_BLOCKS = 6; // number of blocks that file consists of
- final static short REPL = 1; // replication factor before raiding
- final static long BLOCK_SIZE = 8192L; // size of block in byte
- final static String DIR_PATH = "/user/pkling/raidtest";
- final static Path FILE_PATH0 =
- new Path("/user/pkling/raidtest/raidfsck.test");
- final static Path FILE_PATH1 =
- new Path("/user/pkling/raidtest/raidfsck2.test");
- final static Path RAID_PATH = new Path("/destraid/user/pkling/raidtest");
- final static String HAR_NAME = "raidtest_raid.har";
- final static String RAID_DIR = "/destraid";
-
- Configuration conf = null;
- Configuration raidConf = null;
- Configuration clientConf = null;
- MiniDFSCluster cluster = null;
- DistributedFileSystem dfs = null;
- RaidNode rnode = null;
-
-
- RaidShell shell = null;
- String[] args = null;
-
-
- /**
- * creates a MiniDFS instance with a raided file in it
- */
- private void setUp(boolean doHar) throws IOException, ClassNotFoundException {
-
- final int timeBeforeHar;
- if (doHar) {
- timeBeforeHar = 0;
- } else {
- timeBeforeHar = -1;
- }
-
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
-
- conf.set("raid.config.file", CONFIG_FILE);
- conf.setBoolean("raid.config.reload", true);
- conf.setLong("raid.config.reload.interval", RELOAD_INTERVAL);
-
- // scan all policies once every 5 second
- conf.setLong("raid.policy.rescan.interval", 5000);
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- // do not use map-reduce cluster for Raiding
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- // use local block fixer
- conf.set("raid.blockfix.classname",
- "org.apache.hadoop.raid.LocalBlockFixer");
-
- conf.set("raid.server.address", "localhost:0");
- conf.setInt("hdfs.raid.stripeLength", STRIPE_BLOCKS);
- conf.set("hdfs.raid.locations", RAID_DIR);
-
- conf.setInt("dfs.corruptfilesreturned.max", 500);
-
- conf.setBoolean("dfs.permissions", false);
-
- cluster = new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATANODES)
- .build();
- cluster.waitActive();
- dfs = (DistributedFileSystem) cluster.getFileSystem();
- String namenode = dfs.getUri().toString();
-
- FileSystem.setDefaultUri(conf, namenode);
-
- FileWriter fileWriter = new FileWriter(CONFIG_FILE);
- fileWriter.write("\n");
- String str =
- " " +
- " " +
- " " +
- " xor " +
- " " + RAID_DIR + " " +
- " " +
- " targetReplication " +
- " 1 " +
- " after RAIDing, decrease the replication " +
- "factor of a file to this value. " +
- " " +
- " " +
- " metaReplication " +
- " 1 " +
- " replication factor of parity file " +
- " " +
- " " +
- " modTimePeriod " +
- " 2000 " +
- " time (milliseconds) after a file is modified " +
- "to make it a candidate for RAIDing " +
- " ";
-
- if (timeBeforeHar >= 0) {
- str +=
- " " +
- " time_before_har " +
- " " + timeBeforeHar + " " +
- " amount of time waited before har'ing parity " +
- "files " +
- " ";
- }
-
- str +=
- " " +
- " " +
- "";
-
- fileWriter.write(str);
- fileWriter.close();
-
- createTestFile(FILE_PATH0);
- createTestFile(FILE_PATH1);
-
- Path[] filePaths = { FILE_PATH0, FILE_PATH1 };
- raidTestFiles(RAID_PATH, filePaths, doHar);
-
- clientConf = new Configuration(raidConf);
- clientConf.set("fs.hdfs.impl",
- "org.apache.hadoop.hdfs.DistributedRaidFileSystem");
- clientConf.set("fs.raid.underlyingfs.impl",
- "org.apache.hadoop.hdfs.DistributedFileSystem");
-
- // prepare shell and arguments
- shell = new RaidShell(clientConf);
- args = new String[2];
- args[0] = "-fsck";
- args[1] = DIR_PATH;
-
- }
-
- /**
- * Creates test file consisting of random data
- */
- private void createTestFile(Path filePath) throws IOException {
- Random rand = new Random();
- FSDataOutputStream stm = dfs.create(filePath, true,
- conf.getInt("io.file.buffer.size",
- 4096), REPL, BLOCK_SIZE);
-
- final byte[] b = new byte[(int) BLOCK_SIZE];
- for (int i = 0; i < FILE_BLOCKS; i++) {
- rand.nextBytes(b);
- stm.write(b);
- }
- stm.close();
- LOG.info("test file created");
-
- }
-
- /**
- * raids test file
- */
- private void raidTestFiles(Path raidPath, Path[] filePaths, boolean doHar)
- throws IOException, ClassNotFoundException {
- // create RaidNode
- raidConf = new Configuration(conf);
- raidConf.set(RaidNode.RAID_LOCATION_KEY, RAID_DIR);
- raidConf.setInt("raid.blockfix.interval", 1000);
- raidConf.setLong("har.block.size", BLOCK_SIZE * 3);
- // the RaidNode does the raiding inline (instead of submitting to MR node)
- conf.set("raid.classname", "org.apache.hadoop.raid.LocalRaidNode");
- rnode = RaidNode.createRaidNode(null, raidConf);
-
- for (Path filePath: filePaths) {
- long waitStart = Time.now();
- boolean raided = false;
-
- Path parityFilePath = new Path(RAID_DIR,
- filePath.toString().substring(1));
-
- while (!raided) {
- try {
- FileStatus[] listPaths = dfs.listStatus(raidPath);
- if (listPaths != null) {
- if (doHar) {
- // case with HAR
- for (FileStatus f: listPaths) {
- if (f.getPath().toString().endsWith(".har")) {
- // check if the parity file is in the index
- final Path indexPath = new Path(f.getPath(), "_index");
- final FileStatus indexFileStatus =
- dfs.getFileStatus(indexPath);
- final HarIndex harIndex =
- new HarIndex(dfs.open(indexPath), indexFileStatus.getLen());
- final HarIndex.IndexEntry indexEntry =
- harIndex.findEntryByFileName(parityFilePath.toString());
- if (indexEntry != null) {
- LOG.info("raid file " + parityFilePath.toString() +
- " found in Har archive: " +
- f.getPath().toString() +
- " ts=" + indexEntry.mtime);
- raided = true;
- break;
- }
- }
- }
-
- } else {
- // case without HAR
- for (FileStatus f : listPaths) {
- Path found = new Path(f.getPath().toUri().getPath());
- if (parityFilePath.equals(found)) {
- LOG.info("raid file found: " + f.getPath().toString());
- raided = true;
- break;
- }
- }
- }
- }
- } catch (FileNotFoundException ignore) {
- }
- if (!raided) {
- if (Time.now() > waitStart + 40000L) {
- LOG.error("parity file not created after 40s");
- throw new IOException("parity file not HARed after 40s");
- } else {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ignore) {
- }
- }
- }
- }
- }
-
- rnode.stop();
- rnode.join();
- rnode = null;
- LOG.info("test file raided");
- }
-
- /**
- * sleeps for up to 20s until the number of corrupt files
- * in the file system is equal to the number specified
- */
- private void waitUntilCorruptFileCount(DistributedFileSystem dfs,
- int corruptFiles)
- throws IOException {
- long waitStart = Time.now();
- while (RaidDFSUtil.getCorruptFiles(dfs).length != corruptFiles) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException ignore) {
-
- }
-
- if (Time.now() > waitStart + 20000L) {
- break;
- }
- }
-
- int corruptFilesFound = RaidDFSUtil.getCorruptFiles(dfs).length;
- if (corruptFilesFound != corruptFiles) {
- throw new IOException("expected " + corruptFiles +
- " corrupt files but got " +
- corruptFilesFound);
- }
- }
-
- /**
- * removes a specified block from MiniDFS storage and reports it as corrupt
- */
- private void removeAndReportBlock(DistributedFileSystem blockDfs,
- Path filePath,
- LocatedBlock block)
- throws IOException {
- TestRaidDfs.corruptBlock(cluster, filePath, block.getBlock(), NUM_DATANODES, true);
-
- // report deleted block to the name node
- LocatedBlock[] toReport = { block };
- blockDfs.getClient().getNamenode().reportBadBlocks(toReport);
-
- }
-
-
- /**
- * removes a file block in the specified stripe
- */
- private void removeFileBlock(Path filePath, int stripe, int blockInStripe)
- throws IOException {
- LocatedBlocks fileBlocks = dfs.getClient().getNamenode().
- getBlockLocations(filePath.toString(), 0, FILE_BLOCKS * BLOCK_SIZE);
- if (fileBlocks.locatedBlockCount() != FILE_BLOCKS) {
- throw new IOException("expected " + FILE_BLOCKS +
- " file blocks but found " +
- fileBlocks.locatedBlockCount());
- }
- if (blockInStripe >= STRIPE_BLOCKS) {
- throw new IOException("blockInStripe is " + blockInStripe +
- " but must be smaller than " + STRIPE_BLOCKS);
- }
- LocatedBlock block = fileBlocks.get(stripe * STRIPE_BLOCKS + blockInStripe);
- removeAndReportBlock(dfs, filePath, block);
- LOG.info("removed file " + filePath.toString() + " block " +
- stripe * STRIPE_BLOCKS + " in stripe " + stripe);
- }
-
- /**
- * removes a parity block in the specified stripe
- */
- private void removeParityBlock(Path filePath, int stripe) throws IOException {
- // find parity file
- Path destPath = new Path(RAID_DIR);
- RaidNode.ParityFilePair ppair = null;
-
- ppair = RaidNode.getParityFile(destPath, filePath, conf);
- String parityPathStr = ppair.getPath().toUri().getPath();
- LOG.info("parity path: " + parityPathStr);
- FileSystem parityFS = ppair.getFileSystem();
- if (!(parityFS instanceof DistributedFileSystem)) {
- throw new IOException("parity file is not on distributed file system");
- }
- DistributedFileSystem parityDFS = (DistributedFileSystem) parityFS;
-
-
- // now corrupt the block corresponding to the stripe selected
- FileStatus parityFileStatus =
- parityDFS.getFileStatus(new Path(parityPathStr));
- long parityBlockSize = parityFileStatus.getBlockSize();
- long parityFileLength = parityFileStatus.getLen();
- long parityFileLengthInBlocks = (parityFileLength / parityBlockSize) +
- (((parityFileLength % parityBlockSize) == 0) ? 0L : 1L);
- if (parityFileLengthInBlocks <= stripe) {
- throw new IOException("selected stripe " + stripe +
- " but parity file only has " +
- parityFileLengthInBlocks + " blocks");
- }
- if (parityBlockSize != BLOCK_SIZE) {
- throw new IOException("file block size is " + BLOCK_SIZE +
- " but parity file block size is " +
- parityBlockSize);
- }
- LocatedBlocks parityFileBlocks = parityDFS.getClient().getNamenode().
- getBlockLocations(parityPathStr, 0, parityFileLength);
- if (parityFileBlocks.locatedBlockCount() != parityFileLengthInBlocks) {
- throw new IOException("expected " + parityFileLengthInBlocks +
- " parity file blocks but got " +
- parityFileBlocks.locatedBlockCount() +
- " blocks");
- }
- LocatedBlock parityFileBlock = parityFileBlocks.get(stripe);
- removeAndReportBlock(parityDFS, new Path(parityPathStr), parityFileBlock);
- LOG.info("removed parity file block/stripe " + stripe +
- " for " + filePath.toString());
-
- }
-
- /**
- * removes a block from the har part file
- */
- private void removeHarParityBlock(int block) throws IOException {
- Path harPath = new Path(RAID_PATH, HAR_NAME);
- FileStatus [] listPaths = dfs.listStatus(harPath);
-
- boolean deleted = false;
-
- for (FileStatus f: listPaths) {
- if (f.getPath().getName().startsWith("part-")) {
- final Path partPath = new Path(f.getPath().toUri().getPath());
- final LocatedBlocks partBlocks = dfs.getClient().getNamenode().
- getBlockLocations(partPath.toString(),
- 0,
- f.getLen());
-
- if (partBlocks.locatedBlockCount() <= block) {
- throw new IOException("invalid har block " + block);
- }
-
- final LocatedBlock partBlock = partBlocks.get(block);
- removeAndReportBlock(dfs, partPath, partBlock);
- LOG.info("removed block " + block + "/" +
- partBlocks.locatedBlockCount() +
- " of file " + partPath.toString() +
- " block size " + partBlock.getBlockSize());
- deleted = true;
- break;
- }
- }
-
- if (!deleted) {
- throw new IOException("cannot find part file in " + harPath.toString());
- }
- }
-
- /**
- * checks fsck with no missing blocks
- */
- @Test
- public void testClean() throws Exception {
- LOG.info("testClean");
- setUp(false);
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 0, but returns " +
- Integer.toString(result), result == 0);
- }
-
-
- /**
- * checks fsck with missing block in file block but not in parity block
- */
- @Test
- public void testFileBlockMissing() throws Exception {
- LOG.info("testFileBlockMissing");
- setUp(false);
- waitUntilCorruptFileCount(dfs, 0);
- removeFileBlock(FILE_PATH0, 0, 0);
- waitUntilCorruptFileCount(dfs, 1);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 0, but returns " +
- Integer.toString(result), result == 0);
- }
-
- /**
- * checks fsck with missing block in parity block but not in file block
- */
- @Test
- public void testParityBlockMissing() throws Exception {
- LOG.info("testParityBlockMissing");
- setUp(false);
- waitUntilCorruptFileCount(dfs, 0);
- removeParityBlock(FILE_PATH0, 0);
- waitUntilCorruptFileCount(dfs, 1);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 0, but returns " +
- Integer.toString(result), result == 0);
- }
-
- /**
- * checks fsck with missing block in both file block and parity block
- * in different stripes
- */
- @Test
- public void testFileBlockAndParityBlockMissingInDifferentStripes()
- throws Exception {
- LOG.info("testFileBlockAndParityBlockMissingInDifferentStripes");
- setUp(false);
- waitUntilCorruptFileCount(dfs, 0);
- removeFileBlock(FILE_PATH0, 0, 0);
- waitUntilCorruptFileCount(dfs, 1);
- removeParityBlock(FILE_PATH0, 1);
- waitUntilCorruptFileCount(dfs, 2);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 0, but returns " +
- Integer.toString(result), result == 0);
- }
-
- /**
- * checks fsck with missing block in both file block and parity block
- * in same stripe
- */
- @Test
- public void testFileBlockAndParityBlockMissingInSameStripe()
- throws Exception {
- LOG.info("testFileBlockAndParityBlockMissingInSameStripe");
- setUp(false);
- waitUntilCorruptFileCount(dfs, 0);
- removeParityBlock(FILE_PATH0, 1);
- waitUntilCorruptFileCount(dfs, 1);
- removeFileBlock(FILE_PATH0, 1, 0);
- waitUntilCorruptFileCount(dfs, 2);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 1, but returns " +
- Integer.toString(result), result == 1);
- }
-
- /**
- * checks fsck with two missing file blocks in same stripe
- */
- @Test
- public void test2FileBlocksMissingInSameStripe()
- throws Exception {
- LOG.info("test2FileBlocksMissingInSameStripe");
- setUp(false);
- waitUntilCorruptFileCount(dfs, 0);
- removeFileBlock(FILE_PATH0, 1, 1);
- waitUntilCorruptFileCount(dfs, 1);
- removeFileBlock(FILE_PATH0, 1, 0);
- waitUntilCorruptFileCount(dfs, 1);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 1, but returns " +
- Integer.toString(result), result == 1);
- }
-
- /**
- * checks fsck with two missing file blocks in different stripes
- */
- @Test
- public void test2FileBlocksMissingInDifferentStripes()
- throws Exception {
- LOG.info("test2FileBlocksMissingInDifferentStripes");
- setUp(false);
- waitUntilCorruptFileCount(dfs, 0);
- removeFileBlock(FILE_PATH0, 1, 1);
- waitUntilCorruptFileCount(dfs, 1);
- removeFileBlock(FILE_PATH0, 0, 0);
- waitUntilCorruptFileCount(dfs, 1);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 0, but returns " +
- Integer.toString(result), result == 0);
- }
-
- /**
- * checks fsck with file block missing (HAR)
- * use 2 files to verify HAR offset logic in RaidShell fsck
- * both files have one corrupt block, parity blocks are clean
- *
- * parity blocks in har (file.stripe):
- * +-----+-----+-----+ +-----+
- * | 0.0 | 0.1 | 1.0 | | 1.1 |
- * +-----+-----+-----+ +-----+
- * 0 1
- *
- */
- @Test
- public void testFileBlockMissingHar()
- throws Exception {
- LOG.info("testFileBlockMissingHar");
- setUp(true);
- waitUntilCorruptFileCount(dfs, 0);
- removeFileBlock(FILE_PATH0, 1, 1);
- removeFileBlock(FILE_PATH1, 1, 1);
- waitUntilCorruptFileCount(dfs, 2);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 0, but returns " +
- Integer.toString(result), result == 0);
- }
-
- /**
- * checks fsck with file block missing (HAR)
- * use 2 files to verify HAR offset logic in RaidShell fsck
- *
- * parity blocks in har (file.stripe):
- * +-----+-----+-----+ +-----+
- * | 0.0 | 0.1 | 1.0 | | 1.1 |
- * +-----+-----+-----+ +-----+
- * 0 1
- *
- * corrupt file 0, stripe 0 file block 0
- * corrupt file 0, stripe 1 file block 0
- * corrupt file 1, stripe 0 file block 0
- * corrupt file 1, stripe 1 file block 0
- * corrupt har block 0
- * both files should be corrupt
- */
- @Test
- public void testFileBlockAndParityBlockMissingHar1()
- throws Exception {
- LOG.info("testFileBlockAndParityBlockMissingHar1");
- setUp(true);
- waitUntilCorruptFileCount(dfs, 0);
- removeFileBlock(FILE_PATH0, 0, 0);
- removeFileBlock(FILE_PATH0, 1, 0);
- removeFileBlock(FILE_PATH1, 0, 0);
- removeFileBlock(FILE_PATH1, 1, 0);
- removeHarParityBlock(0);
- waitUntilCorruptFileCount(dfs, 3);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 2, but returns " +
- Integer.toString(result), result == 2);
- }
-
- /**
- * checks fsck with file block missing (HAR)
- * use 2 files to verify HAR offset logic in RaidShell fsck
- *
- * parity blocks in har (file.stripe):
- * +-----+-----+-----+ +-----+
- * | 0.0 | 0.1 | 1.0 | | 1.1 |
- * +-----+-----+-----+ +-----+
- * 0 1
- *
- * corrupt file 0, stripe 0 file block 0
- * corrupt file 0, stripe 1 file block 0
- * corrupt file 1, stripe 0 file block 0
- * corrupt file 1, stripe 1 file block 0
- * corrupt har block 1
- * only file 2 should be corrupt
- */
- @Test
- public void testFileBlockAndParityBlockMissingHar2()
- throws Exception {
- LOG.info("testFileBlockAndParityBlockMissingHar2");
- setUp(true);
- waitUntilCorruptFileCount(dfs, 0);
- removeFileBlock(FILE_PATH0, 0, 0);
- removeFileBlock(FILE_PATH0, 1, 0);
- removeFileBlock(FILE_PATH1, 0, 0);
- removeFileBlock(FILE_PATH1, 1, 0);
- removeHarParityBlock(1);
- waitUntilCorruptFileCount(dfs, 3);
-
- int result = ToolRunner.run(shell, args);
-
- assertTrue("fsck should return 1, but returns " +
- Integer.toString(result), result == 1);
- }
-
- /**
- * checks that fsck does not report corrupt file that is not in
- * the specified path
- */
- @Test
- public void testPathFilter()
- throws Exception {
- LOG.info("testPathFilter");
- setUp(false);
- waitUntilCorruptFileCount(dfs, 0);
- removeParityBlock(FILE_PATH0, 1);
- waitUntilCorruptFileCount(dfs, 1);
- removeFileBlock(FILE_PATH0, 1, 0);
- waitUntilCorruptFileCount(dfs, 2);
-
- String[] otherArgs = new String[2];
- otherArgs[0] = "-fsck";
- otherArgs[1] = "/user/pkling/other";
- int result = ToolRunner.run(shell, otherArgs);
-
- assertTrue("fsck should return 0, but returns " +
- Integer.toString(result), result == 0);
- }
-
-
- @After
- public void tearDown() throws Exception {
- if (rnode != null) {
- rnode.stop();
- rnode.join();
- rnode = null;
- }
-
- if (cluster != null) {
- cluster.shutdown();
- cluster = null;
- }
-
- dfs = null;
-
- LOG.info("Test cluster shut down");
- }
-
-
-}
-
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestReedSolomonDecoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestReedSolomonDecoder.java
deleted file mode 100644
index d51617569cf..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestReedSolomonDecoder.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.io.File;
-import java.io.IOException;
-
-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.MiniDFSCluster;
-import org.apache.hadoop.hdfs.RaidDFSUtil;
-import org.apache.hadoop.hdfs.TestRaidDfs;
-import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
-import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.mapred.Reporter;
-import org.junit.Test;
-
-
-public class TestReedSolomonDecoder {
- final static Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.TestReedSolomonDecoder");
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
- final static int NUM_DATANODES = 3;
-
- Configuration conf;
- MiniDFSCluster dfs = null;
- FileSystem fileSys = null;
-
- @Test
- public void testDecoder() throws Exception {
- mySetup();
- int stripeSize = 10;
- int paritySize = 4;
- long blockSize = 8192;
- Path file1 = new Path("/user/raidtest/file1");
- Path recoveredFile1 = new Path("/user/raidtest/file1.recovered");
- Path parityFile1 = new Path("/rsraid/user/raidtest/file1");
- long crc1 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 25, blockSize);
- FileStatus file1Stat = fileSys.getFileStatus(file1);
-
- conf.setInt("raid.rsdecoder.bufsize", 512);
- conf.setInt("raid.rsencoder.bufsize", 512);
-
- try {
- // First encode the file.
- ReedSolomonEncoder encoder = new ReedSolomonEncoder(
- conf, stripeSize, paritySize);
- short parityRepl = 1;
- encoder.encodeFile(fileSys, file1, fileSys, parityFile1, parityRepl,
- Reporter.NULL);
-
- // Ensure there are no corrupt files yet.
- DistributedFileSystem dfs = (DistributedFileSystem)fileSys;
- String[] corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals(corruptFiles.length, 0);
-
- // Now corrupt the file.
- long corruptOffset = blockSize * 5;
- FileStatus srcStat = fileSys.getFileStatus(file1);
- LocatedBlocks locations = RaidDFSUtil.getBlockLocations(dfs,
- file1.toUri().getPath(), 0, srcStat.getLen());
- corruptBlock(locations.get(5).getBlock());
- corruptBlock(locations.get(6).getBlock());
- TestBlockFixer.reportCorruptBlocks(dfs, file1, new int[]{5, 6},
- srcStat.getBlockSize());
-
- // Ensure file is corrupted.
- corruptFiles = RaidDFSUtil.getCorruptFiles(dfs);
- assertEquals(corruptFiles.length, 1);
- assertEquals(corruptFiles[0], file1.toString());
-
- // Fix the file.
- ReedSolomonDecoder decoder = new ReedSolomonDecoder(
- conf, stripeSize, paritySize);
- decoder.decodeFile(fileSys, file1, fileSys, parityFile1,
- corruptOffset, recoveredFile1);
- assertTrue(TestRaidDfs.validateFile(
- fileSys, recoveredFile1, file1Stat.getLen(), crc1));
- } finally {
- myTearDown();
- }
- }
-
- void corruptBlock(ExtendedBlock block) throws IOException {
- assertTrue("Could not corrupt block",
- dfs.corruptBlockOnDataNodes(block) > 0);
- }
-
- private void mySetup() throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- conf.setBoolean("dfs.permissions", false);
-
- dfs = new MiniDFSCluster.Builder(conf).numDataNodes(NUM_DATANODES).build();
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
- String namenode = fileSys.getUri().toString();
- FileSystem.setDefaultUri(conf, namenode);
- }
-
- private void myTearDown() throws Exception {
- if (dfs != null) { dfs.shutdown(); }
- }
-}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestReedSolomonEncoder.java b/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestReedSolomonEncoder.java
deleted file mode 100644
index 86111d05e00..00000000000
--- a/hadoop-hdfs-project/hadoop-hdfs-raid/src/test/java/org/apache/hadoop/raid/TestReedSolomonEncoder.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * 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.raid;
-
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-
-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.MiniDFSCluster;
-import org.apache.hadoop.hdfs.TestRaidDfs;
-import org.apache.hadoop.mapred.Reporter;
-import org.junit.Test;
-
-
-public class TestReedSolomonEncoder {
- final static Log LOG = LogFactory.getLog(
- "org.apache.hadoop.raid.TestReedSolomonEncoder");
- final static String TEST_DIR = new File(System.getProperty("test.build.data",
- "target/test-data")).getAbsolutePath();
- final static int NUM_DATANODES = 3;
-
- Configuration conf;
- String namenode = null;
- MiniDFSCluster dfs = null;
- FileSystem fileSys = null;
-
- @Test
- public void testEncoder() throws Exception {
- mySetup();
- int stripeSize = 10;
- int paritySize = 4;
- long blockSize = 8192;
- Path file1 = new Path("/user/raidtest/file1");
- Path parityFile1 = new Path("/rsraid/user/raidtest/file1");
- long crc1 = TestRaidDfs.createTestFilePartialLastBlock(fileSys, file1,
- 1, 25, blockSize);
- try {
- ReedSolomonEncoder encoder = new ReedSolomonEncoder(
- conf, stripeSize, paritySize);
- short parityRepl = 1;
- encoder.encodeFile(fileSys, file1, fileSys, parityFile1, parityRepl,
- Reporter.NULL);
-
- FileStatus parityStat = fileSys.getFileStatus(parityFile1);
- assertEquals(4*8192*3, parityStat.getLen());
-
- } finally {
- myTearDown();
- }
- }
-
- private void mySetup() throws Exception {
-
- new File(TEST_DIR).mkdirs(); // Make sure data directory exists
- conf = new Configuration();
-
- // make all deletions not go through Trash
- conf.set("fs.shell.delete.classname", "org.apache.hadoop.hdfs.DFSClient");
-
- dfs = new MiniDFSCluster(conf, NUM_DATANODES, true, null);
- dfs.waitActive();
- fileSys = dfs.getFileSystem();
- namenode = fileSys.getUri().toString();
-
- FileSystem.setDefaultUri(conf, namenode);
-
- }
-
- private void myTearDown() throws Exception {
- if (dfs != null) { dfs.shutdown(); }
- }
-}
diff --git a/hadoop-hdfs-project/pom.xml b/hadoop-hdfs-project/pom.xml
index 38c93fa8bd1..27161004a36 100644
--- a/hadoop-hdfs-project/pom.xml
+++ b/hadoop-hdfs-project/pom.xml
@@ -34,7 +34,6 @@ http://maven.apache.org/xsd/maven-4.0.0.xsd">
hadoop-hdfshadoop-hdfs-httpfshadoop-hdfs/src/contrib/bkjournal
- hadoop-hdfs-raid
diff --git a/hadoop-mapreduce-project/build.xml b/hadoop-mapreduce-project/build.xml
index 6a8a7d0be1f..286af16530b 100644
--- a/hadoop-mapreduce-project/build.xml
+++ b/hadoop-mapreduce-project/build.xml
@@ -1711,10 +1711,6 @@
output="${build.dir.eclipse-contrib-classes}/gridmix/main" />
-
-
- Tests failed!
diff --git a/hadoop-mapreduce-project/src/contrib/raid/README b/hadoop-mapreduce-project/src/contrib/raid/README
deleted file mode 100644
index b1662b42bef..00000000000
--- a/hadoop-mapreduce-project/src/contrib/raid/README
+++ /dev/null
@@ -1,201 +0,0 @@
-# Copyright 2008 The Apache Software Foundation Licensed 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.
-
-This package implements a Distributed Raid File System. It is used alongwith
-an instance of the Hadoop Distributed File System (HDFS). It can be used to
-provide better protection against data corruption. It can also be used to
-reduce the total storage requirements of HDFS.
-
-Distributed Raid File System consists of two main software components. The first component
-is the RaidNode, a daemon that creates parity files from specified HDFS files.
-The second component "raidfs" is a software that is layered over a HDFS client and it
-intercepts all calls that an application makes to the HDFS client. If HDFS encounters
-corrupted data while reading a file, the raidfs client detects it; it uses the
-relevant parity blocks to recover the corrupted data (if possible) and returns
-the data to the application. The application is completely transparent to the
-fact that parity data was used to satisfy it's read request.
-
-The primary use of this feature is to save disk space for HDFS files.
-HDFS typically stores data in triplicate.
-The Distributed Raid File System can be configured in such a way that a set of
-data blocks of a file are combined together to form one or more parity blocks.
-This allows one to reduce the replication factor of a HDFS file from 3 to 2
-while keeping the failure probabilty relatively same as before. This typically
-results in saving 25% to 30% of storage space in a HDFS cluster.
-
---------------------------------------------------------------------------------
-
-BUILDING:
-
-In HADOOP_PREFIX, run ant package to build Hadoop and its contrib packages.
-
---------------------------------------------------------------------------------
-
-INSTALLING and CONFIGURING:
-
-The entire code is packaged in the form of a single jar file hadoop-*-raid.jar.
-To use HDFS Raid, you need to put the above mentioned jar file on
-the CLASSPATH. The easiest way is to copy the hadoop-*-raid.jar
-from HADOOP_PREFIX/build/contrib/raid to HADOOP_PREFIX/lib. Alternatively
-you can modify HADOOP_CLASSPATH to include this jar, in conf/hadoop-env.sh.
-
-There is a single configuration file named raid.xml that describes the HDFS
-path(s) that you want to raid. A sample of this file can be found in
-sc/contrib/raid/conf/raid.xml. Please edit the entries in this file to list the
-path(s) that you want to raid. Then, edit the hdfs-site.xml file for
-your installation to include a reference to this raid.xml. You can add the
-following to your hdfs-site.xml
-
- raid.config.file
- /mnt/hdfs/DFS/conf/raid.xml
- This is needed by the RaidNode
-
-
-Please add an entry to your hdfs-site.xml to enable hdfs clients to use the
-parity bits to recover corrupted data.
-
-
- fs.hdfs.impl
- org.apache.hadoop.dfs.DistributedRaidFileSystem
- The FileSystem for hdfs: uris.
-
-
-
---------------------------------------------------------------------------------
-
-OPTIONAL CONFIGIURATION:
-
-The following properties can be set in hdfs-site.xml to further tune you configuration:
-
- Specifies the location where parity files are located.
-
- hdfs.raid.locations
- hdfs://newdfs.data:8000/raid
- The location for parity files. If this is
- is not defined, then defaults to /raid.
-
-
-
- Specify the parity stripe length
-
- hdfs.raid.stripeLength
- 10
- The number of blocks in a file to be combined into
- a single raid parity block. The default value is 5. The lower
- the number the greater is the disk space you will save when you
- enable raid.
-
-
-
- Specify the size of HAR part-files
-
- raid.har.partfile.size
- 4294967296
- The size of HAR part files that store raid parity
- files. The default is 4GB. The higher the number the fewer the
- number of files used to store the HAR archive.
-
-
-
- Specify which implementation of RaidNode to use.
-
- raid.classname
- org.apache.hadoop.raid.DistRaidNode
- Specify which implementation of RaidNode to use
- (class name).
-
-
-
-
- Specify the periodicy at which the RaidNode re-calculates (if necessary)
- the parity blocks
-
- raid.policy.rescan.interval
- 5000
- Specify the periodicity in milliseconds after which
- all source paths are rescanned and parity blocks recomputed if
- necessary. By default, this value is 1 hour.
-
-
-
- By default, the DistributedRaidFileSystem assumes that the underlying file
- system is the DistributedFileSystem. If you want to layer the DistributedRaidFileSystem
- over some other file system, then define a property named fs.raid.underlyingfs.impl
- that specifies the name of the underlying class. For example, if you want to layer
- The DistributedRaidFileSystem over an instance of the NewFileSystem, then
-
- fs.raid.underlyingfs.impl
- org.apche.hadoop.new.NewFileSystem
- Specify the filesystem that is layered immediately below the
- DistributedRaidFileSystem. By default, this value is DistributedFileSystem.
-
-
-
---------------------------------------------------------------------------------
-
-ADMINISTRATION:
-
-The Distributed Raid File System provides support for administration at runtime without
-any downtime to cluster services. It is possible to add/delete new paths to be raided without
-interrupting any load on the cluster. If you change raid.xml, its contents will be
-reload within seconds and the new contents will take effect immediately.
-
-Designate one machine in your cluster to run the RaidNode software. You can run this daemon
-on any machine irrespective of whether that machine is running any other hadoop daemon or not.
-You can start the RaidNode by running the following on the selected machine:
-nohup $HADOOP_PREFIX/bin/hadoop org.apache.hadoop.raid.RaidNode >> /xxx/logs/hadoop-root-raidnode-hadoop.xxx.com.log &
-
-Optionally, we provide two scripts to start and stop the RaidNode. Copy the scripts
-start-raidnode.sh and stop-raidnode.sh to the directory $HADOOP_PREFIX/bin in the machine
-you would like to deploy the daemon. You can start or stop the RaidNode by directly
-callying the scripts from that machine. If you want to deploy the RaidNode remotely,
-copy start-raidnode-remote.sh and stop-raidnode-remote.sh to $HADOOP_PREFIX/bin at
-the machine from which you want to trigger the remote deployment and create a text
-file $HADOOP_PREFIX/conf/raidnode at the same machine containing the name of the server
-where the RaidNode should run. These scripts run ssh to the specified machine and
-invoke start/stop-raidnode.sh there. As an example, you might want to change
-start-mapred.sh in the JobTracker machine so that it automatically calls
-start-raidnode-remote.sh (and do the equivalent thing for stop-mapred.sh and
-stop-raidnode-remote.sh).
-
-To validate the integrity of a file system, run RaidFSCK as follows:
-$HADOOP_PREFIX/bin/hadoop org.apache.hadoop.raid.RaidShell -fsck [path]
-
-This will print a list of corrupt files (i.e., files which have lost too many
-blocks and can no longer be fixed by Raid).
-
-
---------------------------------------------------------------------------------
-
-IMPLEMENTATION:
-
-The RaidNode periodically scans all the specified paths in the configuration
-file. For each path, it recursively scans all files that have more than 2 blocks
-and that has not been modified during the last few hours (default is 24 hours).
-It picks the specified number of blocks (as specified by the stripe size),
-from the file, generates a parity block by combining them and
-stores the results as another HDFS file in the specified destination
-directory. There is a one-to-one mapping between a HDFS
-file and its parity file. The RaidNode also periodically finds parity files
-that are orphaned and deletes them.
-
-The Distributed Raid FileSystem is layered over a DistributedFileSystem
-instance intercepts all calls that go into HDFS. HDFS throws a ChecksumException
-or a BlocMissingException when a file read encounters bad data. The layered
-Distributed Raid FileSystem catches these exceptions, locates the corresponding
-parity file, extract the original data from the parity files and feeds the
-extracted data back to the application in a completely transparent way.
-
-The layered Distributed Raid FileSystem does not fix the data-loss that it
-encounters while serving data. It merely make the application transparently
-use the parity blocks to re-create the original data. A command line tool
-"fsckraid" is currently under development that will fix the corrupted files
-by extracting the data from the associated parity files. An adminstrator
-can run "fsckraid" manually as and when needed.
diff --git a/hadoop-mapreduce-project/src/contrib/raid/build.xml b/hadoop-mapreduce-project/src/contrib/raid/build.xml
deleted file mode 100644
index 80a2ad63abe..00000000000
--- a/hadoop-mapreduce-project/src/contrib/raid/build.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Tests failed!
-
-
-
-
diff --git a/hadoop-mapreduce-project/src/contrib/raid/ivy.xml b/hadoop-mapreduce-project/src/contrib/raid/ivy.xml
deleted file mode 100644
index 55ea7aa1a2e..00000000000
--- a/hadoop-mapreduce-project/src/contrib/raid/ivy.xml
+++ /dev/null
@@ -1,145 +0,0 @@
-
-
-
-
-
- Rumen
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/hadoop-mapreduce-project/src/contrib/raid/ivy/libraries.properties b/hadoop-mapreduce-project/src/contrib/raid/ivy/libraries.properties
deleted file mode 100644
index a9f5ebb283e..00000000000
--- a/hadoop-mapreduce-project/src/contrib/raid/ivy/libraries.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-# 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.
-
-#This properties file lists the versions of the various artifacts used by hadoop.
-#It drives ivy and the generation of a maven POM
-#These are the versions of our dependencies (in alphabetical order)
diff --git a/hadoop-project/pom.xml b/hadoop-project/pom.xml
index 99083001893..017437e2747 100644
--- a/hadoop-project/pom.xml
+++ b/hadoop-project/pom.xml
@@ -257,11 +257,6 @@
hadoop-client${project.version}
-
- org.apache.hadoop
- hadoop-hdfs-raid
- ${project.version}
- org.apache.hadoop