/// <summary>Find an edits file spanning the given transaction ID range.</summary> /// <remarks> /// Find an edits file spanning the given transaction ID range. /// If no such file exists, an exception is thrown. /// </remarks> /// <exception cref="System.IO.IOException"/> internal virtual FilePath FindFinalizedEditsFile(long startTxId, long endTxId) { FilePath ret = new FilePath(sd.GetCurrentDir(), NNStorage.GetFinalizedEditsFileName (startTxId, endTxId)); if (!ret.Exists()) { throw new IOException("No edits file for range " + startTxId + "-" + endTxId); } return(ret); }
/// <summary>Check whether the path is a valid DataNode data directory.</summary> private static void CheckDir(FilePath dataDir) { Storage.StorageDirectory sd = new Storage.StorageDirectory(dataDir); NUnit.Framework.Assert.IsTrue(sd.GetRoot().IsDirectory()); NUnit.Framework.Assert.IsTrue(sd.GetCurrentDir().IsDirectory()); NUnit.Framework.Assert.IsTrue(sd.GetVersionFile().IsFile()); }
/* * 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(); }
/// <summary>Check whether the root is a valid BlockPoolSlice storage.</summary> private static void CheckDir(FilePath root, string bpid) { Storage.StorageDirectory sd = new Storage.StorageDirectory(root); FilePath bpRoot = new FilePath(sd.GetCurrentDir(), bpid); Storage.StorageDirectory bpSd = new Storage.StorageDirectory(bpRoot); NUnit.Framework.Assert.IsTrue(bpSd.GetRoot().IsDirectory()); NUnit.Framework.Assert.IsTrue(bpSd.GetCurrentDir().IsDirectory()); NUnit.Framework.Assert.IsTrue(bpSd.GetVersionFile().IsFile()); }
/// <returns> /// the latest edits log, finalized or otherwise, from the given /// storage directory. /// </returns> /// <exception cref="System.IO.IOException"/> public static FileJournalManager.EditLogFile FindLatestEditsLog(Storage.StorageDirectory sd) { FilePath currentDir = sd.GetCurrentDir(); IList <FileJournalManager.EditLogFile> foundEditLogs = Lists.NewArrayList(FileJournalManager .MatchEditLogs(currentDir)); return(Sharpen.Collections.Max(foundEditLogs, FileJournalManager.EditLogFile.CompareByStartTxid )); }
/// <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 => 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" ); }
/// <summary>Format a block pool slice storage.</summary> /// <param name="bpSdir">the block pool storage</param> /// <param name="nsInfo">the name space info</param> /// <exception cref="System.IO.IOException">Signals that an I/O exception has occurred. /// </exception> private void Format(Storage.StorageDirectory bpSdir, NamespaceInfo nsInfo) { Log.Info("Formatting block pool " + blockpoolID + " directory " + bpSdir.GetCurrentDir ()); bpSdir.ClearDirectory(); // create directory this.layoutVersion = HdfsConstants.DatanodeLayoutVersion; this.cTime = nsInfo.GetCTime(); this.namespaceID = nsInfo.GetNamespaceID(); this.blockpoolID = nsInfo.GetBlockPoolID(); WriteProperties(bpSdir); }
/// <summary> /// Ensure that the current/ directory exists in all storage /// directories /// </summary> /// <exception cref="System.IO.IOException"/> internal virtual void EnsureCurrentDirExists() { for (IEnumerator <Storage.StorageDirectory> it = storage.DirIterator(); it.HasNext ();) { Storage.StorageDirectory sd = it.Next(); FilePath curDir = sd.GetCurrentDir(); if (!curDir.Exists() && !curDir.Mkdirs()) { throw new IOException("Could not create directory " + curDir); } } }
/// <exception cref="System.IO.IOException"/> public virtual void PurgeLogsOlderThan(long minTxIdToKeep) { Log.Info("Purging logs older than " + minTxIdToKeep); FilePath[] files = FileUtil.ListFiles(sd.GetCurrentDir()); IList <FileJournalManager.EditLogFile> editLogs = MatchEditLogs(files, true); foreach (FileJournalManager.EditLogFile log in editLogs) { if (log.GetFirstTxId() < minTxIdToKeep && log.GetLastTxId() < minTxIdToKeep) { purger.PurgeLog(log); } } }
/// <exception cref="System.IO.IOException"/> private string GetClusterId(Configuration config) { // see if cluster id not empty. ICollection <URI> dirsToFormat = FSNamesystem.GetNamespaceDirs(config); IList <URI> editsToFormat = FSNamesystem.GetNamespaceEditsDirs(config); FSImage fsImage = new FSImage(config, dirsToFormat, editsToFormat); IEnumerator <Storage.StorageDirectory> sdit = fsImage.GetStorage().DirIterator(NNStorage.NameNodeDirType .Image); Storage.StorageDirectory sd = sdit.Next(); Properties props = Storage.ReadPropertiesFile(sd.GetVersionFile()); string cid = props.GetProperty("clusterID"); Log.Info("successfully formated : sd=" + sd.GetCurrentDir() + ";cid=" + cid); return(cid); }
/// <summary> /// Perform any steps that must succeed across all storage dirs/JournalManagers /// involved in an upgrade before proceeding onto the actual upgrade stage. /// </summary> /// <remarks> /// Perform any steps that must succeed across all storage dirs/JournalManagers /// involved in an upgrade before proceeding onto the actual upgrade stage. If /// a call to any JM's or local storage dir's doPreUpgrade method fails, then /// doUpgrade will not be called for any JM. The existing current dir is /// renamed to previous.tmp, and then a new, empty current dir is created. /// </remarks> /// <param name="conf"> /// configuration for creating /// <see cref="EditLogFileOutputStream"/> /// </param> /// <param name="sd">the storage directory to perform the pre-upgrade procedure.</param> /// <exception cref="System.IO.IOException">in the event of error</exception> internal static void DoPreUpgrade(Configuration conf, Storage.StorageDirectory sd ) { Log.Info("Starting upgrade of storage directory " + sd.GetRoot()); // rename current to tmp RenameCurToTmp(sd); FilePath curDir = sd.GetCurrentDir(); FilePath tmpDir = sd.GetPreviousTmp(); IList <string> fileNameList = IOUtils.ListDirectory(tmpDir, new _FilenameFilter_121 (tmpDir)); foreach (string s in fileNameList) { FilePath prevFile = new FilePath(tmpDir, s); FilePath newFile = new FilePath(curDir, prevFile.GetName()); Files.CreateLink(newFile.ToPath(), prevFile.ToPath()); } }
/// <exception cref="System.IO.IOException"/> public virtual void PurgeLogsOlderThan(long minTxIdToKeep) { IEnumerator <Storage.StorageDirectory> iter = storage.DirIterator(); while (iter.HasNext()) { Storage.StorageDirectory dir = iter.Next(); IList <FileJournalManager.EditLogFile> editFiles = FileJournalManager.MatchEditLogs (dir.GetCurrentDir()); foreach (FileJournalManager.EditLogFile f in editFiles) { if (f.GetLastTxId() < minTxIdToKeep) { purger.PurgeLog(f); } } } }
/// <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); } }
/* * 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"); }
/// <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."); }
public virtual void SelectInputStreams(ICollection <EditLogInputStream> streams, long fromTxId, bool inProgressOk) { IEnumerator <Storage.StorageDirectory> iter = storage.DirIterator(); while (iter.HasNext()) { Storage.StorageDirectory dir = iter.Next(); IList <FileJournalManager.EditLogFile> editFiles; try { editFiles = FileJournalManager.MatchEditLogs(dir.GetCurrentDir()); } catch (IOException ioe) { throw new RuntimeException(ioe); } FileJournalManager.AddStreamsToCollectionFromFiles(editFiles, streams, fromTxId, inProgressOk); } }
/// <exception cref="System.IO.IOException"/> internal virtual void DeleteTempEdits() { FilenameFilter filter = new _FilenameFilter_1021(); IEnumerator <Storage.StorageDirectory> it = storage.DirIterator(NNStorage.NameNodeDirType .Edits); for (; it.HasNext();) { Storage.StorageDirectory dir = it.Next(); FilePath[] tempEdits = dir.GetCurrentDir().ListFiles(filter); if (tempEdits != null) { foreach (FilePath t in tempEdits) { bool success = t.Delete(); if (!success) { Log.Warn("Failed to delete temporary edits file: " + t.GetAbsolutePath()); } } } } }
/// <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."); }
/// <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(); }