public synchronized boolean saveNamespace(long timeWindow, long txGap,
      FSNamesystem source) throws IOException {
    if (timeWindow > 0 || txGap > 0) {
      final FSImageStorageInspector inspector = storage.readAndInspectDirs(
          EnumSet.of(NameNodeFile.IMAGE, NameNodeFile.IMAGE_ROLLBACK),
          StartupOption.REGULAR);
      FSImageFile image = inspector.getLatestImages().get(0);
      File imageFile = image.getFile();

      final long checkpointTxId = image.getCheckpointTxId();
      final long checkpointAge = Time.now() - imageFile.lastModified();
      if (checkpointAge <= timeWindow * 1000 &&
          checkpointTxId >= this.getCorrectLastAppliedOrWrittenTxId() - txGap) {
        return false;
      }
    }
    saveNamespace(source, NameNodeFile.IMAGE, null);
    return true;
  }
@Test(timeout = 60000)
  public void testSupportBlockGroup() throws Exception {
    final short GROUP_SIZE = (short) (testECPolicy.getNumDataUnits() +
        testECPolicy.getNumParityUnits());
    final int BLOCK_SIZE = 8 * 1024 * 1024;
    Configuration conf = new HdfsConfiguration();
    conf.setLong(DFSConfigKeys.DFS_BLOCK_SIZE_KEY, BLOCK_SIZE);
    MiniDFSCluster cluster = null;
    try {
      cluster = new MiniDFSCluster.Builder(conf).numDataNodes(GROUP_SIZE)
          .build();
      cluster.waitActive();
      DistributedFileSystem fs = cluster.getFileSystem();
      DFSTestUtil.enableAllECPolicies(fs);
      Path parentDir = new Path("/ec-10-4");
      Path childDir = new Path(parentDir, "ec-3-2");
      ErasureCodingPolicy ec32Policy = SystemErasureCodingPolicies
          .getByID(SystemErasureCodingPolicies.RS_3_2_POLICY_ID);

      // Create directories and files
      fs.mkdirs(parentDir);
      fs.mkdirs(childDir);
      fs.setErasureCodingPolicy(parentDir, testECPolicy.getName());
      fs.setErasureCodingPolicy(childDir, ec32Policy.getName());
      Path file_10_4 = new Path(parentDir, "striped_file_10_4");
      Path file_3_2 = new Path(childDir, "striped_file_3_2");

      // Write content to files
      byte[] bytes = StripedFileTestUtil.generateBytes(BLOCK_SIZE);
      DFSTestUtil.writeFile(fs, file_10_4, new String(bytes));
      DFSTestUtil.writeFile(fs, file_3_2, new String(bytes));

      // Save namespace and restart NameNode
      fs.setSafeMode(SafeModeAction.ENTER);
      fs.saveNamespace();
      fs.setSafeMode(SafeModeAction.LEAVE);

      cluster.restartNameNodes();
      fs = cluster.getFileSystem();
      assertTrue(fs.exists(file_10_4));
      assertTrue(fs.exists(file_3_2));

      // check the information of file_10_4
      FSNamesystem fsn = cluster.getNamesystem();
      INodeFile inode = fsn.dir.getINode(file_10_4.toString()).asFile();
      assertTrue(inode.isStriped());
      assertEquals(testECPolicy.getId(), inode.getErasureCodingPolicyID());
      BlockInfo[] blks = inode.getBlocks();
      assertEquals(1, blks.length);
      assertTrue(blks[0].isStriped());
      assertEquals(testECPolicy.getId(),
          fs.getErasureCodingPolicy(file_10_4).getId());
      assertEquals(testECPolicy.getId(),
          ((BlockInfoStriped)blks[0]).getErasureCodingPolicy().getId());
      assertEquals(testECPolicy.getNumDataUnits(),
          ((BlockInfoStriped) blks[0]).getDataBlockNum());
      assertEquals(testECPolicy.getNumParityUnits(),
          ((BlockInfoStriped) blks[0]).getParityBlockNum());
      byte[] content = DFSTestUtil.readFileAsBytes(fs, file_10_4);
      assertArrayEquals(bytes, content);


      // check the information of file_3_2
      inode = fsn.dir.getINode(file_3_2.toString()).asFile();
      assertTrue(inode.isStriped());
      assertEquals(SystemErasureCodingPolicies.getByID(
          SystemErasureCodingPolicies.RS_3_2_POLICY_ID).getId(),
          inode.getErasureCodingPolicyID());
      blks = inode.getBlocks();
      assertEquals(1, blks.length);
      assertTrue(blks[0].isStriped());
      assertEquals(ec32Policy.getId(),
          fs.getErasureCodingPolicy(file_3_2).getId());
      assertEquals(ec32Policy.getNumDataUnits(),
          ((BlockInfoStriped) blks[0]).getDataBlockNum());
      assertEquals(ec32Policy.getNumParityUnits(),
          ((BlockInfoStriped) blks[0]).getParityBlockNum());
      content = DFSTestUtil.readFileAsBytes(fs, file_3_2);
      assertArrayEquals(bytes, content);

      // check the EC policy on parent Dir
      ErasureCodingPolicy ecPolicy =
          fsn.getErasureCodingPolicy(parentDir.toString());
      assertNotNull(ecPolicy);
      assertEquals(testECPolicy.getId(), ecPolicy.getId());

      // check the EC policy on child Dir
      ecPolicy = fsn.getErasureCodingPolicy(childDir.toString());
      assertNotNull(ecPolicy);
      assertEquals(ec32Policy.getId(), ecPolicy.getId());

      // check the EC policy on root directory
      ecPolicy = fsn.getErasureCodingPolicy("/");
      assertNull(ecPolicy);
    } finally {
      if (cluster != null) {
        cluster.shutdown();
      }
    }
  }