Ejemplo n.º 1
0
  /*
   * Read ClusterID, StorageID, StorageType, CTime from
   * DataStorage VERSION file and verify them.
   */
  @Override
  protected void setFieldsFromProperties(Properties props, StorageDirectory sd) throws IOException {
    setLayoutVersion(props, sd);
    setcTime(props, sd);
    setStorageType(props, sd);
    setClusterId(props, layoutVersion, sd);

    // Read NamespaceID in version before federation
    if (!LayoutVersion.supports(Feature.FEDERATION, layoutVersion)) {
      setNamespaceID(props, sd);
    }

    // valid storage id, storage id may be empty
    String ssid = props.getProperty("storageID");
    if (ssid == null) {
      throw new InconsistentFSStateException(
          sd.getRoot(), "file " + STORAGE_FILE_VERSION + " is invalid.");
    }
    String sid = getStorageID();
    if (!(sid.equals("") || ssid.equals("") || sid.equals(ssid))) {
      throw new InconsistentFSStateException(sd.getRoot(), "has incompatible storage Id.");
    }

    if (sid.equals("")) { // update id only if it was empty
      setStorageID(ssid);
    }
  }
Ejemplo n.º 2
0
 private StorageDirectory loadStorageDirectory(
     DataNode datanode, NamespaceInfo nsInfo, File dataDir, StartupOption startOpt)
     throws IOException {
   StorageDirectory sd = new StorageDirectory(dataDir, null, false);
   try {
     StorageState curState = sd.analyzeStorage(startOpt, this);
     switch (curState) {
       case NORMAL:
         break;
       case NON_EXISTENT:
         LOG.info("Storage directory " + dataDir + " does not exist");
         throw new IOException("Storage directory " + dataDir + " does not exist");
       case NOT_FORMATTED: // format
         LOG.info(
             "Storage directory " + dataDir + " is not formatted for " + nsInfo.getBlockPoolID());
         LOG.info("Formatting ...");
         format(sd, nsInfo, datanode.getDatanodeUuid());
         break;
       default:
         throw new RuntimeException("未实现");
     }
     doTransition(datanode, sd, nsInfo, startOpt);
     writeProperties(sd);
     return sd;
   } catch (IOException ioe) {
     sd.unlock();
     throw ioe;
   }
 }
 /** Delete all files and directories in the trash directories. */
 public void clearTrash() {
   for (StorageDirectory sd : storageDirs) {
     File trashRoot = getTrashRootDir(sd);
     Preconditions.checkState(!(trashRoot.exists() && sd.getPreviousDir().exists()));
     FileUtil.fullyDelete(trashRoot);
     LOG.info("Cleared trash for storage directory " + sd);
   }
 }
Ejemplo n.º 4
0
  /**
   * Analize which and whether a transition of the fs state is required and perform it if necessary.
   *
   * <p>Rollback if previousLV >= LAYOUT_VERSION && prevCTime <= namenode.cTime Upgrade if this.LV >
   * LAYOUT_VERSION || this.cTime < namenode.cTime Regular startup if this.LV = LAYOUT_VERSION &&
   * this.cTime = namenode.cTime
   *
   * @param datanode Datanode to which this storage belongs to
   * @param sd storage directory
   * @param nsInfo namespace info
   * @param startOpt startup option
   * @throws IOException
   */
  private void doTransition(
      DataNode datanode, StorageDirectory sd, NamespaceInfo nsInfo, StartupOption startOpt)
      throws IOException {
    if (startOpt == StartupOption.ROLLBACK) {
      doRollback(sd, nsInfo); // rollback if applicable
    }
    readProperties(sd);
    checkVersionUpgradable(this.layoutVersion);
    assert this.layoutVersion >= HdfsConstants.LAYOUT_VERSION : "Future version is not allowed";

    boolean federationSupported = LayoutVersion.supports(Feature.FEDERATION, layoutVersion);
    // For pre-federation version - validate the namespaceID
    if (!federationSupported && getNamespaceID() != nsInfo.getNamespaceID()) {
      throw new IOException(
          "Incompatible namespaceIDs in "
              + sd.getRoot().getCanonicalPath()
              + ": namenode namespaceID = "
              + nsInfo.getNamespaceID()
              + "; datanode namespaceID = "
              + getNamespaceID());
    }

    // For version that supports federation, validate clusterID
    if (federationSupported && !getClusterID().equals(nsInfo.getClusterID())) {
      throw new IOException(
          "Incompatible clusterIDs in "
              + sd.getRoot().getCanonicalPath()
              + ": namenode clusterID = "
              + nsInfo.getClusterID()
              + "; datanode clusterID = "
              + getClusterID());
    }

    // regular start up
    if (this.layoutVersion == HdfsConstants.LAYOUT_VERSION && this.cTime == nsInfo.getCTime())
      return; // regular startup
    // verify necessity of a distributed upgrade
    UpgradeManagerDatanode um = datanode.getUpgradeManagerDatanode(nsInfo.getBlockPoolID());
    verifyDistributedUpgradeProgress(um, nsInfo);

    // do upgrade
    if (this.layoutVersion > HdfsConstants.LAYOUT_VERSION || this.cTime < nsInfo.getCTime()) {
      doUpgrade(sd, nsInfo); // upgrade
      return;
    }

    // layoutVersion == LAYOUT_VERSION && this.cTime > nsInfo.cTime
    // must shutdown
    throw new IOException(
        "Datanode state: LV = "
            + this.getLayoutVersion()
            + " CTime = "
            + this.getCTime()
            + " is newer than the namespace state: LV = "
            + nsInfo.getLayoutVersion()
            + " CTime = "
            + nsInfo.getCTime());
  }
Ejemplo n.º 5
0
 private void format(StorageDirectory bpSdir, NamespaceInfo nsInfo) throws IOException {
   LOG.info("Formatting block pool " + blockpoolID + " directory " + bpSdir.getCurrentDir());
   bpSdir.clearDirectory(); // create directory
   this.layoutVersion = HdfsConstants.DATANODE_LAYOUT_VERSION;
   this.cTime = nsInfo.getCTime();
   this.namespaceID = nsInfo.getNamespaceID();
   this.blockpoolID = nsInfo.getBlockPoolID();
   writeProperties(bpSdir);
 }
Ejemplo n.º 6
0
 void endCheckpoint() throws IOException {
   for (StorageDirectory sd : storageDirs) {
     File tmpCkptDir = sd.getLastCheckpointTmp();
     File prevCkptDir = sd.getPreviousCheckpoint();
     // delete previous dir
     if (prevCkptDir.exists()) deleteDir(prevCkptDir);
     // rename tmp to previous
     if (tmpCkptDir.exists()) rename(tmpCkptDir, prevCkptDir);
   }
 }
Ejemplo n.º 7
0
 void finalizeUpgrade(String bpID) throws IOException {
   for (StorageDirectory sd : storageDirs) {
     File prevDir = sd.getPreviousDir();
     if (prevDir.exists()) {
       throw new RuntimeException("未实现");
     } else {
       BlockPoolSliceStorage bpStorage = bpStorageMap.get(bpID);
       bpStorage.doFinalize(sd.getCurrentDir());
     }
   }
 }
 /**
  * Remove block pool level storage directory.
  *
  * @param absPathToRemove the absolute path of the root for the block pool level storage to
  *     remove.
  */
 void remove(File absPathToRemove) {
   Preconditions.checkArgument(absPathToRemove.isAbsolute());
   LOG.info("Removing block level storage: " + absPathToRemove);
   for (Iterator<StorageDirectory> it = this.storageDirs.iterator(); it.hasNext(); ) {
     StorageDirectory sd = it.next();
     if (sd.getRoot().getAbsoluteFile().equals(absPathToRemove)) {
       it.remove();
       break;
     }
   }
 }
Ejemplo n.º 9
0
 /**
  * Prepare directories for a new checkpoint.
  *
  * <p>Rename <code>current</code> to <code>lastcheckpoint.tmp</code> and recreate <code>current
  * </code>.
  *
  * @throws IOException
  */
 void startCheckpoint() throws IOException {
   for (StorageDirectory sd : storageDirs) {
     File curDir = sd.getCurrentDir();
     File tmpCkptDir = sd.getLastCheckpointTmp();
     assert !tmpCkptDir.exists() : tmpCkptDir.getName() + " directory must not exist.";
     if (curDir.exists()) {
       // rename current to tmp
       rename(curDir, tmpCkptDir);
     }
     if (!curDir.mkdir()) throw new IOException("Cannot create directory " + curDir);
   }
 }
Ejemplo n.º 10
0
 public void clearRollingUpgradeMarkers(List<StorageDirectory> dnStorageDirs) throws IOException {
   for (StorageDirectory sd : dnStorageDirs) {
     File bpRoot = getBpRoot(blockpoolID, sd.getCurrentDir());
     File markerFile = new File(bpRoot, ROLLING_UPGRADE_MARKER_FILE);
     if (!storagesWithoutRollingUpgradeMarker.contains(bpRoot.toString())) {
       if (markerFile.exists()) {
         throw new RuntimeException("未实现");
       }
       storagesWithoutRollingUpgradeMarker.add(bpRoot.toString());
       storagesWithRollingUpgradeMarker.remove(bpRoot.toString());
     }
   }
 }
Ejemplo n.º 11
0
  void format(StorageDirectory sd, NamespaceInfo nsInfo, String datanodeUuid) throws IOException {
    sd.clearDirectory();
    this.layoutVersion = HdfsConstants.DATANODE_LAYOUT_VERSION;
    this.clusterID = nsInfo.getClusterID();
    this.namespaceID = nsInfo.getNamespaceID();
    this.cTime = 0;
    setDatanodeUuid(datanodeUuid);
    if (sd.getStorageUuid() == null) {
      // 分配新的 Storage UUID.
      sd.setStorageUuid(DatanodeStorage.generateUuid());
    }

    writeProperties(sd);
  }
 /**
  * Create a rolling upgrade marker file for each BP storage root, if it does not exist already.
  */
 public void setRollingUpgradeMarkers(List<StorageDirectory> dnStorageDirs) throws IOException {
   for (StorageDirectory sd : dnStorageDirs) {
     File bpRoot = getBpRoot(blockpoolID, sd.getCurrentDir());
     File markerFile = new File(bpRoot, ROLLING_UPGRADE_MARKER_FILE);
     if (!storagesWithRollingUpgradeMarker.contains(bpRoot.toString())) {
       if (!markerFile.exists() && markerFile.createNewFile()) {
         LOG.info("Created " + markerFile);
       } else {
         LOG.info(markerFile + " already exists.");
       }
       storagesWithRollingUpgradeMarker.add(bpRoot.toString());
       storagesWithoutRollingUpgradeMarker.remove(bpRoot.toString());
     }
   }
 }
Ejemplo n.º 13
0
 /**
  * 鏄惁鍥犵┖闂翠笉瓒虫嫆鍐�
  *
  * @param fileType 璇锋眰鍐欐搷浣滅殑鏂囦欢绫诲瀷
  * @return 杩斿洖婊¤冻鍐欐潯浠剁殑鏈�紭鐩綍锛涘鏋滆繑鍥瀗ull琛ㄧず娌℃湁鐩綍婊¤冻鏉′欢
  */
 private StorageDirectory limitSpaceUnwrite(int fileType, int type) {
   List<StorageDirectory> directories = getDirectorysByPriority(fileType);
   for (StorageDirectory directory : directories) {
     // 濡傛灉鍙鏌ュ缃瓨鍌ㄥ崱鍒欒繃婊や笅
     if (type == 1 && directory.type != DIRECTORY_EXTERNAL_SDCARD) {
       continue;
     }
     long residualSpace = getResidualSpace(directory.rootDirectory);
     if (getFileMaxSize(fileType) <= residualSpace) {
       directory.residualSpace = residualSpace;
       return directory;
     }
   }
   return null;
 }
Ejemplo n.º 14
0
  public synchronized boolean createStorageID(StorageDirectory sd, boolean regenerateStorageIds) {
    final String oldStorageID = sd.getStorageUuid();

    if (oldStorageID == null || regenerateStorageIds) {
      sd.setStorageUuid(DatanodeStorage.generateUuid());
      LOG.info(
          "Generated new storageID "
              + sd.getStorageUuid()
              + " for directory "
              + sd.getRoot()
              + (oldStorageID == null ? "" : (" to replace " + oldStorageID)));
      return true;
    }
    return false;
  }
Ejemplo n.º 15
0
 /*
  * Finalize the upgrade for a block pool
  */
 void finalizeUpgrade(String bpID) throws IOException {
   // To handle finalizing a snapshot taken at datanode level while
   // upgrading to federation, if datanode level snapshot previous exists,
   // then finalize it. Else finalize the corresponding BP.
   for (StorageDirectory sd : storageDirs) {
     File prevDir = sd.getPreviousDir();
     if (prevDir.exists()) {
       // data node level storage finalize
       doFinalize(sd);
     } else {
       // block pool storage finalize using specific bpID
       BlockPoolSliceStorage bpStorage = bpStorageMap.get(bpID);
       bpStorage.doFinalize(sd.getCurrentDir());
     }
   }
 }
 /**
  * Check whether the rolling upgrade marker file exists for each BP storage root. If it does
  * exist, then the marker file is cleared and more importantly the layout upgrade is finalized.
  */
 public void clearRollingUpgradeMarkers(List<StorageDirectory> dnStorageDirs) throws IOException {
   for (StorageDirectory sd : dnStorageDirs) {
     File bpRoot = getBpRoot(blockpoolID, sd.getCurrentDir());
     File markerFile = new File(bpRoot, ROLLING_UPGRADE_MARKER_FILE);
     if (!storagesWithoutRollingUpgradeMarker.contains(bpRoot.toString())) {
       if (markerFile.exists()) {
         LOG.info("Deleting " + markerFile);
         doFinalize(sd.getCurrentDir());
         if (!markerFile.delete()) {
           LOG.warn("Failed to delete " + markerFile);
         }
       }
       storagesWithoutRollingUpgradeMarker.add(bpRoot.toString());
       storagesWithRollingUpgradeMarker.remove(bpRoot.toString());
     }
   }
 }
Ejemplo n.º 17
0
 @Override
 protected void setFieldsFromProperties(Properties props, StorageDirectory sd) throws IOException {
   setLayoutVersion(props, sd);
   setNamespaceID(props, sd);
   setcTime(props, sd);
   String sbpid = props.getProperty("blockpoolID");
   setBlockPoolID(sd.getRoot(), sbpid);
 }
  /**
   * 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");
  }
  /**
   * 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;
    }
  }
Ejemplo n.º 20
0
 void doFinalize(File dnCurDir) throws IOException {
   File bpRoot = getBpRoot(blockpoolID, dnCurDir);
   StorageDirectory bpSd = new StorageDirectory(bpRoot);
   File prevDir = bpSd.getPreviousDir();
   if (!prevDir.exists()) {
     return; // already finalized
   }
   final String dataDirPath = bpSd.getRoot().getCanonicalPath();
   LOG.info(
       "Finalizing upgrade for storage directory "
           + dataDirPath
           + ".\n   cur LV = "
           + this.getLayoutVersion()
           + "; cur CTime = "
           + this.getCTime());
   assert bpSd.getCurrentDir().exists() : "Current directory must exist.";
   throw new RuntimeException("未实现");
 }
Ejemplo n.º 21
0
 void format(StorageDirectory sd, NamespaceInfo nsInfo) throws IOException {
   sd.clearDirectory(); // create directory
   this.layoutVersion = HdfsConstants.LAYOUT_VERSION;
   this.clusterID = nsInfo.getClusterID();
   this.namespaceID = nsInfo.getNamespaceID();
   this.cTime = 0;
   // store storageID as it currently is
   writeProperties(sd);
 }
Ejemplo n.º 22
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);
 }
Ejemplo n.º 23
0
  /**
   * Finalize procedure deletes an existing snapshot.
   *
   * <ol>
   *   <li>Rename previous to finalized.tmp directory
   *   <li>Fully delete the finalized.tmp directory
   * </ol>
   *
   * Do nothing, if previous directory does not exist
   */
  void doFinalize(StorageDirectory sd) throws IOException {
    File prevDir = sd.getPreviousDir();
    if (!prevDir.exists()) return; // already discarded

    final String dataDirPath = sd.getRoot().getCanonicalPath();
    LOG.info(
        "Finalizing upgrade for storage directory "
            + dataDirPath
            + ".\n   cur LV = "
            + this.getLayoutVersion()
            + "; cur CTime = "
            + this.getCTime());
    assert sd.getCurrentDir().exists() : "Current directory must exist.";
    final File tmpDir = sd.getFinalizedTmp(); // finalized.tmp directory
    final File bbwDir = new File(sd.getRoot(), Storage.STORAGE_1_BBW);
    // 1. rename previous to finalized.tmp
    rename(prevDir, tmpDir);

    // 2. delete finalized.tmp dir in a separate thread
    // Also delete the blocksBeingWritten from HDFS 1.x and earlier, if
    // it exists.
    new Daemon(
            new Runnable() {
              @Override
              public void run() {
                try {
                  deleteDir(tmpDir);
                  if (bbwDir.exists()) {
                    deleteDir(bbwDir);
                  }
                } catch (IOException ex) {
                  LOG.error("Finalize upgrade for " + dataDirPath + " failed", ex);
                }
                LOG.info("Finalize upgrade for " + dataDirPath + " is complete");
              }

              @Override
              public String toString() {
                return "Finalize " + dataDirPath;
              }
            })
        .start();
  }
  /*
   * Finalize the block pool storage by deleting <BP>/previous directory
   * that holds the snapshot.
   */
  void doFinalize(File dnCurDir) throws IOException {
    File bpRoot = getBpRoot(blockpoolID, dnCurDir);
    StorageDirectory bpSd = new StorageDirectory(bpRoot);
    // block pool level previous directory
    File prevDir = bpSd.getPreviousDir();
    if (!prevDir.exists()) {
      return; // already finalized
    }
    final String dataDirPath = bpSd.getRoot().getCanonicalPath();
    LOG.info(
        "Finalizing upgrade for storage directory "
            + dataDirPath
            + ".\n   cur LV = "
            + this.getLayoutVersion()
            + "; cur CTime = "
            + this.getCTime());
    assert bpSd.getCurrentDir().exists() : "Current directory must exist.";

    // rename previous to finalized.tmp
    final File tmpDir = bpSd.getFinalizedTmp();
    rename(prevDir, tmpDir);

    // delete finalized.tmp dir in a separate thread
    new Daemon(
            new Runnable() {
              @Override
              public void run() {
                try {
                  deleteDir(tmpDir);
                } catch (IOException ex) {
                  LOG.error("Finalize upgrade for " + dataDirPath + " failed.", ex);
                }
                LOG.info("Finalize upgrade for " + dataDirPath + " is complete.");
              }

              @Override
              public String toString() {
                return "Finalize " + dataDirPath;
              }
            })
        .start();
  }
Ejemplo n.º 25
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);
  }
Ejemplo n.º 26
0
  private void doTransition(
      DataNode datanode, StorageDirectory sd, NamespaceInfo nsInfo, StartupOption startOpt)
      throws IOException {
    if (startOpt == StartupOption.ROLLBACK && sd.getPreviousDir().exists()) {
      throw new RuntimeException("ROLLBACK 未实现");
    } else {
      int restored = restoreBlockFilesFromTrash(getTrashRootDir(sd));
      LOG.info("从垃圾桶恢复" + restored + "块文件.");
    }
    readProperties(sd);
    checkVersionUpgradable(this.layoutVersion);
    assert this.layoutVersion >= HdfsConstants.DATANODE_LAYOUT_VERSION
        : "Future version is not allowed";

    if (getNamespaceID() != nsInfo.getNamespaceID()) {
      throw new IOException(
          "Incompatible namespaceIDs in "
              + sd.getRoot().getCanonicalPath()
              + ": namenode namespaceID = "
              + nsInfo.getNamespaceID()
              + "; datanode namespaceID = "
              + getNamespaceID());
    }
    if (!blockpoolID.equals(nsInfo.getBlockPoolID())) {
      throw new IOException(
          "Incompatible blockpoolIDs in "
              + sd.getRoot().getCanonicalPath()
              + ": namenode blockpoolID = "
              + nsInfo.getBlockPoolID()
              + "; datanode blockpoolID = "
              + blockpoolID);
    }
    if (this.layoutVersion == HdfsConstants.DATANODE_LAYOUT_VERSION
        && this.cTime == nsInfo.getCTime()) {
      return; // 正常启动
    }
    throw new RuntimeException("upgrade 未实现");
  }
Ejemplo n.º 27
0
 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);
     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:
         throw new RuntimeException("未实现");
     }
     doTransition(datanode, sd, nsInfo, startOpt);
     if (getCTime() != nsInfo.getCTime()) {
       throw new IOException("Data-node and name-node CTimes 必须是相同.");
     }
     // 3. 更新成功加载存储。
     setServiceLayoutVersion(getServiceLayoutVersion());
     writeProperties(sd);
     return sd;
   } catch (IOException ioe) {
     sd.unlock();
     throw ioe;
   }
 }
Ejemplo n.º 28
0
 /**
  * Check whether underlying file system supports file locking.
  *
  * @return <code>true</code> if exclusive locks are supported or <code>false</code> otherwise.
  * @throws IOException
  * @see StorageDirectory#lock()
  */
 public boolean isLockSupported(int idx) throws IOException {
   StorageDirectory sd = storageDirs.get(idx);
   FileLock firstLock = null;
   FileLock secondLock = null;
   try {
     firstLock = sd.lock;
     if (firstLock == null) {
       firstLock = sd.tryLock();
       if (firstLock == null) return true;
     }
     secondLock = sd.tryLock();
     if (secondLock == null) return true;
   } finally {
     if (firstLock != null && firstLock != sd.lock) {
       firstLock.release();
       firstLock.channel().close();
     }
     if (secondLock != null) {
       secondLock.release();
       secondLock.channel().close();
     }
   }
   return false;
 }
Ejemplo n.º 29
0
 @Override
 public boolean isPreUpgradableLayout(StorageDirectory sd) throws IOException {
   File oldF = new File(sd.getRoot(), "storage");
   if (!oldF.exists()) return false;
   // check the layout version inside the storage file
   // Lock and Read old storage file
   RandomAccessFile oldFile = new RandomAccessFile(oldF, "rws");
   FileLock oldLock = oldFile.getChannel().tryLock();
   try {
     oldFile.seek(0);
     int oldVersion = oldFile.readInt();
     if (oldVersion < LAST_PRE_UPGRADE_LAYOUT_VERSION) return false;
   } finally {
     oldLock.release();
     oldFile.close();
   }
   return true;
 }
Ejemplo n.º 30
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));
    }
  }