/**
 * 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.server.namenode;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hdfs.DFSTestUtil;
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.DistributedFileSystem;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.protocol.SnapshotException;
import org.apache.hadoop.hdfs.server.namenode.snapshot.Snapshot;
import org.apache.hadoop.hdfs.server.namenode.snapshot.SnapshotManager;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;

/** Test snapshot related operations. */
public class TestSnapshotPathINodes {
  private static final long seed = 0;
  private static final short REPLICATION = 3;

  static private final Path dir = new Path("/TestSnapshot");
  
  static private final Path sub1 = new Path(dir, "sub1");
  static private final Path file1 = new Path(sub1, "file1");
  static private final Path file2 = new Path(sub1, "file2");

  static private MiniDFSCluster cluster;
  static private FSDirectory fsdir;

  static private DistributedFileSystem hdfs;

  @BeforeClass
  public static void setUp() throws Exception {
    Configuration conf = new Configuration();
    cluster = new MiniDFSCluster.Builder(conf)
      .numDataNodes(REPLICATION)
      .build();
    cluster.waitActive();

    FSNamesystem fsn = cluster.getNamesystem();
    fsdir = fsn.getFSDirectory();
    
    hdfs = cluster.getFileSystem();
  }

  @Before
  public void reset() throws Exception {
    DFSTestUtil.createFile(hdfs, file1, 1024, REPLICATION, seed);
    DFSTestUtil.createFile(hdfs, file2, 1024, REPLICATION, seed);
  }

  @AfterClass
  public static void tearDown() throws Exception {
    if (cluster != null) {
      cluster.shutdown();
    }
  }

  /** Test allow-snapshot operation. */
  @Test (timeout=15000)
  public void testAllowSnapshot() throws Exception {
    final String pathStr = sub1.toString();
    final INode before = fsdir.getINode(pathStr);
    
    // Before a directory is snapshottable
    Assert.assertFalse(before.asDirectory().isSnapshottable());

    // After a directory is snapshottable
    final Path path = new Path(pathStr);
    hdfs.allowSnapshot(path);
    {
      final INode after = fsdir.getINode(pathStr);
      Assert.assertTrue(after.asDirectory().isSnapshottable());
    }
    
    hdfs.disallowSnapshot(path);
    {
      final INode after = fsdir.getINode(pathStr);
      Assert.assertFalse(after.asDirectory().isSnapshottable());
    }
  }
  
  static Snapshot getSnapshot(INodesInPath inodesInPath, String name,
      int index) {
    if (name == null) {
      return null;
    }
    final INode inode = inodesInPath.getINode(index - 1);
    return inode.asDirectory().getSnapshot(DFSUtil.string2Bytes(name));
  }

  static void assertSnapshot(INodesInPath inodesInPath, boolean isSnapshot,
      final Snapshot snapshot, int index) {
    assertEquals(isSnapshot, inodesInPath.isSnapshot());
    assertEquals(Snapshot.getSnapshotId(isSnapshot ? snapshot : null),
        inodesInPath.getPathSnapshotId());
    if (!isSnapshot) {
      assertEquals(Snapshot.getSnapshotId(snapshot),
          inodesInPath.getLatestSnapshotId());
    }
    if (isSnapshot && index >= 0) {
      assertEquals(Snapshot.Root.class, inodesInPath.getINode(index).getClass());
    }
  }

  static void assertINodeFile(INode inode, Path path) {
    assertEquals(path.getName(), inode.getLocalName());
    assertEquals(INodeFile.class, inode.getClass());
  }

  /** 
   * for normal (non-snapshot) file.
   */
  @Test (timeout=15000)
  public void testNonSnapshotPathINodes() throws Exception {
    // Get the inodes by resolving the path of a normal file
    byte[][] components = INode.getPathComponents(file1.toString());
    INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
        components, false);
    // The number of inodes should be equal to components.length
    assertEquals(nodesInPath.length(), components.length);
    // The returned nodesInPath should be non-snapshot
    assertSnapshot(nodesInPath, false, null, -1);

    // verify components are correct
    for (int i=0; i < components.length; i++) {
      assertEquals(components[i], nodesInPath.getPathComponent(i));
    }

    // The last INode should be associated with file1
    assertTrue("file1=" + file1 + ", nodesInPath=" + nodesInPath,
        nodesInPath.getINode(components.length - 1) != null);
    assertEquals(nodesInPath.getINode(components.length - 1).getFullPathName(),
        file1.toString());
    assertEquals(nodesInPath.getINode(components.length - 2).getFullPathName(),
        sub1.toString());
    assertEquals(nodesInPath.getINode(components.length - 3).getFullPathName(),
        dir.toString());

    assertEquals(Path.SEPARATOR, nodesInPath.getPath(0));
    assertEquals(dir.toString(), nodesInPath.getPath(1));
    assertEquals(sub1.toString(), nodesInPath.getPath(2));
    assertEquals(file1.toString(), nodesInPath.getPath(3));

    assertEquals(file1.getParent().toString(),
                 nodesInPath.getParentINodesInPath().getPath());

    nodesInPath = INodesInPath.resolve(fsdir.rootDir, components, false);
    assertEquals(nodesInPath.length(), components.length);
    assertSnapshot(nodesInPath, false, null, -1);
    assertEquals(nodesInPath.getLastINode().getFullPathName(), file1.toString());
  }
  
  /** 
   * for snapshot file.
   */
  @Test (timeout=15000)
  public void testSnapshotPathINodes() throws Exception {
    // Create a snapshot for the dir, and check the inodes for the path
    // pointing to a snapshot file
    hdfs.allowSnapshot(sub1);
    hdfs.createSnapshot(sub1, "s1");
    // The path when accessing the snapshot file of file1 is
    // /TestSnapshot/sub1/.snapshot/s1/file1
    String snapshotPath = sub1.toString() + "/.snapshot/s1/file1";
    byte[][] components = INode.getPathComponents(snapshotPath);
    INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
        components, false);
    // Length of inodes should be (components.length - 1), since we will ignore
    // ".snapshot" 
    assertEquals(nodesInPath.length(), components.length - 1);
    // SnapshotRootIndex should be 3: {root, Testsnapshot, sub1, s1, file1}
    final Snapshot snapshot = getSnapshot(nodesInPath, "s1", 3);
    assertSnapshot(nodesInPath, true, snapshot, 3);
    assertEquals(".snapshot/s1",
        DFSUtil.bytes2String(nodesInPath.getPathComponent(3)));
    assertTrue(nodesInPath.getINode(3) instanceof Snapshot.Root);
    assertEquals("s1", nodesInPath.getINode(3).getLocalName());

    // Check the INode for file1 (snapshot file)
    INode snapshotFileNode = nodesInPath.getLastINode();
    assertINodeFile(snapshotFileNode, file1);
    assertTrue(snapshotFileNode.getParent().isWithSnapshot());
    
    // Call getExistingPathINodes and request only one INode.
    nodesInPath = INodesInPath.resolve(fsdir.rootDir, components, false);
    assertEquals(nodesInPath.length(), components.length - 1);
    assertSnapshot(nodesInPath, true, snapshot, 3);
    // Check the INode for file1 (snapshot file)
    assertINodeFile(nodesInPath.getLastINode(), file1);

    // Resolve the path "/TestSnapshot/sub1/.snapshot"  
    String dotSnapshotPath = sub1.toString() + "/.snapshot";
    components = INode.getPathComponents(dotSnapshotPath);
    nodesInPath = INodesInPath.resolve(fsdir.rootDir, components, false);
    // The number of INodes returned should still be components.length
    // since we put a null in the inode array for ".snapshot"
    assertEquals(nodesInPath.length(), components.length);
    assertEquals(".snapshot",
        DFSUtil.bytes2String(nodesInPath.getLastLocalName()));
    assertNull(nodesInPath.getLastINode());
    // ensure parent inodes can strip the .snapshot
    assertEquals(sub1.toString(),
        nodesInPath.getParentINodesInPath().getPath());

    // No SnapshotRoot dir is included in the resolved inodes  
    assertSnapshot(nodesInPath, true, snapshot, -1);
    // The last INode should be null, the last but 1 should be sub1
    assertNull(nodesInPath.getLastINode());
    assertEquals(nodesInPath.getINode(-2).getFullPathName(), sub1.toString());
    assertTrue(nodesInPath.getINode(-2).isDirectory());
    
    String[] invalidPathComponent = {"invalidDir", "foo", ".snapshot", "bar"};
    Path invalidPath = new Path(invalidPathComponent[0]);
    for(int i = 1; i < invalidPathComponent.length; i++) {
      invalidPath = new Path(invalidPath, invalidPathComponent[i]);
      try {
        hdfs.getFileStatus(invalidPath);
        Assert.fail();
      } catch(FileNotFoundException fnfe) {
        System.out.println("The exception is expected: " + fnfe);
      }
    }
    hdfs.deleteSnapshot(sub1, "s1");
    hdfs.disallowSnapshot(sub1);
  }
  
  /** 
   * for snapshot file after deleting the original file.
   */
  @Test (timeout=15000)
  public void testSnapshotPathINodesAfterDeletion() throws Exception {
    // Create a snapshot for the dir, and check the inodes for the path
    // pointing to a snapshot file
    hdfs.allowSnapshot(sub1);
    hdfs.createSnapshot(sub1, "s2");
    
    // Delete the original file /TestSnapshot/sub1/file1
    hdfs.delete(file1, false);
    
    final Snapshot snapshot;
    {
      // Resolve the path for the snapshot file
      // /TestSnapshot/sub1/.snapshot/s2/file1
      String snapshotPath = sub1.toString() + "/.snapshot/s2/file1";
      byte[][] components = INode.getPathComponents(snapshotPath);
      INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
          components, false);
      // Length of inodes should be (components.length - 1), since we will ignore
      // ".snapshot" 
      assertEquals(nodesInPath.length(), components.length - 1);
      // SnapshotRootIndex should be 3: {root, Testsnapshot, sub1, s2, file1}
      snapshot = getSnapshot(nodesInPath, "s2", 3);
      assertSnapshot(nodesInPath, true, snapshot, 3);
  
      // Check the INode for file1 (snapshot file)
      final INode inode = nodesInPath.getLastINode();
      assertEquals(file1.getName(), inode.getLocalName());
      assertTrue(inode.asFile().isWithSnapshot());
    }

    // Check the INodes for path /TestSnapshot/sub1/file1
    byte[][] components = INode.getPathComponents(file1.toString());
    INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
        components, false);
    // The length of inodes should be equal to components.length
    assertEquals(nodesInPath.length(), components.length);
    // The number of non-null elements should be components.length - 1 since
    // file1 has been deleted
    assertEquals(getNumNonNull(nodesInPath), components.length - 1);
    // The returned nodesInPath should be non-snapshot
    assertSnapshot(nodesInPath, false, snapshot, -1);
    // The last INode should be null, and the one before should be associated
    // with sub1
    assertNull(nodesInPath.getINode(components.length - 1));
    assertEquals(nodesInPath.getINode(components.length - 2).getFullPathName(),
        sub1.toString());
    assertEquals(nodesInPath.getINode(components.length - 3).getFullPathName(),
        dir.toString());
    hdfs.deleteSnapshot(sub1, "s2");
    hdfs.disallowSnapshot(sub1);
  }

  private int getNumNonNull(INodesInPath iip) {
    for (int i = iip.length() - 1; i >= 0; i--) {
      if (iip.getINode(i) != null) {
        return i+1;
      }
    }
    return 0;
  }

  /**
   * for snapshot file while adding a new file after snapshot.
   */
  @Test (timeout=15000)
  public void testSnapshotPathINodesWithAddedFile() throws Exception {
    // Create a snapshot for the dir, and check the inodes for the path
    // pointing to a snapshot file
    hdfs.allowSnapshot(sub1);
    hdfs.createSnapshot(sub1, "s4");
    
    // Add a new file /TestSnapshot/sub1/file3
    final Path file3 = new Path(sub1, "file3");
    DFSTestUtil.createFile(hdfs, file3, 1024, REPLICATION, seed);

    Snapshot s4;
    {
      // Check the inodes for /TestSnapshot/sub1/.snapshot/s4/file3
      String snapshotPath = sub1.toString() + "/.snapshot/s4/file3";
      byte[][] components = INode.getPathComponents(snapshotPath);
      INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
          components, false);
      // Length of inodes should be (components.length - 1), since we will ignore
      // ".snapshot" 
      assertEquals(nodesInPath.length(), components.length - 1);
      // The number of non-null inodes should be components.length - 2, since
      // snapshot of file3 does not exist
      assertEquals(getNumNonNull(nodesInPath), components.length - 2);
      s4 = getSnapshot(nodesInPath, "s4", 3);

      // SnapshotRootIndex should still be 3: {root, Testsnapshot, sub1, s4, null}
      assertSnapshot(nodesInPath, true, s4, 3);
  
      // Check the last INode in inodes, which should be null
      assertNull(nodesInPath.getINode(nodesInPath.length() - 1));
    }

    // Check the inodes for /TestSnapshot/sub1/file3
    byte[][] components = INode.getPathComponents(file3.toString());
    INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
        components, false);
    // The number of inodes should be equal to components.length
    assertEquals(nodesInPath.length(), components.length);

    // The returned nodesInPath should be non-snapshot
    assertSnapshot(nodesInPath, false, s4, -1);

    // The last INode should be associated with file3
    assertEquals(nodesInPath.getINode(components.length - 1).getFullPathName(),
        file3.toString());
    assertEquals(nodesInPath.getINode(components.length - 2).getFullPathName(),
        sub1.toString());
    assertEquals(nodesInPath.getINode(components.length - 3).getFullPathName(),
        dir.toString());
    hdfs.deleteSnapshot(sub1, "s4");
    hdfs.disallowSnapshot(sub1);
  }
  
  /** 
   * for snapshot file while modifying file after snapshot.
   */
  @Test (timeout=15000)
  public void testSnapshotPathINodesAfterModification() throws Exception {
    // First check the INode for /TestSnapshot/sub1/file1
    byte[][] components = INode.getPathComponents(file1.toString());
    INodesInPath nodesInPath = INodesInPath.resolve(fsdir.rootDir,
        components, false);
    // The number of inodes should be equal to components.length
    assertEquals(nodesInPath.length(), components.length);

    // The last INode should be associated with file1
    assertEquals(nodesInPath.getINode(components.length - 1).getFullPathName(),
        file1.toString());
    // record the modification time of the inode
    final long modTime = nodesInPath.getINode(nodesInPath.length() - 1)
        .getModificationTime();
    
    // Create a snapshot for the dir, and check the inodes for the path
    // pointing to a snapshot file
    hdfs.allowSnapshot(sub1);
    hdfs.createSnapshot(sub1, "s3");
    
    // Modify file1
    DFSTestUtil.appendFile(hdfs, file1, "the content for appending");

    // Check the INodes for snapshot of file1
    String snapshotPath = sub1.toString() + "/.snapshot/s3/file1";
    components = INode.getPathComponents(snapshotPath);
    INodesInPath ssNodesInPath = INodesInPath.resolve(fsdir.rootDir,
        components, false);
    // Length of ssInodes should be (components.length - 1), since we will
    // ignore ".snapshot" 
    assertEquals(ssNodesInPath.length(), components.length - 1);
    final Snapshot s3 = getSnapshot(ssNodesInPath, "s3", 3);
    assertSnapshot(ssNodesInPath, true, s3, 3);
    // Check the INode for snapshot of file1
    INode snapshotFileNode = ssNodesInPath.getLastINode();
    assertEquals(snapshotFileNode.getLocalName(), file1.getName());
    assertTrue(snapshotFileNode.asFile().isWithSnapshot());
    // The modification time of the snapshot INode should be the same with the
    // original INode before modification
    assertEquals(modTime,
        snapshotFileNode.getModificationTime(ssNodesInPath.getPathSnapshotId()));

    // Check the INode for /TestSnapshot/sub1/file1 again
    components = INode.getPathComponents(file1.toString());
    INodesInPath newNodesInPath = INodesInPath.resolve(fsdir.rootDir,
        components, false);
    assertSnapshot(newNodesInPath, false, s3, -1);
    // The number of inodes should be equal to components.length
    assertEquals(newNodesInPath.length(), components.length);
    // The last INode should be associated with file1
    final int last = components.length - 1;
    assertEquals(newNodesInPath.getINode(last).getFullPathName(),
        file1.toString());
    // The modification time of the INode for file3 should have been changed
    Assert.assertFalse(modTime == newNodesInPath.getINode(last).getModificationTime());
    hdfs.deleteSnapshot(sub1, "s3");
    hdfs.disallowSnapshot(sub1);
  }

  @Test
  public void testShortCircuitSnapshotSearch() throws SnapshotException {
    FSNamesystem fsn = cluster.getNamesystem();
    SnapshotManager sm = fsn.getSnapshotManager();
    assertEquals(0, sm.getNumSnapshottableDirs());

    INodesInPath iip = Mockito.mock(INodesInPath.class);
    List<INodeDirectory> snapDirs = new ArrayList<>();
    FSDirSnapshotOp.checkSnapshot(fsn.getFSDirectory(), iip, snapDirs);
    Mockito.verifyZeroInteractions(iip);
  }
}
