예제 #1
0
        /*
         * Finalize the block pool storage by deleting <BP>/previous directory
         * that holds the snapshot.
         */
        /// <exception cref="System.IO.IOException"/>
        internal virtual void DoFinalize(FilePath dnCurDir)
        {
            FilePath bpRoot = GetBpRoot(blockpoolID, dnCurDir);

            Storage.StorageDirectory bpSd = new Storage.StorageDirectory(bpRoot);
            // block pool level previous directory
            FilePath prevDir = bpSd.GetPreviousDir();

            if (!prevDir.Exists())
            {
                return;
            }
            // already finalized
            string dataDirPath = bpSd.GetRoot().GetCanonicalPath();

            Log.Info("Finalizing upgrade for storage directory " + dataDirPath + ".\n   cur LV = "
                     + this.GetLayoutVersion() + "; cur CTime = " + this.GetCTime());
            System.Diagnostics.Debug.Assert(bpSd.GetCurrentDir().Exists(), "Current directory must exist."
                                            );
            // rename previous to finalized.tmp
            FilePath tmpDir = bpSd.GetFinalizedTmp();

            Rename(prevDir, tmpDir);
            // delete finalized.tmp dir in a separate thread
            new Daemon(new _Runnable_618(tmpDir, dataDirPath)).Start();
        }
예제 #2
0
        /// <summary>Upgrade to any release after 0.22 (0.22 included) release e.g.</summary>
        /// <remarks>
        /// Upgrade to any release after 0.22 (0.22 included) release e.g. 0.22 =&gt; 0.23
        /// Upgrade procedure is as follows:
        /// <ol>
        /// <li>If <SD>/current/<bpid>/previous exists then delete it</li>
        /// <li>Rename <SD>/current/<bpid>/current to
        /// <SD>/current/bpid/current/previous.tmp</li>
        /// <li>Create new <SD>current/<bpid>/current directory</li>
        /// <ol>
        /// <li>Hard links for block files are created from previous.tmp to current</li>
        /// <li>Save new version file in current directory</li>
        /// </ol>
        /// <li>Rename previous.tmp to previous</li> </ol>
        /// </remarks>
        /// <param name="bpSd">storage directory <SD>/current/<bpid></param>
        /// <param name="nsInfo">Namespace Info from the namenode</param>
        /// <exception cref="System.IO.IOException">on error</exception>
        internal virtual void DoUpgrade(DataNode datanode, Storage.StorageDirectory bpSd,
                                        NamespaceInfo nsInfo)
        {
            // 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.DatanodeLayoutVersion + "; new CTime = " + nsInfo.GetCTime());
            // get <SD>/previous directory
            string dnRoot = GetDataNodeStorageRoot(bpSd.GetRoot().GetCanonicalPath());

            Storage.StorageDirectory dnSdStorage = new Storage.StorageDirectory(new FilePath(
                                                                                    dnRoot));
            FilePath dnPrevDir = dnSdStorage.GetPreviousDir();

            // If <SD>/previous directory exists delete it
            if (dnPrevDir.Exists())
            {
                DeleteDir(dnPrevDir);
            }
            FilePath bpCurDir  = bpSd.GetCurrentDir();
            FilePath bpPrevDir = bpSd.GetPreviousDir();

            System.Diagnostics.Debug.Assert(bpCurDir.Exists(), "BP level current directory must exist."
                                            );
            CleanupDetachDir(new FilePath(bpCurDir, DataStorage.StorageDirDetached));
            // 1. Delete <SD>/current/<bpid>/previous dir before upgrading
            if (bpPrevDir.Exists())
            {
                DeleteDir(bpPrevDir);
            }
            FilePath bpTmpDir = bpSd.GetPreviousTmp();

            System.Diagnostics.Debug.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.DatanodeLayoutVersion;
            System.Diagnostics.Debug.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"
                     );
        }
예제 #3
0
        /* Flag if there is at least one storage dir that doesn't contain the newest
         * fstime */
        /* Flag set false if there are any "previous" directories found */
        // Track the name and edits dir with the latest times
        /// <exception cref="System.IO.IOException"/>
        internal override void InspectDirectory(Storage.StorageDirectory sd)
        {
            // Was the file just formatted?
            if (!sd.GetVersionFile().Exists())
            {
                hasOutOfDateStorageDirs = true;
                return;
            }
            bool imageExists = false;
            bool editsExists = false;

            // Determine if sd is image, edits or both
            if (sd.GetStorageDirType().IsOfType(NNStorage.NameNodeDirType.Image))
            {
                imageExists = NNStorage.GetStorageFile(sd, NNStorage.NameNodeFile.Image).Exists();
                imageDirs.AddItem(sd.GetRoot().GetCanonicalPath());
            }
            if (sd.GetStorageDirType().IsOfType(NNStorage.NameNodeDirType.Edits))
            {
                editsExists = NNStorage.GetStorageFile(sd, NNStorage.NameNodeFile.Edits).Exists();
                editsDirs.AddItem(sd.GetRoot().GetCanonicalPath());
            }
            long checkpointTime = ReadCheckpointTime(sd);

            checkpointTimes.AddItem(checkpointTime);
            if (sd.GetStorageDirType().IsOfType(NNStorage.NameNodeDirType.Image) && (latestNameCheckpointTime
                                                                                     < checkpointTime) && imageExists)
            {
                latestNameCheckpointTime = checkpointTime;
                latestNameSD             = sd;
            }
            if (sd.GetStorageDirType().IsOfType(NNStorage.NameNodeDirType.Edits) && (latestEditsCheckpointTime
                                                                                     < checkpointTime) && editsExists)
            {
                latestEditsCheckpointTime = checkpointTime;
                latestEditsSD             = sd;
            }
            // check that we have a valid, non-default checkpointTime
            if (checkpointTime <= 0L)
            {
                hasOutOfDateStorageDirs = true;
            }
            // set finalized flag
            isUpgradeFinalized = isUpgradeFinalized && !sd.GetPreviousDir().Exists();
        }
예제 #4
0
        /// <summary>
        /// Rename the existing current dir to previous.tmp, and create a new empty
        /// current dir.
        /// </summary>
        /// <exception cref="System.IO.IOException"/>
        public static void RenameCurToTmp(Storage.StorageDirectory sd)
        {
            FilePath curDir  = sd.GetCurrentDir();
            FilePath prevDir = sd.GetPreviousDir();
            FilePath tmpDir  = sd.GetPreviousTmp();

            Preconditions.CheckState(curDir.Exists(), "Current directory must exist for preupgrade."
                                     );
            Preconditions.CheckState(!prevDir.Exists(), "Previous directory must not exist for preupgrade."
                                     );
            Preconditions.CheckState(!tmpDir.Exists(), "Previous.tmp directory must not exist for preupgrade."
                                     + "Consider restarting for recovery.");
            // rename current to tmp
            NNStorage.Rename(curDir, tmpDir);
            if (!curDir.Mkdir())
            {
                throw new IOException("Cannot create directory " + curDir);
            }
        }
예제 #5
0
        /*
         * Roll back to old snapshot at the block pool level
         * If previous directory exists:
         * <ol>
         * <li>Rename <SD>/current/<bpid>/current to removed.tmp</li>
         * <li>Rename * <SD>/current/<bpid>/previous to current</li>
         * <li>Remove removed.tmp</li>
         * </ol>
         *
         * Do nothing if previous directory does not exist.
         * @param bpSd Block pool storage directory at <SD>/current/<bpid>
         */
        /// <exception cref="System.IO.IOException"/>
        internal virtual void DoRollback(Storage.StorageDirectory bpSd, NamespaceInfo nsInfo
                                         )
        {
            FilePath prevDir = bpSd.GetPreviousDir();

            // regular startup if previous dir does not exist
            if (!prevDir.Exists())
            {
                return;
            }
            // read attributes out of the VERSION file of previous directory
            Org.Apache.Hadoop.Hdfs.Server.Datanode.BlockPoolSliceStorage prevInfo = new Org.Apache.Hadoop.Hdfs.Server.Datanode.BlockPoolSliceStorage
                                                                                        ();
            prevInfo.ReadPreviousVersionProperties(bpSd);
            // We allow rollback to a state, which is either consistent with
            // the namespace state or can be further upgraded to it.
            // In another word, we can only roll back when ( storedLV >= software LV)
            // && ( DN.previousCTime <= NN.ctime)
            if (!(prevInfo.GetLayoutVersion() >= HdfsConstants.DatanodeLayoutVersion && prevInfo
                  .GetCTime() <= nsInfo.GetCTime()))
            {
                // cannot rollback
                throw new InconsistentFSStateException(bpSd.GetRoot(), "Cannot rollback to a newer state.\nDatanode previous state: LV = "
                                                       + prevInfo.GetLayoutVersion() + " CTime = " + prevInfo.GetCTime() + " is newer than the namespace state: LV = "
                                                       + HdfsConstants.DatanodeLayoutVersion + " CTime = " + nsInfo.GetCTime());
            }
            Log.Info("Rolling back storage directory " + bpSd.GetRoot() + ".\n   target LV = "
                     + nsInfo.GetLayoutVersion() + "; target CTime = " + nsInfo.GetCTime());
            FilePath tmpDir = bpSd.GetRemovedTmp();

            System.Diagnostics.Debug.Assert(!tmpDir.Exists(), "removed.tmp directory must not exist."
                                            );
            // 1. rename current to tmp
            FilePath curDir = bpSd.GetCurrentDir();

            System.Diagnostics.Debug.Assert(curDir.Exists(), "Current directory must exist.");
            Rename(curDir, tmpDir);
            // 2. rename previous to current
            Rename(prevDir, curDir);
            // 3. delete removed.tmp dir
            DeleteDir(tmpDir);
            Log.Info("Rollback of " + bpSd.GetRoot() + " is complete");
        }
예제 #6
0
        /// <summary>Finalize the upgrade.</summary>
        /// <remarks>
        /// Finalize the upgrade. The previous dir, if any, will be renamed and
        /// removed. After this is completed, rollback is no longer allowed.
        /// </remarks>
        /// <param name="sd">the storage directory to finalize</param>
        /// <exception cref="System.IO.IOException">in the event of error</exception>
        internal static void DoFinalize(Storage.StorageDirectory sd)
        {
            FilePath prevDir = sd.GetPreviousDir();

            if (!prevDir.Exists())
            {
                // already discarded
                Log.Info("Directory " + prevDir + " does not exist.");
                Log.Info("Finalize upgrade for " + sd.GetRoot() + " is not required.");
                return;
            }
            Log.Info("Finalizing upgrade of storage directory " + sd.GetRoot());
            Preconditions.CheckState(sd.GetCurrentDir().Exists(), "Current directory must exist."
                                     );
            FilePath tmpDir = sd.GetFinalizedTmp();

            // rename previous to tmp and remove
            NNStorage.Rename(prevDir, tmpDir);
            NNStorage.DeleteDir(tmpDir);
            Log.Info("Finalize upgrade for " + sd.GetRoot() + " is complete.");
        }
예제 #7
0
 /// <summary>Perform the upgrade of the storage dir to the given storage info.</summary>
 /// <remarks>
 /// Perform the upgrade of the storage dir to the given storage info. The new
 /// storage info is written into the current directory, and the previous.tmp
 /// directory is renamed to previous.
 /// </remarks>
 /// <param name="sd">the storage directory to upgrade</param>
 /// <param name="storage">info about the new upgraded versions.</param>
 /// <exception cref="System.IO.IOException">in the event of error</exception>
 public static void DoUpgrade(Storage.StorageDirectory sd, Storage storage)
 {
     Log.Info("Performing upgrade of storage directory " + sd.GetRoot());
     try
     {
         // Write the version file, since saveFsImage only makes the
         // fsimage_<txid>, and the directory is otherwise empty.
         storage.WriteProperties(sd);
         FilePath prevDir = sd.GetPreviousDir();
         FilePath tmpDir  = sd.GetPreviousTmp();
         Preconditions.CheckState(!prevDir.Exists(), "previous directory must not exist for upgrade."
                                  );
         Preconditions.CheckState(tmpDir.Exists(), "previous.tmp directory must exist for upgrade."
                                  );
         // rename tmp to previous
         NNStorage.Rename(tmpDir, prevDir);
     }
     catch (IOException ioe)
     {
         Log.Error("Unable to rename temp to previous for " + sd.GetRoot(), ioe);
         throw;
     }
 }
예제 #8
0
        /// <summary>
        /// Return true if this storage dir can roll back to the previous storage
        /// state, false otherwise.
        /// </summary>
        /// <remarks>
        /// Return true if this storage dir can roll back to the previous storage
        /// state, false otherwise. The NN will refuse to run the rollback operation
        /// unless at least one JM or fsimage storage directory can roll back.
        /// </remarks>
        /// <param name="storage">the storage info for the current state</param>
        /// <param name="prevStorage">the storage info for the previous (unupgraded) state</param>
        /// <param name="targetLayoutVersion">the layout version we intend to roll back to</param>
        /// <returns>true if this JM can roll back, false otherwise.</returns>
        /// <exception cref="System.IO.IOException">in the event of error</exception>
        internal static bool CanRollBack(Storage.StorageDirectory sd, StorageInfo storage
                                         , StorageInfo prevStorage, int targetLayoutVersion)
        {
            FilePath prevDir = sd.GetPreviousDir();

            if (!prevDir.Exists())
            {
                // use current directory then
                Log.Info("Storage directory " + sd.GetRoot() + " does not contain previous fs state."
                         );
                // read and verify consistency with other directories
                storage.ReadProperties(sd);
                return(false);
            }
            // read and verify consistency of the prev dir
            prevStorage.ReadPreviousVersionProperties(sd);
            if (prevStorage.GetLayoutVersion() != targetLayoutVersion)
            {
                throw new IOException("Cannot rollback to storage version " + prevStorage.GetLayoutVersion
                                          () + " using this version of the NameNode, which uses storage version " + targetLayoutVersion
                                      + ". " + "Please use the previous version of HDFS to perform the rollback.");
            }
            return(true);
        }
예제 #9
0
        /// <summary>Perform rollback of the storage dir to the previous state.</summary>
        /// <remarks>
        /// Perform rollback of the storage dir to the previous state. The existing
        /// current dir is removed, and the previous dir is renamed to current.
        /// </remarks>
        /// <param name="sd">the storage directory to roll back.</param>
        /// <exception cref="System.IO.IOException">in the event of error</exception>
        internal static void DoRollBack(Storage.StorageDirectory sd)
        {
            FilePath prevDir = sd.GetPreviousDir();

            if (!prevDir.Exists())
            {
                return;
            }
            FilePath tmpDir = sd.GetRemovedTmp();

            Preconditions.CheckState(!tmpDir.Exists(), "removed.tmp directory must not exist for rollback."
                                     + "Consider restarting for recovery.");
            // rename current to tmp
            FilePath curDir = sd.GetCurrentDir();

            Preconditions.CheckState(curDir.Exists(), "Current directory must exist for rollback."
                                     );
            NNStorage.Rename(curDir, tmpDir);
            // rename previous to current
            NNStorage.Rename(prevDir, curDir);
            // delete tmp dir
            NNStorage.DeleteDir(tmpDir);
            Log.Info("Rollback of " + sd.GetRoot() + " is complete.");
        }
예제 #10
0
 /// <summary>
 /// Analyze whether a transition of the BP state is required and
 /// perform it if necessary.
 /// </summary>
 /// <remarks>
 /// Analyze whether a transition of the BP state is required and
 /// perform it if necessary.
 /// <br />
 /// Rollback if previousLV &gt;= LAYOUT_VERSION && prevCTime &lt;= namenode.cTime.
 /// Upgrade if this.LV &gt; LAYOUT_VERSION || this.cTime &lt; namenode.cTime Regular
 /// startup if this.LV = LAYOUT_VERSION && this.cTime = namenode.cTime
 /// </remarks>
 /// <param name="sd">storage directory <SD>/current/<bpid></param>
 /// <param name="nsInfo">namespace info</param>
 /// <param name="startOpt">startup option</param>
 /// <exception cref="System.IO.IOException"/>
 private void DoTransition(DataNode datanode, Storage.StorageDirectory sd, NamespaceInfo
                           nsInfo, HdfsServerConstants.StartupOption startOpt)
 {
     if (startOpt == HdfsServerConstants.StartupOption.Rollback && sd.GetPreviousDir()
         .Exists())
     {
         Preconditions.CheckState(!GetTrashRootDir(sd).Exists(), sd.GetPreviousDir() + " and "
                                  + GetTrashRootDir(sd) + " should not " + " both be present.");
         DoRollback(sd, nsInfo);
     }
     else
     {
         // rollback if applicable
         if (startOpt == HdfsServerConstants.StartupOption.Rollback && !sd.GetPreviousDir(
                 ).Exists())
         {
             // Restore all the files in the trash. The restored files are retained
             // during rolling upgrade rollback. They are deleted during rolling
             // upgrade downgrade.
             int restored = RestoreBlockFilesFromTrash(GetTrashRootDir(sd));
             Log.Info("Restored " + restored + " block files from trash.");
         }
     }
     ReadProperties(sd);
     CheckVersionUpgradable(this.layoutVersion);
     System.Diagnostics.Debug.Assert(this.layoutVersion >= HdfsConstants.DatanodeLayoutVersion
                                     , "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.DatanodeLayoutVersion && this.cTime == nsInfo
         .GetCTime())
     {
         return;
     }
     // regular startup
     if (this.layoutVersion > HdfsConstants.DatanodeLayoutVersion)
     {
         int restored = RestoreBlockFilesFromTrash(GetTrashRootDir(sd));
         Log.Info("Restored " + restored + " block files from trash " + "before the layout upgrade. These blocks will be moved to "
                  + "the previous directory during the upgrade");
     }
     if (this.layoutVersion > HdfsConstants.DatanodeLayoutVersion || this.cTime < nsInfo
         .GetCTime())
     {
         DoUpgrade(datanode, 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());
 }
예제 #11
0
        /// <exception cref="System.IO.IOException"/>
        internal override void InspectDirectory(Storage.StorageDirectory sd)
        {
            // Was the directory just formatted?
            if (!sd.GetVersionFile().Exists())
            {
                Log.Info("No version file in " + sd.GetRoot());
                needToSave |= true;
                return;
            }
            // Check for a seen_txid file, which marks a minimum transaction ID that
            // must be included in our load plan.
            try
            {
                maxSeenTxId = Math.Max(maxSeenTxId, NNStorage.ReadTransactionIdFile(sd));
            }
            catch (IOException ioe)
            {
                Log.Warn("Unable to determine the max transaction ID seen by " + sd, ioe);
                return;
            }
            FilePath currentDir = sd.GetCurrentDir();

            FilePath[] filesInStorage;
            try
            {
                filesInStorage = FileUtil.ListFiles(currentDir);
            }
            catch (IOException ioe)
            {
                Log.Warn("Unable to inspect storage directory " + currentDir, ioe);
                return;
            }
            foreach (FilePath f in filesInStorage)
            {
                Log.Debug("Checking file " + f);
                string name = f.GetName();
                // Check for fsimage_*
                Matcher imageMatch = this.MatchPattern(name);
                if (imageMatch != null)
                {
                    if (sd.GetStorageDirType().IsOfType(NNStorage.NameNodeDirType.Image))
                    {
                        try
                        {
                            long txid = long.Parse(imageMatch.Group(1));
                            foundImages.AddItem(new FSImageStorageInspector.FSImageFile(sd, f, txid));
                        }
                        catch (FormatException)
                        {
                            Log.Error("Image file " + f + " has improperly formatted " + "transaction ID");
                        }
                    }
                    else
                    {
                        // skip
                        Log.Warn("Found image file at " + f + " but storage directory is " + "not configured to contain images."
                                 );
                    }
                }
            }
            // set finalized flag
            isUpgradeFinalized = isUpgradeFinalized && !sd.GetPreviousDir().Exists();
        }