TestCrcCorruption.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:9k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.hdfs;
  19. import java.io.*;
  20. import java.nio.channels.FileChannel;
  21. import java.nio.ByteBuffer;
  22. import java.util.Random;
  23. import junit.framework.*;
  24. import org.apache.hadoop.conf.Configuration;
  25. import org.apache.hadoop.fs.FileSystem;
  26. import org.apache.hadoop.fs.LocalFileSystem;
  27. import org.apache.hadoop.fs.ChecksumException;
  28. import org.apache.hadoop.fs.Path;
  29. /**
  30.  * A JUnit test for corrupted file handling.
  31.  * This test creates a bunch of files/directories with replication 
  32.  * factor of 2. Then verifies that a client can automatically 
  33.  * access the remaining valid replica inspite of the following 
  34.  * types of simulated errors:
  35.  *
  36.  *  1. Delete meta file on one replica
  37.  *  2. Truncates meta file on one replica
  38.  *  3. Corrupts the meta file header on one replica
  39.  *  4. Corrupts any random offset and portion of the meta file
  40.  *  5. Swaps two meta files, i.e the format of the meta files 
  41.  *     are valid but their CRCs do not match with their corresponding 
  42.  *     data blocks
  43.  * The above tests are run for varied values of io.bytes.per.checksum 
  44.  * and dfs.block.size. It tests for the case when the meta file is 
  45.  * multiple blocks.
  46.  *
  47.  * Another portion of the test is commented out till HADOOP-1557 
  48.  * is addressed:
  49.  *  1. Create file with 2 replica, corrupt the meta file of replica, 
  50.  *     decrease replication factor from 2 to 1. Validate that the 
  51.  *     remaining replica is the good one.
  52.  *  2. Create file with 2 replica, corrupt the meta file of one replica, 
  53.  *     increase replication factor of file to 3. verify that the new 
  54.  *     replica was created from the non-corrupted replica.
  55.  */
  56. public class TestCrcCorruption extends TestCase {
  57.   
  58.   public TestCrcCorruption(String testName) {
  59.     super(testName);
  60.   }
  61.   protected void setUp() throws Exception {
  62.   }
  63.   protected void tearDown() throws Exception {
  64.   }
  65.   
  66.   /** 
  67.    * check if DFS can handle corrupted CRC blocks
  68.    */
  69.   private void thistest(Configuration conf, DFSTestUtil util) throws Exception {
  70.     MiniDFSCluster cluster = null;
  71.     int numDataNodes = 2;
  72.     short replFactor = 2;
  73.     Random random = new Random();
  74.     try {
  75.       cluster = new MiniDFSCluster(conf, numDataNodes, true, null);
  76.       cluster.waitActive();
  77.       FileSystem fs = cluster.getFileSystem();
  78.       util.createFiles(fs, "/srcdat", replFactor);
  79.       util.waitReplication(fs, "/srcdat", (short)2);
  80.       // Now deliberately remove/truncate meta blocks from the first
  81.       // directory of the first datanode. The complete absense of a meta
  82.       // file disallows this Datanode to send data to another datanode.
  83.       // However, a client is alowed access to this block.
  84.       //
  85.       File data_dir = new File(System.getProperty("test.build.data"),
  86.                                "dfs/data/data1/current");
  87.       assertTrue("data directory does not exist", data_dir.exists());
  88.       File[] blocks = data_dir.listFiles();
  89.       assertTrue("Blocks do not exist in data-dir", (blocks != null) && (blocks.length > 0));
  90.       int num = 0;
  91.       for (int idx = 0; idx < blocks.length; idx++) {
  92.         if (blocks[idx].getName().startsWith("blk_") &&
  93.             blocks[idx].getName().endsWith(".meta")) {
  94.           num++;
  95.           if (num % 3 == 0) {
  96.             //
  97.             // remove .meta file
  98.             //
  99.             System.out.println("Deliberately removing file " + blocks[idx].getName());
  100.             assertTrue("Cannot remove file.", blocks[idx].delete());
  101.           } else if (num % 3 == 1) {
  102.             //
  103.             // shorten .meta file
  104.             //
  105.             RandomAccessFile file = new RandomAccessFile(blocks[idx], "rw");
  106.             FileChannel channel = file.getChannel();
  107.             int newsize = random.nextInt((int)channel.size()/2);
  108.             System.out.println("Deliberately truncating file " + 
  109.                                blocks[idx].getName() + 
  110.                                " to size " + newsize + " bytes.");
  111.             channel.truncate(newsize);
  112.             file.close();
  113.           } else {
  114.             //
  115.             // corrupt a few bytes of the metafile
  116.             //
  117.             RandomAccessFile file = new RandomAccessFile(blocks[idx], "rw");
  118.             FileChannel channel = file.getChannel();
  119.             long position = 0;
  120.             //
  121.             // The very first time, corrupt the meta header at offset 0
  122.             //
  123.             if (num != 2) {
  124.               position = (long)random.nextInt((int)channel.size());
  125.             }
  126.             int length = random.nextInt((int)(channel.size() - position + 1));
  127.             byte[] buffer = new byte[length];
  128.             random.nextBytes(buffer);
  129.             channel.write(ByteBuffer.wrap(buffer), position);
  130.             System.out.println("Deliberately corrupting file " + 
  131.                                blocks[idx].getName() + 
  132.                                " at offset " + position +
  133.                                " length " + length);
  134.             file.close();
  135.           }
  136.         }
  137.       }
  138.       //
  139.       // Now deliberately corrupt all meta blocks from the second
  140.       // directory of the first datanode
  141.       //
  142.       data_dir = new File(System.getProperty("test.build.data"),
  143.                                "dfs/data/data2/current");
  144.       assertTrue("data directory does not exist", data_dir.exists());
  145.       blocks = data_dir.listFiles();
  146.       assertTrue("Blocks do not exist in data-dir", (blocks != null) && (blocks.length > 0));
  147.       int count = 0;
  148.       File previous = null;
  149.       for (int idx = 0; idx < blocks.length; idx++) {
  150.         if (blocks[idx].getName().startsWith("blk_") &&
  151.             blocks[idx].getName().endsWith(".meta")) {
  152.           //
  153.           // Move the previous metafile into the current one.
  154.           //
  155.           count++;
  156.           if (count % 2 == 0) {
  157.             System.out.println("Deliberately insertimg bad crc into files " +
  158.                                 blocks[idx].getName() + " " + previous.getName());
  159.             assertTrue("Cannot remove file.", blocks[idx].delete());
  160.             assertTrue("Cannot corrupt meta file.", previous.renameTo(blocks[idx]));
  161.             assertTrue("Cannot recreate empty meta file.", previous.createNewFile());
  162.             previous = null;
  163.           } else {
  164.             previous = blocks[idx];
  165.           }
  166.         }
  167.       }
  168.       //
  169.       // Only one replica is possibly corrupted. The other replica should still
  170.       // be good. Verify.
  171.       //
  172.       assertTrue("Corrupted replicas not handled properly.",
  173.                  util.checkFiles(fs, "/srcdat"));
  174.       System.out.println("All File still have a valid replica");
  175.       //
  176.       // set replication factor back to 1. This causes only one replica of
  177.       // of each block to remain in HDFS. The check is to make sure that 
  178.       // the corrupted replica generated above is the one that gets deleted.
  179.       // This test is currently disabled until HADOOP-1557 is solved.
  180.       //
  181.       util.setReplication(fs, "/srcdat", (short)1);
  182.       //util.waitReplication(fs, "/srcdat", (short)1);
  183.       //System.out.println("All Files done with removing replicas");
  184.       //assertTrue("Excess replicas deleted. Corrupted replicas found.",
  185.       //           util.checkFiles(fs, "/srcdat"));
  186.       System.out.println("The excess-corrupted-replica test is disabled " +
  187.                          " pending HADOOP-1557");
  188.       util.cleanup(fs, "/srcdat");
  189.     } finally {
  190.       if (cluster != null) { cluster.shutdown(); }
  191.     }
  192.   }
  193.   public void testCrcCorruption() throws Exception {
  194.     //
  195.     // default parameters
  196.     //
  197.     System.out.println("TestCrcCorruption with default parameters");
  198.     Configuration conf1 = new Configuration();
  199.     conf1.setInt("dfs.blockreport.intervalMsec", 3 * 1000);
  200.     DFSTestUtil util1 = new DFSTestUtil("TestCrcCorruption", 40, 3, 8*1024);
  201.     thistest(conf1, util1);
  202.     //
  203.     // specific parameters
  204.     //
  205.     System.out.println("TestCrcCorruption with specific parameters");
  206.     Configuration conf2 = new Configuration();
  207.     conf2.setInt("io.bytes.per.checksum", 17);
  208.     conf2.setInt("dfs.block.size", 34);
  209.     DFSTestUtil util2 = new DFSTestUtil("TestCrcCorruption", 40, 3, 400);
  210.     thistest(conf2, util2);
  211.   }
  212. }