/**
 * 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 java.io.File;
import java.io.IOException;
import java.util.EnumMap;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.StartupOption;
import org.apache.hadoop.hdfs.server.namenode.FSEditLogOpCodes;
import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil;
import org.apache.hadoop.hdfs.server.namenode.NNStorage;
import org.apache.hadoop.hdfs.util.Holder;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.test.GenericTestUtils;
import org.junit.Test;

/**
 * Unit test to make sure that Append properly logs the right
 * things to the edit log, such that files aren't lost or truncated
 * on restart.
 */
public class TestFileAppendRestart {
  private static final int BLOCK_SIZE = 4096;
  private static final String HADOOP_23_BROKEN_APPEND_TGZ =
      "image-with-buggy-append.tgz";
    
  private void writeAndAppend(FileSystem fs, Path p,
      int lengthForCreate, int lengthForAppend) throws IOException {
    // Creating a file with 4096 blockSize to write multiple blocks
    FSDataOutputStream stream = fs.create(
        p, true, BLOCK_SIZE, (short) 1, BLOCK_SIZE);
    try {
      AppendTestUtil.write(stream, 0, lengthForCreate);
      stream.close();
      
      stream = fs.append(p);
      AppendTestUtil.write(stream, lengthForCreate, lengthForAppend);
      stream.close();
    } finally {
      IOUtils.closeStream(stream);
    }
    
    int totalLength = lengthForCreate + lengthForAppend; 
    assertEquals(totalLength, fs.getFileStatus(p).getLen());
  }
    
  /**
   * Regression test for HDFS-2991. Creates and appends to files
   * where blocks start/end on block boundaries.
   */
  @Test
  public void testAppendRestart() throws Exception {
    final Configuration conf = new HdfsConfiguration();
    // Turn off persistent IPC, so that the DFSClient can survive NN restart
    conf.setInt(
        CommonConfigurationKeysPublic.IPC_CLIENT_CONNECTION_MAXIDLETIME_KEY,
        0);
    MiniDFSCluster cluster = null;

    FSDataOutputStream stream = null;
    try {
      cluster = new MiniDFSCluster.Builder(conf).numDataNodes(1).build();
      FileSystem fs = cluster.getFileSystem();
      File editLog =
        new File(FSImageTestUtil.getNameNodeCurrentDirs(cluster, 0).get(0),
            NNStorage.getInProgressEditsFileName(1));
      EnumMap<FSEditLogOpCodes, Holder<Integer>> counts;
      
      Path p1 = new Path("/block-boundaries");
      writeAndAppend(fs, p1, BLOCK_SIZE, BLOCK_SIZE);

      counts = FSImageTestUtil.countEditLogOpTypes(editLog);
      // OP_ADD to create file
      // OP_UPDATE_BLOCKS for first block
      // OP_CLOSE to close file
      // OP_ADD to reopen file
      // OP_UPDATE_BLOCKS for second block
      // OP_CLOSE to close file
      assertEquals(2, (int)counts.get(FSEditLogOpCodes.OP_ADD).held);
      assertEquals(2, (int)counts.get(FSEditLogOpCodes.OP_UPDATE_BLOCKS).held);
      assertEquals(2, (int)counts.get(FSEditLogOpCodes.OP_CLOSE).held);

      Path p2 = new Path("/not-block-boundaries");
      writeAndAppend(fs, p2, BLOCK_SIZE/2, BLOCK_SIZE);
      counts = FSImageTestUtil.countEditLogOpTypes(editLog);
      // OP_ADD to create file
      // OP_UPDATE_BLOCKS for first block
      // OP_CLOSE to close file
      // OP_ADD to re-establish the lease
      // OP_UPDATE_BLOCKS from the updatePipeline call (increments genstamp of last block)
      // OP_UPDATE_BLOCKS at the start of the second block
      // OP_CLOSE to close file
      // Total: 2 OP_ADDs, 3 OP_UPDATE_BLOCKS, and 2 OP_CLOSEs in addition
      //        to the ones above
      assertEquals(2+2, (int)counts.get(FSEditLogOpCodes.OP_ADD).held);
      assertEquals(2+3, (int)counts.get(FSEditLogOpCodes.OP_UPDATE_BLOCKS).held);
      assertEquals(2+2, (int)counts.get(FSEditLogOpCodes.OP_CLOSE).held);
      
      cluster.restartNameNode();
      
      AppendTestUtil.check(fs, p1, 2*BLOCK_SIZE);
      AppendTestUtil.check(fs, p2, 3*BLOCK_SIZE/2);
    } finally {
      IOUtils.closeStream(stream);
      if (cluster != null) { cluster.shutdown(); }
    }
  }

  /**
   * Earlier versions of HDFS had a bug (HDFS-2991) which caused
   * append(), when called exactly at a block boundary,
   * to not log an OP_ADD. This ensures that we can read from
   * such buggy versions correctly, by loading an image created
   * using a namesystem image created with 0.23.1-rc2 exhibiting
   * the issue.
   */
  @Test
  public void testLoadLogsFromBuggyEarlierVersions() throws IOException {
    final Configuration conf = new HdfsConfiguration();

    String tarFile = System.getProperty("test.cache.data", "build/test/cache")
      + "/" + HADOOP_23_BROKEN_APPEND_TGZ;
    String testDir = System.getProperty("test.build.data", "build/test/data");
    File dfsDir = new File(testDir, "image-with-buggy-append");
    if (dfsDir.exists() && !FileUtil.fullyDelete(dfsDir)) {
      throw new IOException("Could not delete dfs directory '" + dfsDir + "'");
    }
    FileUtil.unTar(new File(tarFile), new File(testDir));

    File nameDir = new File(dfsDir, "name");
    GenericTestUtils.assertExists(nameDir);

    conf.set(DFSConfigKeys.DFS_NAMENODE_NAME_DIR_KEY, nameDir.getAbsolutePath());

    MiniDFSCluster cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
      .format(false)
      .manageDataDfsDirs(false)
      .manageNameDfsDirs(false)
      .numDataNodes(0)
      .waitSafeMode(false)
      .startupOption(StartupOption.UPGRADE)
      .build();
    try {
      FileSystem fs = cluster.getFileSystem();
      Path testPath = new Path("/tmp/io_data/test_io_0");
      assertEquals(2*1024*1024, fs.getFileStatus(testPath).getLen());
    } finally {
      cluster.shutdown();
    }
  }

  /**
   * Test to append to the file, when one of datanode in the existing pipeline is down.
   * @throws Exception
   */
  @Test
  public void testAppendWithPipelineRecovery() throws Exception {
    Configuration conf = new Configuration();
    MiniDFSCluster cluster = null;
    try {
      cluster = new MiniDFSCluster.Builder(conf).manageDataDfsDirs(true)
          .manageNameDfsDirs(true).numDataNodes(4)
          .racks(new String[] { "/rack1", "/rack1", "/rack1", "/rack2" })
          .build();
      cluster.waitActive();

      DistributedFileSystem fs = cluster.getFileSystem();
      Path path = new Path("/test1");
      DFSTestUtil.createFile(fs, path, 1024, (short) 3, 1l);

      cluster.stopDataNode(3);
      DFSTestUtil.appendFile(fs, path, "hello");
    } finally {
      if (null != cluster) {
        cluster.shutdown();
      }
    }
  }
}
