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

网格计算

开发平台:

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.server.namenode;
  19. import junit.framework.TestCase;
  20. import java.io.*;
  21. import java.util.Collection;
  22. import java.util.List;
  23. import java.util.Iterator;
  24. import java.util.Random;
  25. import org.apache.hadoop.conf.Configuration;
  26. import org.apache.hadoop.hdfs.DistributedFileSystem;
  27. import org.apache.hadoop.hdfs.MiniDFSCluster;
  28. import org.apache.hadoop.hdfs.protocol.FSConstants.SafeModeAction;
  29. import org.apache.hadoop.hdfs.server.common.Storage;
  30. import org.apache.hadoop.hdfs.server.namenode.FSImage.NameNodeFile;
  31. import org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode.ErrorSimulator;
  32. import org.apache.hadoop.hdfs.server.common.HdfsConstants.StartupOption;
  33. import org.apache.hadoop.hdfs.server.common.Storage.StorageDirectory;
  34. import org.apache.hadoop.hdfs.server.namenode.FSImage.NameNodeDirType;
  35. import org.apache.hadoop.hdfs.tools.DFSAdmin;
  36. import org.apache.hadoop.fs.FSDataOutputStream;
  37. import org.apache.hadoop.fs.FileSystem;
  38. import org.apache.hadoop.fs.FileUtil;
  39. import org.apache.hadoop.fs.Path;
  40. /**
  41.  * This class tests the creation and validation of a checkpoint.
  42.  */
  43. public class TestCheckpoint extends TestCase {
  44.   static final long seed = 0xDEADBEEFL;
  45.   static final int blockSize = 4096;
  46.   static final int fileSize = 8192;
  47.   static final int numDatanodes = 3;
  48.   short replication = 3;
  49.   private void writeFile(FileSystem fileSys, Path name, int repl)
  50.     throws IOException {
  51.     FSDataOutputStream stm = fileSys.create(name, true,
  52.                                             fileSys.getConf().getInt("io.file.buffer.size", 4096),
  53.                                             (short)repl, (long)blockSize);
  54.     byte[] buffer = new byte[fileSize];
  55.     Random rand = new Random(seed);
  56.     rand.nextBytes(buffer);
  57.     stm.write(buffer);
  58.     stm.close();
  59.   }
  60.   
  61.   
  62.   private void checkFile(FileSystem fileSys, Path name, int repl)
  63.     throws IOException {
  64.     assertTrue(fileSys.exists(name));
  65.     int replication = fileSys.getFileStatus(name).getReplication();
  66.     assertEquals("replication for " + name, repl, replication);
  67.     //We should probably test for more of the file properties.    
  68.   }
  69.   
  70.   private void cleanupFile(FileSystem fileSys, Path name)
  71.     throws IOException {
  72.     assertTrue(fileSys.exists(name));
  73.     fileSys.delete(name, true);
  74.     assertTrue(!fileSys.exists(name));
  75.   }
  76.   /**
  77.    * put back the old namedir
  78.    */
  79.   private void resurrectNameDir(File namedir) 
  80.     throws IOException {
  81.     String parentdir = namedir.getParent();
  82.     String name = namedir.getName();
  83.     File oldname =  new File(parentdir, name + ".old");
  84.     if (!oldname.renameTo(namedir)) {
  85.       assertTrue(false);
  86.     }
  87.   }
  88.   /**
  89.    * remove one namedir
  90.    */
  91.   private void removeOneNameDir(File namedir) 
  92.     throws IOException {
  93.     String parentdir = namedir.getParent();
  94.     String name = namedir.getName();
  95.     File newname =  new File(parentdir, name + ".old");
  96.     if (!namedir.renameTo(newname)) {
  97.       assertTrue(false);
  98.     }
  99.   }
  100.   /*
  101.    * Verify that namenode does not startup if one namedir is bad.
  102.    */
  103.   private void testNamedirError(Configuration conf, Collection<File> namedirs) 
  104.     throws IOException {
  105.     System.out.println("Starting testNamedirError");
  106.     MiniDFSCluster cluster = null;
  107.     if (namedirs.size() <= 1) {
  108.       return;
  109.     }
  110.     
  111.     //
  112.     // Remove one namedir & Restart cluster. This should fail.
  113.     //
  114.     File first = namedirs.iterator().next();
  115.     removeOneNameDir(first);
  116.     try {
  117.       cluster = new MiniDFSCluster(conf, 0, false, null);
  118.       cluster.shutdown();
  119.       assertTrue(false);
  120.     } catch (Throwable t) {
  121.       // no nothing
  122.     }
  123.     resurrectNameDir(first); // put back namedir
  124.   }
  125.   /*
  126.    * Simulate namenode crashing after rolling edit log.
  127.    */
  128.   private void testSecondaryNamenodeError1(Configuration conf)
  129.     throws IOException {
  130.     System.out.println("Starting testSecondaryNamenodeError 1");
  131.     Path file1 = new Path("checkpointxx.dat");
  132.     MiniDFSCluster cluster = new MiniDFSCluster(conf, numDatanodes, 
  133.                                                 false, null);
  134.     cluster.waitActive();
  135.     FileSystem fileSys = cluster.getFileSystem();
  136.     try {
  137.       assertTrue(!fileSys.exists(file1));
  138.       //
  139.       // Make the checkpoint fail after rolling the edits log.
  140.       //
  141.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  142.       ErrorSimulator.setErrorSimulation(0);
  143.       try {
  144.         secondary.doCheckpoint();  // this should fail
  145.         assertTrue(false);
  146.       } catch (IOException e) {
  147.       }
  148.       ErrorSimulator.clearErrorSimulation(0);
  149.       secondary.shutdown();
  150.       //
  151.       // Create a new file
  152.       //
  153.       writeFile(fileSys, file1, replication);
  154.       checkFile(fileSys, file1, replication);
  155.     } finally {
  156.       fileSys.close();
  157.       cluster.shutdown();
  158.     }
  159.     //
  160.     // Restart cluster and verify that file exists.
  161.     // Then take another checkpoint to verify that the 
  162.     // namenode restart accounted for the rolled edit logs.
  163.     //
  164.     System.out.println("Starting testSecondaryNamenodeError 2");
  165.     cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  166.     cluster.waitActive();
  167.     // Also check that the edits file is empty here
  168.     // and that temporary checkpoint files are gone.
  169.     FSImage image = cluster.getNameNode().getFSImage();
  170.     for (Iterator<StorageDirectory> it = 
  171.              image.dirIterator(NameNodeDirType.IMAGE); it.hasNext();) {
  172.       StorageDirectory sd = it.next();
  173.       assertFalse(FSImage.getImageFile(sd, NameNodeFile.IMAGE_NEW).exists());
  174.     }
  175.     for (Iterator<StorageDirectory> it = 
  176.             image.dirIterator(NameNodeDirType.EDITS); it.hasNext();) {
  177.       StorageDirectory sd = it.next();
  178.       assertFalse(image.getEditNewFile(sd).exists());
  179.       File edits = image.getEditFile(sd);
  180.       assertTrue(edits.exists()); // edits should exist and be empty
  181.       long editsLen = edits.length();
  182.       assertTrue(editsLen == Integer.SIZE/Byte.SIZE);
  183.     }
  184.     
  185.     fileSys = cluster.getFileSystem();
  186.     try {
  187.       checkFile(fileSys, file1, replication);
  188.       cleanupFile(fileSys, file1);
  189.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  190.       secondary.doCheckpoint();
  191.       secondary.shutdown();
  192.     } finally {
  193.       fileSys.close();
  194.       cluster.shutdown();
  195.     }
  196.   }
  197.   /*
  198.    * Simulate a namenode crash after uploading new image
  199.    */
  200.   private void testSecondaryNamenodeError2(Configuration conf)
  201.     throws IOException {
  202.     System.out.println("Starting testSecondaryNamenodeError 21");
  203.     Path file1 = new Path("checkpointyy.dat");
  204.     MiniDFSCluster cluster = new MiniDFSCluster(conf, numDatanodes, 
  205.                                                 false, null);
  206.     cluster.waitActive();
  207.     FileSystem fileSys = cluster.getFileSystem();
  208.     try {
  209.       assertTrue(!fileSys.exists(file1));
  210.       //
  211.       // Make the checkpoint fail after uploading the new fsimage.
  212.       //
  213.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  214.       ErrorSimulator.setErrorSimulation(1);
  215.       try {
  216.         secondary.doCheckpoint();  // this should fail
  217.         assertTrue(false);
  218.       } catch (IOException e) {
  219.       }
  220.       ErrorSimulator.clearErrorSimulation(1);
  221.       secondary.shutdown();
  222.       //
  223.       // Create a new file
  224.       //
  225.       writeFile(fileSys, file1, replication);
  226.       checkFile(fileSys, file1, replication);
  227.     } finally {
  228.       fileSys.close();
  229.       cluster.shutdown();
  230.     }
  231.     //
  232.     // Restart cluster and verify that file exists.
  233.     // Then take another checkpoint to verify that the 
  234.     // namenode restart accounted for the rolled edit logs.
  235.     //
  236.     System.out.println("Starting testSecondaryNamenodeError 22");
  237.     cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  238.     cluster.waitActive();
  239.     fileSys = cluster.getFileSystem();
  240.     try {
  241.       checkFile(fileSys, file1, replication);
  242.       cleanupFile(fileSys, file1);
  243.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  244.       secondary.doCheckpoint();
  245.       secondary.shutdown();
  246.     } finally {
  247.       fileSys.close();
  248.       cluster.shutdown();
  249.     }
  250.   }
  251.   /*
  252.    * Simulate a secondary namenode crash after rolling the edit log.
  253.    */
  254.   private void testSecondaryNamenodeError3(Configuration conf)
  255.     throws IOException {
  256.     System.out.println("Starting testSecondaryNamenodeError 31");
  257.     Path file1 = new Path("checkpointzz.dat");
  258.     MiniDFSCluster cluster = new MiniDFSCluster(conf, numDatanodes, 
  259.                                                 false, null);
  260.     cluster.waitActive();
  261.     FileSystem fileSys = cluster.getFileSystem();
  262.     try {
  263.       assertTrue(!fileSys.exists(file1));
  264.       //
  265.       // Make the checkpoint fail after rolling the edit log.
  266.       //
  267.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  268.       ErrorSimulator.setErrorSimulation(0);
  269.       try {
  270.         secondary.doCheckpoint();  // this should fail
  271.         assertTrue(false);
  272.       } catch (IOException e) {
  273.       }
  274.       ErrorSimulator.clearErrorSimulation(0);
  275.       secondary.shutdown(); // secondary namenode crash!
  276.       // start new instance of secondary and verify that 
  277.       // a new rollEditLog suceedes inspite of the fact that 
  278.       // edits.new already exists.
  279.       //
  280.       secondary = startSecondaryNameNode(conf);
  281.       secondary.doCheckpoint();  // this should work correctly
  282.       secondary.shutdown();
  283.       //
  284.       // Create a new file
  285.       //
  286.       writeFile(fileSys, file1, replication);
  287.       checkFile(fileSys, file1, replication);
  288.     } finally {
  289.       fileSys.close();
  290.       cluster.shutdown();
  291.     }
  292.     //
  293.     // Restart cluster and verify that file exists.
  294.     // Then take another checkpoint to verify that the 
  295.     // namenode restart accounted for the twice-rolled edit logs.
  296.     //
  297.     System.out.println("Starting testSecondaryNamenodeError 32");
  298.     cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  299.     cluster.waitActive();
  300.     fileSys = cluster.getFileSystem();
  301.     try {
  302.       checkFile(fileSys, file1, replication);
  303.       cleanupFile(fileSys, file1);
  304.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  305.       secondary.doCheckpoint();
  306.       secondary.shutdown();
  307.     } finally {
  308.       fileSys.close();
  309.       cluster.shutdown();
  310.     }
  311.   }
  312.   /**
  313.    * Simulate a secondary node failure to transfer image
  314.    * back to the name-node.
  315.    * Used to truncate primary fsimage file.
  316.    */
  317.   void testSecondaryFailsToReturnImage(Configuration conf)
  318.     throws IOException {
  319.     System.out.println("Starting testSecondaryFailsToReturnImage");
  320.     Path file1 = new Path("checkpointRI.dat");
  321.     MiniDFSCluster cluster = new MiniDFSCluster(conf, numDatanodes, 
  322.                                                 false, null);
  323.     cluster.waitActive();
  324.     FileSystem fileSys = cluster.getFileSystem();
  325.     FSImage image = cluster.getNameNode().getFSImage();
  326.     try {
  327.       assertTrue(!fileSys.exists(file1));
  328.       StorageDirectory sd = null;
  329.       for (Iterator<StorageDirectory> it = 
  330.                 image.dirIterator(NameNodeDirType.IMAGE); it.hasNext();)
  331.          sd = it.next();
  332.       assertTrue(sd != null);
  333.       long fsimageLength = FSImage.getImageFile(sd, NameNodeFile.IMAGE).length();
  334.       //
  335.       // Make the checkpoint
  336.       //
  337.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  338.       ErrorSimulator.setErrorSimulation(2);
  339.       try {
  340.         secondary.doCheckpoint();  // this should fail
  341.         assertTrue(false);
  342.       } catch (IOException e) {
  343.         System.out.println("testSecondaryFailsToReturnImage: doCheckpoint() " +
  344.             "failed predictably - " + e);
  345.       }
  346.       ErrorSimulator.clearErrorSimulation(2);
  347.       // Verify that image file sizes did not change.
  348.       for (Iterator<StorageDirectory> it = 
  349.               image.dirIterator(NameNodeDirType.IMAGE); it.hasNext();) {
  350.         assertTrue(FSImage.getImageFile(it.next(), 
  351.                                 NameNodeFile.IMAGE).length() == fsimageLength);
  352.       }
  353.       secondary.shutdown();
  354.     } finally {
  355.       fileSys.close();
  356.       cluster.shutdown();
  357.     }
  358.   }
  359.   /**
  360.    * Test different startup scenarios.
  361.    * <p><ol>
  362.    * <li> Start of primary name-node in secondary directory must succeed. 
  363.    * <li> Start of secondary node when the primary is already running in 
  364.    *      this directory must fail.
  365.    * <li> Start of primary name-node if secondary node is already running in 
  366.    *      this directory must fail.
  367.    * <li> Start of two secondary nodes in the same directory must fail.
  368.    * <li> Import of a checkpoint must fail if primary 
  369.    * directory contains a valid image.
  370.    * <li> Import of the secondary image directory must succeed if primary 
  371.    * directory does not exist.
  372.    * <li> Recover failed checkpoint for secondary node.
  373.    * <li> Complete failed checkpoint for secondary node.
  374.    * </ol>
  375.    */
  376.   void testStartup(Configuration conf) throws IOException {
  377.     System.out.println("Startup of the name-node in the checkpoint directory.");
  378.     String primaryDirs = conf.get("dfs.name.dir");
  379.     String primaryEditsDirs = conf.get("dfs.name.edits.dir");
  380.     String checkpointDirs = conf.get("fs.checkpoint.dir");
  381.     String checkpointEditsDirs = conf.get("fs.checkpoint.edits.dir");
  382.     NameNode nn = startNameNode(conf, checkpointDirs, checkpointEditsDirs,
  383.                                  StartupOption.REGULAR);
  384.     // Starting secondary node in the same directory as the primary
  385.     System.out.println("Startup of secondary in the same dir as the primary.");
  386.     SecondaryNameNode secondary = null;
  387.     try {
  388.       secondary = startSecondaryNameNode(conf);
  389.       assertFalse(secondary.getFSImage().isLockSupported(0));
  390.       secondary.shutdown();
  391.     } catch (IOException e) { // expected to fail
  392.       assertTrue(secondary == null);
  393.     }
  394.     nn.stop(); nn = null;
  395.     // Starting primary node in the same directory as the secondary
  396.     System.out.println("Startup of primary in the same dir as the secondary.");
  397.     // secondary won't start without primary
  398.     nn = startNameNode(conf, primaryDirs, primaryEditsDirs,
  399.                         StartupOption.REGULAR);
  400.     boolean succeed = false;
  401.     do {
  402.       try {
  403.         secondary = startSecondaryNameNode(conf);
  404.         succeed = true;
  405.       } catch(IOException ie) { // keep trying
  406.         System.out.println("Try again: " + ie.getLocalizedMessage());
  407.       }
  408.     } while(!succeed);
  409.     nn.stop(); nn = null;
  410.     try {
  411.       nn = startNameNode(conf, checkpointDirs, checkpointEditsDirs,
  412.                           StartupOption.REGULAR);
  413.       assertFalse(nn.getFSImage().isLockSupported(0));
  414.       nn.stop(); nn = null;
  415.     } catch (IOException e) { // expected to fail
  416.       assertTrue(nn == null);
  417.     }
  418.     // Try another secondary in the same directory
  419.     System.out.println("Startup of two secondaries in the same dir.");
  420.     // secondary won't start without primary
  421.     nn = startNameNode(conf, primaryDirs, primaryEditsDirs,
  422.                         StartupOption.REGULAR);
  423.     SecondaryNameNode secondary2 = null;
  424.     try {
  425.       secondary2 = startSecondaryNameNode(conf);
  426.       assertFalse(secondary2.getFSImage().isLockSupported(0));
  427.       secondary2.shutdown();
  428.     } catch (IOException e) { // expected to fail
  429.       assertTrue(secondary2 == null);
  430.     }
  431.     nn.stop(); nn = null;
  432.     secondary.shutdown();
  433.     // Import a checkpoint with existing primary image.
  434.     System.out.println("Import a checkpoint with existing primary image.");
  435.     try {
  436.       nn = startNameNode(conf, primaryDirs, primaryEditsDirs,
  437.                           StartupOption.IMPORT);
  438.       assertTrue(false);
  439.     } catch (IOException e) { // expected to fail
  440.       assertTrue(nn == null);
  441.     }
  442.     
  443.     // Remove current image and import a checkpoint.
  444.     System.out.println("Import a checkpoint with existing primary image.");
  445.     List<File> nameDirs = (List<File>)FSNamesystem.getNamespaceDirs(conf);
  446.     List<File> nameEditsDirs = (List<File>)FSNamesystem.
  447.                                   getNamespaceEditsDirs(conf);
  448.     long fsimageLength = new File(new File(nameDirs.get(0), "current"), 
  449.                                         NameNodeFile.IMAGE.getName()).length();
  450.     for(File dir : nameDirs) {
  451.       if(dir.exists())
  452.         if(!(FileUtil.fullyDelete(dir)))
  453.           throw new IOException("Cannot remove directory: " + dir);
  454.       if (!dir.mkdirs())
  455.         throw new IOException("Cannot create directory " + dir);
  456.     }
  457.     for(File dir : nameEditsDirs) {
  458.       if(dir.exists())
  459.         if(!(FileUtil.fullyDelete(dir)))
  460.           throw new IOException("Cannot remove directory: " + dir);
  461.       if (!dir.mkdirs())
  462.         throw new IOException("Cannot create directory " + dir);
  463.     }
  464.     
  465.     nn = startNameNode(conf, primaryDirs, primaryEditsDirs,
  466.                         StartupOption.IMPORT);
  467.     // Verify that image file sizes did not change.
  468.     FSImage image = nn.getFSImage();
  469.     for (Iterator<StorageDirectory> it = 
  470.             image.dirIterator(NameNodeDirType.IMAGE); it.hasNext();) {
  471.       assertTrue(FSImage.getImageFile(it.next(), 
  472.                           NameNodeFile.IMAGE).length() == fsimageLength);
  473.     }
  474.     nn.stop();
  475.     // recover failed checkpoint
  476.     nn = startNameNode(conf, primaryDirs, primaryEditsDirs,
  477.                         StartupOption.REGULAR);
  478.     Collection<File> secondaryDirs = FSImage.getCheckpointDirs(conf, null);
  479.     for(File dir : secondaryDirs) {
  480.       Storage.rename(new File(dir, "current"), 
  481.                      new File(dir, "lastcheckpoint.tmp"));
  482.     }
  483.     secondary = startSecondaryNameNode(conf);
  484.     secondary.shutdown();
  485.     for(File dir : secondaryDirs) {
  486.       assertTrue(new File(dir, "current").exists()); 
  487.       assertFalse(new File(dir, "lastcheckpoint.tmp").exists());
  488.     }
  489.     
  490.     // complete failed checkpoint
  491.     for(File dir : secondaryDirs) {
  492.       Storage.rename(new File(dir, "previous.checkpoint"), 
  493.                      new File(dir, "lastcheckpoint.tmp"));
  494.     }
  495.     secondary = startSecondaryNameNode(conf);
  496.     secondary.shutdown();
  497.     for(File dir : secondaryDirs) {
  498.       assertTrue(new File(dir, "current").exists()); 
  499.       assertTrue(new File(dir, "previous.checkpoint").exists()); 
  500.       assertFalse(new File(dir, "lastcheckpoint.tmp").exists());
  501.     }
  502.     nn.stop(); nn = null;
  503.     
  504.     // Check that everything starts ok now.
  505.     MiniDFSCluster cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  506.     cluster.waitActive();
  507.     cluster.shutdown();
  508.   }
  509.   NameNode startNameNode( Configuration conf,
  510.                           String imageDirs,
  511.                           String editsDirs,
  512.                           StartupOption start) throws IOException {
  513.     conf.set("fs.default.name", "hdfs://localhost:0");
  514.     conf.set("dfs.http.address", "0.0.0.0:0");  
  515.     conf.set("dfs.name.dir", imageDirs);
  516.     conf.set("dfs.name.edits.dir", editsDirs);
  517.     String[] args = new String[]{start.getName()};
  518.     NameNode nn = NameNode.createNameNode(args, conf);
  519.     assertTrue(nn.isInSafeMode());
  520.     return nn;
  521.   }
  522.   SecondaryNameNode startSecondaryNameNode(Configuration conf
  523.                                           ) throws IOException {
  524.     conf.set("dfs.secondary.http.address", "0.0.0.0:0");
  525.     return new SecondaryNameNode(conf);
  526.   }
  527.   /**
  528.    * Tests checkpoint in HDFS.
  529.    */
  530.   public void testCheckpoint() throws IOException {
  531.     Path file1 = new Path("checkpoint.dat");
  532.     Path file2 = new Path("checkpoint2.dat");
  533.     Collection<File> namedirs = null;
  534.     Configuration conf = new Configuration();
  535.     conf.set("dfs.secondary.http.address", "0.0.0.0:0");
  536.     replication = (short)conf.getInt("dfs.replication", 3);  
  537.     MiniDFSCluster cluster = new MiniDFSCluster(conf, numDatanodes, true, null);
  538.     cluster.waitActive();
  539.     FileSystem fileSys = cluster.getFileSystem();
  540.     try {
  541.       //
  542.       // verify that 'format' really blew away all pre-existing files
  543.       //
  544.       assertTrue(!fileSys.exists(file1));
  545.       assertTrue(!fileSys.exists(file2));
  546.       namedirs = cluster.getNameDirs();
  547.       //
  548.       // Create file1
  549.       //
  550.       writeFile(fileSys, file1, replication);
  551.       checkFile(fileSys, file1, replication);
  552.       //
  553.       // Take a checkpoint
  554.       //
  555.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  556.       ErrorSimulator.initializeErrorSimulationEvent(3);
  557.       secondary.doCheckpoint();
  558.       secondary.shutdown();
  559.     } finally {
  560.       fileSys.close();
  561.       cluster.shutdown();
  562.     }
  563.     //
  564.     // Restart cluster and verify that file1 still exist.
  565.     //
  566.     cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  567.     cluster.waitActive();
  568.     fileSys = cluster.getFileSystem();
  569.     try {
  570.       // check that file1 still exists
  571.       checkFile(fileSys, file1, replication);
  572.       cleanupFile(fileSys, file1);
  573.       // create new file file2
  574.       writeFile(fileSys, file2, replication);
  575.       checkFile(fileSys, file2, replication);
  576.       //
  577.       // Take a checkpoint
  578.       //
  579.       SecondaryNameNode secondary = startSecondaryNameNode(conf);
  580.       secondary.doCheckpoint();
  581.       secondary.shutdown();
  582.     } finally {
  583.       fileSys.close();
  584.       cluster.shutdown();
  585.     }
  586.     //
  587.     // Restart cluster and verify that file2 exists and
  588.     // file1 does not exist.
  589.     //
  590.     cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  591.     cluster.waitActive();
  592.     fileSys = cluster.getFileSystem();
  593.     assertTrue(!fileSys.exists(file1));
  594.     try {
  595.       // verify that file2 exists
  596.       checkFile(fileSys, file2, replication);
  597.     } finally {
  598.       fileSys.close();
  599.       cluster.shutdown();
  600.     }
  601.     // file2 is left behind.
  602.     testSecondaryNamenodeError1(conf);
  603.     testSecondaryNamenodeError2(conf);
  604.     testSecondaryNamenodeError3(conf);
  605.     testNamedirError(conf, namedirs);
  606.     testSecondaryFailsToReturnImage(conf);
  607.     testStartup(conf);
  608.   }
  609.   /**
  610.    * Tests save namepsace.
  611.    */
  612.   public void testSaveNamespace() throws IOException {
  613.     MiniDFSCluster cluster = null;
  614.     DistributedFileSystem fs = null;
  615.     try {
  616.       Configuration conf = new Configuration();
  617.       cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  618.       cluster.waitActive();
  619.       fs = (DistributedFileSystem)(cluster.getFileSystem());
  620.       // Saving image without safe mode should fail
  621.       DFSAdmin admin = new DFSAdmin(conf);
  622.       String[] args = new String[]{"-saveNamespace"};
  623.       try {
  624.         admin.run(args);
  625.       } catch(IOException eIO) {
  626.         assertTrue(eIO.getLocalizedMessage().contains("Safe mode should be turned ON"));
  627.       } catch(Exception e) {
  628.         throw new IOException(e);
  629.       }
  630.       // create new file
  631.       Path file = new Path("namespace.dat");
  632.       writeFile(fs, file, replication);
  633.       checkFile(fs, file, replication);
  634.       // verify that the edits file is NOT empty
  635.       Collection<File> editsDirs = cluster.getNameEditsDirs();
  636.       for(File ed : editsDirs) {
  637.         assertTrue(new File(ed, "current/edits").length() > Integer.SIZE/Byte.SIZE);
  638.       }
  639.       // Saving image in safe mode should succeed
  640.       fs.setSafeMode(SafeModeAction.SAFEMODE_ENTER);
  641.       try {
  642.         admin.run(args);
  643.       } catch(Exception e) {
  644.         throw new IOException(e);
  645.       }
  646.       // verify that the edits file is empty
  647.       for(File ed : editsDirs) {
  648.         assertTrue(new File(ed, "current/edits").length() == Integer.SIZE/Byte.SIZE);
  649.       }
  650.       // restart cluster and verify file exists
  651.       cluster.shutdown();
  652.       cluster = null;
  653.       cluster = new MiniDFSCluster(conf, numDatanodes, false, null);
  654.       cluster.waitActive();
  655.       fs = (DistributedFileSystem)(cluster.getFileSystem());
  656.       checkFile(fs, file, replication);
  657.     } finally {
  658.       if(fs != null) fs.close();
  659.       if(cluster!= null) cluster.shutdown();
  660.     }
  661.   }
  662. }