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

网格计算

开发平台:

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.File;
  20. import java.io.IOException;
  21. import junit.framework.TestCase;
  22. import org.apache.commons.logging.Log;
  23. import org.apache.commons.logging.LogFactory;
  24. import org.apache.hadoop.conf.Configuration;
  25. import org.apache.hadoop.hdfs.server.common.HdfsConstants.NodeType;
  26. import org.apache.hadoop.hdfs.server.common.HdfsConstants.StartupOption;
  27. import static org.apache.hadoop.hdfs.server.common.HdfsConstants.NodeType.NAME_NODE;
  28. import static org.apache.hadoop.hdfs.server.common.HdfsConstants.NodeType.DATA_NODE;
  29. /**
  30. * This test ensures the appropriate response (successful or failure) from
  31. * the system when the system is started under various storage state and
  32. * version conditions.
  33. */
  34. public class TestDFSStorageStateRecovery extends TestCase {
  35.  
  36.   private static final Log LOG = LogFactory.getLog(
  37.                                                    "org.apache.hadoop.hdfs.TestDFSStorageStateRecovery");
  38.   private Configuration conf = null;
  39.   private int testCounter = 0;
  40.   private MiniDFSCluster cluster = null;
  41.   
  42.   /**
  43.    * The test case table.  Each row represents a test case.  This table is
  44.    * taken from the table in Apendix A of the HDFS Upgrade Test Plan
  45.    * (TestPlan-HdfsUpgrade.html) attached to
  46.    * http://issues.apache.org/jira/browse/HADOOP-702
  47.    * The column meanings are:
  48.    *  0) current directory exists
  49.    *  1) previous directory exists
  50.    *  2) previous.tmp directory exists
  51.    *  3) removed.tmp directory exists
  52.    *  4) node should recover and startup
  53.    *  5) current directory should exist after recovery but before startup
  54.    *  6) previous directory should exist after recovery but before startup
  55.    */
  56.   static boolean[][] testCases = new boolean[][] {
  57.     new boolean[] {true,  false, false, false, true,  true,  false}, // 1
  58.     new boolean[] {true,  true,  false, false, true,  true,  true }, // 2
  59.     new boolean[] {true,  false, true,  false, true,  true,  true }, // 3
  60.     new boolean[] {true,  true,  true,  true,  false, false, false }, // 4
  61.     new boolean[] {true,  true,  true,  false, false, false, false }, // 4
  62.     new boolean[] {false, true,  true,  true,  false, false, false }, // 4
  63.     new boolean[] {false, true,  true,  false, false, false, false }, // 4
  64.     new boolean[] {false, false, false, false, false, false, false }, // 5
  65.     new boolean[] {false, true,  false, false, false, false, false }, // 6
  66.     new boolean[] {false, false, true,  false, true,  true,  false}, // 7
  67.     new boolean[] {true,  false, false, true,  true,  true,  false}, // 8
  68.     new boolean[] {true,  true,  false, true,  false, false, false }, // 9
  69.     new boolean[] {true,  true,  true,  true,  false, false, false }, // 10
  70.     new boolean[] {true,  false, true,  true,  false, false, false }, // 10
  71.     new boolean[] {false, true,  true,  true,  false, false, false }, // 10
  72.     new boolean[] {false, false, true,  true,  false, false, false }, // 10
  73.     new boolean[] {false, false, false, true,  false, false, false }, // 11
  74.     new boolean[] {false, true,  false, true,  true,  true,  true }, // 12
  75.   };
  76.   
  77.   /**
  78.    * Writes an INFO log message containing the parameters. Only
  79.    * the first 4 elements of the state array are included in the message.
  80.    */
  81.   void log(String label, int numDirs, int testCaseNum, boolean[] state) {
  82.     LOG.info("============================================================");
  83.     LOG.info("***TEST " + (testCounter++) + "*** " 
  84.              + label + ":"
  85.              + " numDirs="+numDirs
  86.              + " testCase="+testCaseNum
  87.              + " current="+state[0]
  88.              + " previous="+state[1]
  89.              + " previous.tmp="+state[2]
  90.              + " removed.tmp="+state[3]);
  91.   }
  92.   
  93.   /**
  94.    * Sets up the storage directories for the given node type, either
  95.    * dfs.name.dir or dfs.data.dir. For each element in dfs.name.dir or
  96.    * dfs.data.dir, the subdirectories represented by the first four elements 
  97.    * of the <code>state</code> array will be created and populated.
  98.    * See UpgradeUtilities.createStorageDirs().
  99.    * 
  100.    * @param nodeType
  101.    *   the type of node that storage should be created for. Based on this
  102.    *   parameter either dfs.name.dir or dfs.data.dir is used from the global conf.
  103.    * @param state
  104.    *   a row from the testCases table which indicates which directories
  105.    *   to setup for the node
  106.    * @return file paths representing either dfs.name.dir or dfs.data.dir
  107.    *   directories
  108.    */
  109.   String[] createStorageState(NodeType nodeType, boolean[] state) throws Exception {
  110.     String[] baseDirs = (nodeType == NAME_NODE ?
  111.                          conf.getStrings("dfs.name.dir") :
  112.                          conf.getStrings("dfs.data.dir"));
  113.     UpgradeUtilities.createEmptyDirs(baseDirs);
  114.     if (state[0])  // current
  115.       UpgradeUtilities.createStorageDirs(nodeType, baseDirs, "current");
  116.     if (state[1])  // previous
  117.       UpgradeUtilities.createStorageDirs(nodeType, baseDirs, "previous");
  118.     if (state[2])  // previous.tmp
  119.       UpgradeUtilities.createStorageDirs(nodeType, baseDirs, "previous.tmp");
  120.     if (state[3])  // removed.tmp
  121.       UpgradeUtilities.createStorageDirs(nodeType, baseDirs, "removed.tmp");
  122.     return baseDirs;
  123.   }
  124.  
  125.   /**
  126.    * Verify that the current and/or previous exist as indicated by 
  127.    * the method parameters.  If previous exists, verify that
  128.    * it hasn't been modified by comparing the checksum of all it's
  129.    * containing files with their original checksum.  It is assumed that
  130.    * the server has recovered.
  131.    */
  132.   void checkResult(NodeType nodeType, String[] baseDirs, 
  133.                    boolean currentShouldExist, boolean previousShouldExist) 
  134.     throws IOException
  135.   {
  136.     switch (nodeType) {
  137.     case NAME_NODE:
  138.       if (currentShouldExist) {
  139.         for (int i = 0; i < baseDirs.length; i++) {
  140.           assertTrue(new File(baseDirs[i],"current").isDirectory());
  141.           assertTrue(new File(baseDirs[i],"current/VERSION").isFile());
  142.           assertTrue(new File(baseDirs[i],"current/edits").isFile());
  143.           assertTrue(new File(baseDirs[i],"current/fsimage").isFile());
  144.           assertTrue(new File(baseDirs[i],"current/fstime").isFile());
  145.         }
  146.       }
  147.       break;
  148.     case DATA_NODE:
  149.       if (currentShouldExist) {
  150.         for (int i = 0; i < baseDirs.length; i++) {
  151.           assertEquals(
  152.                        UpgradeUtilities.checksumContents(
  153.                                                          nodeType, new File(baseDirs[i],"current")),
  154.                        UpgradeUtilities.checksumMasterContents(nodeType));
  155.         }
  156.       }
  157.       break;
  158.     }
  159.     if (previousShouldExist) {
  160.       for (int i = 0; i < baseDirs.length; i++) {
  161.         assertTrue(new File(baseDirs[i],"previous").isDirectory());
  162.         assertEquals(
  163.                      UpgradeUtilities.checksumContents(
  164.                                                        nodeType, new File(baseDirs[i],"previous")),
  165.                      UpgradeUtilities.checksumMasterContents(nodeType));
  166.       }
  167.     }
  168.   }
  169.  
  170.   /**
  171.    * This test iterates over the testCases table and attempts
  172.    * to startup the NameNode and DataNode normally.
  173.    */
  174.   public void testStorageStates() throws Exception {
  175.     String[] baseDirs;
  176.     UpgradeUtilities.initialize();
  177.     for (int numDirs = 1; numDirs <= 2; numDirs++) {
  178.       conf = new Configuration();
  179.       conf.setInt("dfs.datanode.scan.period.hours", -1);      
  180.       conf = UpgradeUtilities.initializeStorageStateConf(numDirs, conf);
  181.       for (int i = 0; i < testCases.length; i++) {
  182.         boolean[] testCase = testCases[i];
  183.         boolean shouldRecover = testCase[4];
  184.         boolean curAfterRecover = testCase[5];
  185.         boolean prevAfterRecover = testCase[6];
  186.         log("NAME_NODE recovery", numDirs, i, testCase);
  187.         baseDirs = createStorageState(NAME_NODE, testCase);
  188.         if (shouldRecover) {
  189.           cluster = new MiniDFSCluster(conf, 0, StartupOption.REGULAR);
  190.           checkResult(NAME_NODE, baseDirs, curAfterRecover, prevAfterRecover);
  191.           cluster.shutdown();
  192.         } else {
  193.           try {
  194.             cluster = new MiniDFSCluster(conf, 0, StartupOption.REGULAR);
  195.             throw new AssertionError("NameNode should have failed to start");
  196.           } catch (IOException expected) {
  197.             // the exception is expected
  198.             // check that the message says "not formatted" 
  199.             // when storage directory is empty (case #5)
  200.             if(!testCases[i][0] && !testCases[i][2] 
  201.                       && !testCases[i][1] && !testCases[i][3]) {
  202.               assertTrue(expected.getLocalizedMessage().contains(
  203.                   "NameNode is not formatted"));
  204.             }
  205.           }
  206.         }
  207.         
  208.         log("DATA_NODE recovery", numDirs, i, testCase);
  209.         createStorageState(NAME_NODE, new boolean[] {true, true, false, false});
  210.         cluster = new MiniDFSCluster(conf, 0, StartupOption.REGULAR);
  211.         baseDirs = createStorageState(DATA_NODE, testCase);
  212.         if (!testCase[0] && !testCase[1] && !testCase[2] && !testCase[3]) {
  213.           // DataNode will create and format current if no directories exist
  214.           cluster.startDataNodes(conf, 1, false, StartupOption.REGULAR, null);
  215.         } else {
  216.           if (shouldRecover) {
  217.             cluster.startDataNodes(conf, 1, false, StartupOption.REGULAR, null);
  218.             checkResult(DATA_NODE, baseDirs, curAfterRecover, prevAfterRecover);
  219.           } else {
  220.             try {
  221.               cluster.startDataNodes(conf, 1, false, StartupOption.REGULAR, null);
  222.               throw new AssertionError("DataNode should have failed to start");
  223.             } catch (Exception expected) {
  224.               // expected
  225.             }
  226.           }
  227.         }
  228.         cluster.shutdown();
  229.       } // end testCases loop
  230.     } // end numDirs loop
  231.   }
  232.  
  233.   protected void tearDown() throws Exception {
  234.     LOG.info("Shutting down MiniDFSCluster");
  235.     if (cluster != null) cluster.shutdown();
  236.   }
  237.   
  238.   public static void main(String[] args) throws Exception {
  239.     new TestDFSStorageStateRecovery().testStorageStates();
  240.   }
  241.   
  242. }