예제 #1
0
 private void doTransition(
     DataNode datanode, StorageDirectory sd, NamespaceInfo nsInfo, StartupOption startOpt)
     throws IOException {
   if (startOpt == StartupOption.ROLLBACK) {
     throw new RuntimeException("未实现");
   }
   readProperties(sd);
   checkVersionUpgradable(this.layoutVersion);
   // 版本号为负数,越小越高,文件里面的layoutVersion必须比hadoop版本大或者等于
   assert this.layoutVersion >= HdfsConstants.DATANODE_LAYOUT_VERSION : "不允许将来的版本";
   boolean federationSupported =
       DataNodeLayoutVersion.supports(LayoutVersion.Feature.FEDERATION, layoutVersion);
   if (!federationSupported && getNamespaceID() != nsInfo.getNamespaceID()) {
     throw new IOException(
         "Incompatible namespaceIDs in "
             + sd.getRoot().getCanonicalPath()
             + ": namenode namespaceID = "
             + nsInfo.getNamespaceID()
             + "; datanode namespaceID = "
             + getNamespaceID());
   }
   if (federationSupported && !getClusterID().equals(nsInfo.getClusterID())) {
     throw new IOException(
         "Incompatible clusterIDs in "
             + sd.getRoot().getCanonicalPath()
             + ": namenode clusterID = "
             + nsInfo.getClusterID()
             + "; datanode clusterID = "
             + getClusterID());
   }
   boolean haveValidStorageId =
       DataNodeLayoutVersion.supports(
               LayoutVersion.Feature.ADD_DATANODE_AND_STORAGE_UUIDS, layoutVersion)
           && DatanodeStorage.isValidStorageId(sd.getStorageUuid());
   if (this.layoutVersion == HdfsConstants.DATANODE_LAYOUT_VERSION) {
     createStorageID(sd, !haveValidStorageId);
     return;
   }
   throw new IOException(
       "BUG: The stored LV = "
           + this.getLayoutVersion()
           + " is newer than the supported LV = "
           + HdfsConstants.DATANODE_LAYOUT_VERSION);
 }
  /**
   * Upgrade to any release after 0.22 (0.22 included) release e.g. 0.22 => 0.23 Upgrade procedure
   * is as follows:
   *
   * <ol>
   *   <li>If <SD>/current/<bpid>/previous exists then delete it
   *   <li>Rename <SD>/current/<bpid>/current to <SD>/current/bpid/current/previous.tmp
   *   <li>Create new <SD>current/<bpid>/current directory
   *       <ol>
   *         <li>Hard links for block files are created from previous.tmp to current
   *         <li>Save new version file in current directory
   *       </ol>
   *   <li>Rename previous.tmp to previous
   * </ol>
   *
   * @param bpSd storage directory <SD>/current/<bpid>
   * @param nsInfo Namespace Info from the namenode
   * @throws IOException on error
   */
  void doUpgrade(DataNode datanode, StorageDirectory bpSd, NamespaceInfo nsInfo)
      throws IOException {
    // Upgrading is applicable only to release with federation or after
    if (!DataNodeLayoutVersion.supports(LayoutVersion.Feature.FEDERATION, layoutVersion)) {
      return;
    }
    LOG.info(
        "Upgrading block pool storage directory "
            + bpSd.getRoot()
            + ".\n   old LV = "
            + this.getLayoutVersion()
            + "; old CTime = "
            + this.getCTime()
            + ".\n   new LV = "
            + HdfsConstants.DATANODE_LAYOUT_VERSION
            + "; new CTime = "
            + nsInfo.getCTime());
    // get <SD>/previous directory
    String dnRoot = getDataNodeStorageRoot(bpSd.getRoot().getCanonicalPath());
    StorageDirectory dnSdStorage = new StorageDirectory(new File(dnRoot));
    File dnPrevDir = dnSdStorage.getPreviousDir();

    // If <SD>/previous directory exists delete it
    if (dnPrevDir.exists()) {
      deleteDir(dnPrevDir);
    }
    File bpCurDir = bpSd.getCurrentDir();
    File bpPrevDir = bpSd.getPreviousDir();
    assert bpCurDir.exists() : "BP level current directory must exist.";
    cleanupDetachDir(new File(bpCurDir, DataStorage.STORAGE_DIR_DETACHED));

    // 1. Delete <SD>/current/<bpid>/previous dir before upgrading
    if (bpPrevDir.exists()) {
      deleteDir(bpPrevDir);
    }
    File bpTmpDir = bpSd.getPreviousTmp();
    assert !bpTmpDir.exists() : "previous.tmp directory must not exist.";

    // 2. Rename <SD>/current/<bpid>/current to
    //    <SD>/current/<bpid>/previous.tmp
    rename(bpCurDir, bpTmpDir);

    // 3. Create new <SD>/current with block files hardlinks and VERSION
    linkAllBlocks(datanode, bpTmpDir, bpCurDir);
    this.layoutVersion = HdfsConstants.DATANODE_LAYOUT_VERSION;
    assert this.namespaceID == nsInfo.getNamespaceID()
        : "Data-node and name-node layout versions must be the same.";
    this.cTime = nsInfo.getCTime();
    writeProperties(bpSd);

    // 4.rename <SD>/current/<bpid>/previous.tmp to
    // <SD>/current/<bpid>/previous
    rename(bpTmpDir, bpPrevDir);
    LOG.info("Upgrade of block pool " + blockpoolID + " at " + bpSd.getRoot() + " is complete");
  }
  /**
   * Cleanup the detachDir.
   *
   * <p>If the directory is not empty report an error; Otherwise remove the directory.
   *
   * @param detachDir detach directory
   * @throws IOException if the directory is not empty or it can not be removed
   */
  private void cleanupDetachDir(File detachDir) throws IOException {
    if (!DataNodeLayoutVersion.supports(LayoutVersion.Feature.APPEND_RBW_DIR, layoutVersion)
        && detachDir.exists()
        && detachDir.isDirectory()) {

      if (FileUtil.list(detachDir).length != 0) {
        throw new IOException(
            "Detached directory "
                + detachDir
                + " is not empty. Please manually move each file under this "
                + "directory to the finalized directory if the finalized "
                + "directory tree does not have the file.");
      } else if (!detachDir.delete()) {
        throw new IOException("Cannot remove directory " + detachDir);
      }
    }
  }
예제 #4
0
  private void setFieldsFromProperties(
      Properties props, StorageDirectory sd, boolean overrideLayoutVersion, int toLayoutVersion)
      throws IOException {
    if (overrideLayoutVersion) {
      this.layoutVersion = toLayoutVersion;
    } else {
      setLayoutVersion(props, sd);
    }
    setcTime(props, sd);
    checkStorageType(props, sd);
    setClusterId(props, layoutVersion, sd);
    if (!DataNodeLayoutVersion.supports(LayoutVersion.Feature.FEDERATION, layoutVersion)) {
      setNamespaceID(props, sd);
    }

    String ssid = props.getProperty("storageID");
    if (ssid == null) {
      throw new InconsistentFSStateException(
          sd.getRoot(), "file " + STORAGE_FILE_VERSION + " is invalid.");
    }
    String sid = sd.getStorageUuid();
    if (!(sid == null || sid.equals("") || ssid.equals("") || sid.equals(ssid))) {
      throw new InconsistentFSStateException(sd.getRoot(), "具有不兼容的存储标识。");
    }
    if (sid == null) { // update id only if it was null
      sd.setStorageUuid(ssid);
    }
    if (props.getProperty("datanodeUuid") != null) {
      String dnUuid = props.getProperty("datanodeUuid");
      if (getDatanodeUuid() == null) {
        setDatanodeUuid(dnUuid);
      } else if (getDatanodeUuid().compareTo(dnUuid) != 0) {
        throw new InconsistentFSStateException(
            sd.getRoot(),
            "Root "
                + sd.getRoot()
                + ": DatanodeUuid="
                + dnUuid
                + ", does not match "
                + getDatanodeUuid()
                + " from other"
                + " StorageDirectory.");
      }
    }
  }
예제 #5
0
  @Override
  protected void setPropertiesFromFields(Properties props, StorageDirectory sd) throws IOException {
    props.setProperty("storageType", storageType.toString());
    props.setProperty("clusterID", clusterID);
    props.setProperty("cTime", String.valueOf(cTime));
    props.setProperty("layoutVersion", String.valueOf(layoutVersion));
    props.setProperty("storageID", sd.getStorageUuid());

    String datanodeUuid = getDatanodeUuid();
    if (datanodeUuid != null) {
      props.setProperty("datanodeUuid", datanodeUuid);
    }

    // Set NamespaceID in version before federation
    if (!DataNodeLayoutVersion.supports(LayoutVersion.Feature.FEDERATION, layoutVersion)) {
      props.setProperty("namespaceID", String.valueOf(namespaceID));
    }
  }