/**
 * 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.apache.hadoop.hdfs.server.common.HdfsServerConstants.NodeType.DATA_NODE;
import static org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NodeType.NAME_NODE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.io.File;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants;
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NodeType;
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.StartupOption;
import org.apache.hadoop.hdfs.server.common.Storage;
import org.apache.hadoop.hdfs.server.common.StorageInfo;
import org.junit.After;
import org.junit.Test;

/**
 * This test ensures the appropriate response (successful or failure) from 
 * a Datanode when the system is started with differing version combinations. 
 */
public class TestDFSStartupVersions {
  
  private static final Log LOG = LogFactory.getLog(
                                                   "org.apache.hadoop.hdfs.TestDFSStartupVersions");
  private MiniDFSCluster cluster = null;
  
  /**
   * Writes an INFO log message containing the parameters.
   */
  void log(String label, NodeType nodeType, Integer testCase,
      StorageData sd) {
    String testCaseLine = "";
    if (testCase != null) {
      testCaseLine = " testCase="+testCase;
    }
    LOG.info("============================================================");
    LOG.info("***TEST*** " + label + ":"
             + testCaseLine
             + " nodeType="+nodeType
             + " layoutVersion="+sd.storageInfo.getLayoutVersion()
             + " namespaceID="+sd.storageInfo.getNamespaceID()
             + " fsscTime="+sd.storageInfo.getCTime()
             + " clusterID="+sd.storageInfo.getClusterID()
             + " BlockPoolID="+sd.blockPoolId);
  }
  
  /**
   * Class used for initializing version information for tests
   */
  private static class StorageData {
    private final StorageInfo storageInfo;
    private final String blockPoolId;
    
    StorageData(int layoutVersion, int namespaceId, String clusterId,
        long cTime, String bpid) {
      storageInfo = new StorageInfo(layoutVersion, namespaceId, clusterId,
          cTime, NodeType.DATA_NODE);
      blockPoolId = bpid;
    }
  }
  
  /**
   * Initialize the versions array.  This array stores all combinations 
   * of cross product:
   *  {oldLayoutVersion,currentLayoutVersion,futureLayoutVersion} X
   *    {currentNamespaceId,incorrectNamespaceId} X
   *      {pastFsscTime,currentFsscTime,futureFsscTime}
   */
  private StorageData[] initializeVersions() throws Exception {
    int layoutVersionOld = Storage.LAST_UPGRADABLE_LAYOUT_VERSION;
    int layoutVersionCur = HdfsServerConstants.DATANODE_LAYOUT_VERSION;
    int layoutVersionNew = Integer.MIN_VALUE;
    int namespaceIdCur = UpgradeUtilities.getCurrentNamespaceID(null);
    int namespaceIdOld = Integer.MIN_VALUE;
    long fsscTimeOld = Long.MIN_VALUE;
    long fsscTimeCur = UpgradeUtilities.getCurrentFsscTime(null);
    long fsscTimeNew = Long.MAX_VALUE;
    String clusterID = "testClusterID";
    String invalidClusterID = "testClusterID";
    String bpid = UpgradeUtilities.getCurrentBlockPoolID(null);
    String invalidBpid = "invalidBpid";
    
    return new StorageData[] {
        new StorageData(layoutVersionOld, namespaceIdCur, clusterID,
            fsscTimeOld, bpid), // 0
        new StorageData(layoutVersionOld, namespaceIdCur, clusterID,
            fsscTimeCur, bpid), // 1
        new StorageData(layoutVersionOld, namespaceIdCur, clusterID,
            fsscTimeNew, bpid), // 2
        new StorageData(layoutVersionOld, namespaceIdOld, clusterID,
            fsscTimeOld, bpid), // 3
        new StorageData(layoutVersionOld, namespaceIdOld, clusterID,
            fsscTimeCur, bpid), // 4
        new StorageData(layoutVersionOld, namespaceIdOld, clusterID,
            fsscTimeNew, bpid), // 5
        new StorageData(layoutVersionCur, namespaceIdCur, clusterID,
            fsscTimeOld, bpid), // 6
        new StorageData(layoutVersionCur, namespaceIdCur, clusterID,
            fsscTimeCur, bpid), // 7
        new StorageData(layoutVersionCur, namespaceIdCur, clusterID,
            fsscTimeNew, bpid), // 8
        new StorageData(layoutVersionCur, namespaceIdOld, clusterID,
            fsscTimeOld, bpid), // 9
        new StorageData(layoutVersionCur, namespaceIdOld, clusterID,
            fsscTimeCur, bpid), // 10
        new StorageData(layoutVersionCur, namespaceIdOld, clusterID,
            fsscTimeNew, bpid), // 11
        new StorageData(layoutVersionNew, namespaceIdCur, clusterID,
            fsscTimeOld, bpid), // 12
        new StorageData(layoutVersionNew, namespaceIdCur, clusterID,
            fsscTimeCur, bpid), // 13
        new StorageData(layoutVersionNew, namespaceIdCur, clusterID,
            fsscTimeNew, bpid), // 14
        new StorageData(layoutVersionNew, namespaceIdOld, clusterID,
            fsscTimeOld, bpid), // 15
        new StorageData(layoutVersionNew, namespaceIdOld, clusterID,
            fsscTimeCur, bpid), // 16
        new StorageData(layoutVersionNew, namespaceIdOld, clusterID,
            fsscTimeNew, bpid), // 17
        // Test with invalid clusterId
        new StorageData(layoutVersionCur, namespaceIdCur, invalidClusterID,
            fsscTimeCur, bpid), // 18
        // Test with invalid block pool Id
        new StorageData(layoutVersionCur, namespaceIdCur, clusterID,
            fsscTimeCur, invalidBpid) // 19
    };
  }
  
  /**
   * Determines if the given Namenode version and Datanode version
   * are compatible with each other. Compatibility in this case mean
   * that the Namenode and Datanode will successfully start up and
   * will work together. The rules for compatibility,
   * taken from the DFS Upgrade Design, are as follows:
   * <pre>
   * <ol>
   * <li>Check 0: Datanode namespaceID != Namenode namespaceID the startup fails
   * </li>
   * <li>Check 1: Datanode clusterID != Namenode clusterID the startup fails
   * </li>
   * <li>Check 2: Datanode blockPoolID != Namenode blockPoolID the startup fails
   * </li>
   * <li>Check 3: The data-node does regular startup (no matter which options 
   *    it is started with) if
   *       softwareLV == storedLV AND 
   *       DataNode.FSSCTime == NameNode.FSSCTime
   * </li>
   * <li>Check 4: The data-node performs an upgrade if it is started without any 
   *    options and
   *       |softwareLV| > |storedLV| OR 
   *       (softwareLV == storedLV AND
   *        DataNode.FSSCTime < NameNode.FSSCTime)
   * </li>
   * <li>NOT TESTED: The data-node rolls back if it is started with
   *    the -rollback option and
   *       |softwareLV| >= |previous.storedLV| AND 
   *       DataNode.previous.FSSCTime <= NameNode.FSSCTime
   * </li>
   * <li>Check 5: In all other cases the startup fails.</li>
   * </ol>
   * </pre>
   */
  boolean isVersionCompatible(StorageData namenodeSd, StorageData datanodeSd) {
    final StorageInfo namenodeVer = namenodeSd.storageInfo;
    final StorageInfo datanodeVer = datanodeSd.storageInfo;
    // check #0
    if (namenodeVer.getNamespaceID() != datanodeVer.getNamespaceID()) {
      LOG.info("namespaceIDs are not equal: isVersionCompatible=false");
      return false;
    }
    // check #1
    if (!namenodeVer.getClusterID().equals(datanodeVer.getClusterID())) {
      LOG.info("clusterIDs are not equal: isVersionCompatible=false");
      return false;
    }
    // check #2
    if (!namenodeSd.blockPoolId.equals(datanodeSd.blockPoolId)) {
      LOG.info("blockPoolIDs are not equal: isVersionCompatible=false");
      return false;
    }
    // check #3
    int softwareLV = HdfsServerConstants.DATANODE_LAYOUT_VERSION;
    int storedLV = datanodeVer.getLayoutVersion();
    if (softwareLV == storedLV &&  
        datanodeVer.getCTime() == namenodeVer.getCTime()) 
      {
        LOG.info("layoutVersions and cTimes are equal: isVersionCompatible=true");
        return true;
      }
    // check #4
    long absSoftwareLV = Math.abs((long)softwareLV);
    long absStoredLV = Math.abs((long)storedLV);
    if (absSoftwareLV > absStoredLV ||
        (softwareLV == storedLV &&
         datanodeVer.getCTime() < namenodeVer.getCTime())) 
      {
        LOG.info("softwareLayoutVersion is newer OR namenode cTime is newer: isVersionCompatible=true");
        return true;
      }
    // check #5
    LOG.info("default case: isVersionCompatible=false");
    return false;
  }
  
  /**
   * This test ensures the appropriate response (successful or failure) from 
   * a Datanode when the system is started with differing version combinations. 
   * <pre>
   * For each 3-tuple in the cross product
   *   ({oldLayoutVersion,currentLayoutVersion,futureLayoutVersion},
   *    {currentNamespaceId,incorrectNamespaceId},
   *    {pastFsscTime,currentFsscTime,futureFsscTime})
   *      1. Startup Namenode with version file containing 
   *         (currentLayoutVersion,currentNamespaceId,currentFsscTime)
   *      2. Attempt to startup Datanode with version file containing 
   *         this iterations version 3-tuple
   * </pre>
   */
  @Test (timeout=300000)
  public void testVersions() throws Exception {
    UpgradeUtilities.initialize();
    Configuration conf = UpgradeUtilities.initializeStorageStateConf(1, 
                                                      new HdfsConfiguration());
    StorageData[] versions = initializeVersions();
    UpgradeUtilities.createNameNodeStorageDirs(
        conf.getStrings(DFSConfigKeys.DFS_NAMENODE_NAME_DIR_KEY), "current");
    cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
                                              .format(false)
                                              .manageDataDfsDirs(false)
                                              .manageNameDfsDirs(false)
                                              .startupOption(StartupOption.REGULAR)
                                              .build();
    StorageData nameNodeVersion = new StorageData(
        HdfsServerConstants.NAMENODE_LAYOUT_VERSION,
        UpgradeUtilities.getCurrentNamespaceID(cluster),
        UpgradeUtilities.getCurrentClusterID(cluster),
        UpgradeUtilities.getCurrentFsscTime(cluster),
        UpgradeUtilities.getCurrentBlockPoolID(cluster));
    
    log("NameNode version info", NAME_NODE, null, nameNodeVersion);
    String bpid = UpgradeUtilities.getCurrentBlockPoolID(cluster);
    for (int i = 0; i < versions.length; i++) {
      File[] storage = UpgradeUtilities.createDataNodeStorageDirs(
          conf.getStrings(DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY), "current");
      log("DataNode version info", DATA_NODE, i, versions[i]);
      UpgradeUtilities.createDataNodeVersionFile(storage,
          versions[i].storageInfo, bpid, versions[i].blockPoolId);
      try {
        cluster.startDataNodes(conf, 1, false, StartupOption.REGULAR, null);
      } catch (Exception ignore) {
        // Ignore.  The asserts below will check for problems.
        // ignore.printStackTrace();
      }
      assertTrue(cluster.getNameNode() != null);
      assertEquals(isVersionCompatible(nameNodeVersion, versions[i]),
                   cluster.isDataNodeUp());
      cluster.shutdownDataNodes();
    }
  }
  
  @After
  public void tearDown() throws Exception {
    LOG.info("Shutting down MiniDFSCluster");
    if (cluster != null) {
      cluster.shutdown();
      cluster = null;
    }
  }
  
  public static void main(String[] args) throws Exception {
    new TestDFSStartupVersions().testVersions();
  }
  
}

