Example #1
0
  /**
   * Upgrade -- Move current storage into a backup directory, and hardlink all its blocks into the
   * new current directory.
   *
   * <p>Upgrade from pre-0.22 to 0.22 or later release e.g. 0.19/0.20/ => 0.22/0.23
   *
   * <ul>
   *   <li>If <SD>/previous exists then delete it
   *   <li>Rename <SD>/current to <SD>/previous.tmp
   *   <li>Create new <SD>/current/<bpid>/current directory
   *   <li>
   *       <ul>
   *         <li>Hard links for block files are created from <SD>/previous.tmp to
   *             <SD>/current/<bpid>/current
   *         <li>Saves new version file in <SD>/current/<bpid>/current directory
   *       </ul>
   *   <li>Rename <SD>/previous.tmp to <SD>/previous
   * </ul>
   *
   * There should be only ONE namenode in the cluster for first time upgrade to 0.22
   *
   * @param sd storage directory
   * @throws IOException on error
   */
  void doUpgrade(StorageDirectory sd, NamespaceInfo nsInfo) throws IOException {
    if (LayoutVersion.supports(Feature.FEDERATION, layoutVersion)) {
      clusterID = nsInfo.getClusterID();
      layoutVersion = nsInfo.getLayoutVersion();
      writeProperties(sd);
      return;
    }

    LOG.info(
        "Upgrading storage directory "
            + sd.getRoot()
            + ".\n   old LV = "
            + this.getLayoutVersion()
            + "; old CTime = "
            + this.getCTime()
            + ".\n   new LV = "
            + nsInfo.getLayoutVersion()
            + "; new CTime = "
            + nsInfo.getCTime());

    File curDir = sd.getCurrentDir();
    File prevDir = sd.getPreviousDir();
    File bbwDir = new File(sd.getRoot(), Storage.STORAGE_1_BBW);

    assert curDir.exists() : "Data node current directory must exist.";
    // Cleanup directory "detach"
    cleanupDetachDir(new File(curDir, STORAGE_DIR_DETACHED));

    // 1. delete <SD>/previous dir before upgrading
    if (prevDir.exists()) deleteDir(prevDir);
    // get previous.tmp directory, <SD>/previous.tmp
    File tmpDir = sd.getPreviousTmp();
    assert !tmpDir.exists() : "Data node previous.tmp directory must not exist.";

    // 2. Rename <SD>/current to <SD>/previous.tmp
    rename(curDir, tmpDir);

    // 3. Format BP and hard link blocks from previous directory
    File curBpDir = BlockPoolSliceStorage.getBpRoot(nsInfo.getBlockPoolID(), curDir);
    BlockPoolSliceStorage bpStorage =
        new BlockPoolSliceStorage(
            nsInfo.getNamespaceID(),
            nsInfo.getBlockPoolID(),
            nsInfo.getCTime(),
            nsInfo.getClusterID());
    bpStorage.format(curDir, nsInfo);
    linkAllBlocks(tmpDir, bbwDir, new File(curBpDir, STORAGE_DIR_CURRENT));

    // 4. Write version file under <SD>/current
    layoutVersion = HdfsConstants.LAYOUT_VERSION;
    clusterID = nsInfo.getClusterID();
    writeProperties(sd);

    // 5. Rename <SD>/previous.tmp to <SD>/previous
    rename(tmpDir, prevDir);
    LOG.info("Upgrade of " + sd.getRoot() + " is complete");
    addBlockPoolStorage(nsInfo.getBlockPoolID(), bpStorage);
  }
  /**
   * Load one storage directory. Recover from previous transitions if required.
   *
   * @param datanode datanode instance
   * @param nsInfo namespace information
   * @param dataDir the root path of the storage directory
   * @param startOpt startup option
   * @return the StorageDirectory successfully loaded.
   * @throws IOException
   */
  private StorageDirectory loadStorageDirectory(
      DataNode datanode, NamespaceInfo nsInfo, File dataDir, StartupOption startOpt)
      throws IOException {
    StorageDirectory sd = new StorageDirectory(dataDir, null, true);
    try {
      StorageState curState = sd.analyzeStorage(startOpt, this);
      // sd is locked but not opened
      switch (curState) {
        case NORMAL:
          break;
        case NON_EXISTENT:
          LOG.info("Block pool storage directory " + dataDir + " does not exist");
          throw new IOException("Storage directory " + dataDir + " does not exist");
        case NOT_FORMATTED: // format
          LOG.info(
              "Block pool storage directory "
                  + dataDir
                  + " is not formatted for "
                  + nsInfo.getBlockPoolID());
          LOG.info("Formatting ...");
          format(sd, nsInfo);
          break;
        default: // recovery part is common
          sd.doRecover(curState);
      }

      // 2. Do transitions
      // Each storage directory is treated individually.
      // During startup some of them can upgrade or roll back
      // while others could be up-to-date for the regular startup.
      doTransition(datanode, sd, nsInfo, startOpt);
      if (getCTime() != nsInfo.getCTime()) {
        throw new IOException("Data-node and name-node CTimes must be the same.");
      }

      // 3. Update successfully loaded storage.
      setServiceLayoutVersion(getServiceLayoutVersion());
      writeProperties(sd);

      return sd;
    } catch (IOException ioe) {
      sd.unlock();
      throw ioe;
    }
  }
 /**
  * Format a block pool slice storage.
  *
  * @param dnCurDir DataStorage current directory
  * @param nsInfo the name space info
  * @throws IOException Signals that an I/O exception has occurred.
  */
 void format(File dnCurDir, NamespaceInfo nsInfo) throws IOException {
   File curBpDir = getBpRoot(nsInfo.getBlockPoolID(), dnCurDir);
   StorageDirectory bpSdir = new StorageDirectory(curBpDir);
   format(bpSdir, nsInfo);
 }