You are viewing a plain text version of this content. The canonical link for it is here.
Posted to hdfs-commits@hadoop.apache.org by ji...@apache.org on 2014/03/24 22:08:51 UTC
svn commit: r1581067 [2/3] - in
/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs: ./
dev-support/
src/contrib/bkjournal/src/main/java/org/apache/hadoop/contrib/bkjournal/
src/contrib/bkjournal/src/test/java/org/apache/hadoop/contrib/bkj...
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSImage.java Mon Mar 24 21:08:50 2014
@@ -181,7 +181,8 @@ public class FSImage implements Closeabl
* @return true if the image needs to be saved or false otherwise
*/
boolean recoverTransitionRead(StartupOption startOpt, FSNamesystem target,
- MetaRecoveryContext recovery) throws IOException {
+ MetaRecoveryContext recovery)
+ throws IOException {
assert startOpt != StartupOption.FORMAT :
"NameNode formatting should be performed before reading the image";
@@ -260,8 +261,8 @@ public class FSImage implements Closeabl
doImportCheckpoint(target);
return false; // import checkpoint saved image already
case ROLLBACK:
- doRollback();
- break;
+ throw new AssertionError("Rollback is now a standalone command, "
+ + "NameNode should not be starting with this option.");
case REGULAR:
default:
// just load the image
@@ -280,17 +281,15 @@ public class FSImage implements Closeabl
private boolean recoverStorageDirs(StartupOption startOpt,
Map<StorageDirectory, StorageState> dataDirStates) throws IOException {
boolean isFormatted = false;
+ // This loop needs to be over all storage dirs, even shared dirs, to make
+ // sure that we properly examine their state, but we make sure we don't
+ // mutate the shared dir below in the actual loop.
for (Iterator<StorageDirectory> it =
storage.dirIterator(); it.hasNext();) {
StorageDirectory sd = it.next();
StorageState curState;
try {
curState = sd.analyzeStorage(startOpt, storage);
- String nameserviceId = DFSUtil.getNamenodeNameServiceId(conf);
- if (curState != StorageState.NORMAL && HAUtil.isHAEnabled(conf, nameserviceId)) {
- throw new IOException("Cannot start an HA namenode with name dirs " +
- "that need recovery. Dir: " + sd + " state: " + curState);
- }
// sd is locked but not opened
switch(curState) {
case NON_EXISTENT:
@@ -302,7 +301,7 @@ public class FSImage implements Closeabl
case NORMAL:
break;
default: // recovery is possible
- sd.doRecover(curState);
+ sd.doRecover(curState);
}
if (curState != StorageState.NOT_FORMATTED
&& startOpt != StartupOption.ROLLBACK) {
@@ -327,7 +326,7 @@ public class FSImage implements Closeabl
void checkUpgrade(FSNamesystem target) throws IOException {
// Upgrade or rolling upgrade is allowed only if there are
// no previous fs states in any of the directories
- for (Iterator<StorageDirectory> it = storage.dirIterator(); it.hasNext();) {
+ for (Iterator<StorageDirectory> it = storage.dirIterator(false); it.hasNext();) {
StorageDirectory sd = it.next();
if (sd.getPreviousDir().exists())
throw new InconsistentFSStateException(sd.getRoot(),
@@ -356,7 +355,7 @@ public class FSImage implements Closeabl
checkUpgrade(target);
// load the latest image
- this.loadFSImage(target, null, null);
+ this.loadFSImage(target, StartupOption.UPGRADE, null);
// Do upgrade for each directory
target.checkRollingUpgrade("upgrade namenode");
@@ -368,28 +367,17 @@ public class FSImage implements Closeabl
List<StorageDirectory> errorSDs =
Collections.synchronizedList(new ArrayList<StorageDirectory>());
- for (Iterator<StorageDirectory> it = storage.dirIterator(); it.hasNext();) {
+ assert !editLog.isSegmentOpen() : "Edits log must not be open.";
+ LOG.info("Starting upgrade of local storage directories."
+ + "\n old LV = " + oldLV
+ + "; old CTime = " + oldCTime
+ + ".\n new LV = " + storage.getLayoutVersion()
+ + "; new CTime = " + storage.getCTime());
+ // Do upgrade for each directory
+ for (Iterator<StorageDirectory> it = storage.dirIterator(false); it.hasNext();) {
StorageDirectory sd = it.next();
- LOG.info("Starting upgrade of image directory " + sd.getRoot()
- + ".\n old LV = " + oldLV
- + "; old CTime = " + oldCTime
- + ".\n new LV = " + storage.getLayoutVersion()
- + "; new CTime = " + storage.getCTime());
try {
- File curDir = sd.getCurrentDir();
- File prevDir = sd.getPreviousDir();
- File tmpDir = sd.getPreviousTmp();
- assert curDir.exists() : "Current directory must exist.";
- assert !prevDir.exists() : "previous directory must not exist.";
- assert !tmpDir.exists() : "previous.tmp directory must not exist.";
- assert !editLog.isSegmentOpen() : "Edits log must not be open.";
-
- // rename current to tmp
- NNStorage.rename(curDir, tmpDir);
-
- if (!curDir.mkdir()) {
- throw new IOException("Cannot create directory " + curDir);
- }
+ NNUpgradeUtil.doPreUpgrade(sd);
} catch (Exception e) {
LOG.error("Failed to move aside pre-upgrade storage " +
"in image directory " + sd.getRoot(), e);
@@ -397,41 +385,38 @@ public class FSImage implements Closeabl
continue;
}
}
+ if (target.isHaEnabled()) {
+ editLog.doPreUpgradeOfSharedLog();
+ }
storage.reportErrorsOnDirectories(errorSDs);
errorSDs.clear();
saveFSImageInAllDirs(target, editLog.getLastWrittenTxId());
- for (Iterator<StorageDirectory> it = storage.dirIterator(); it.hasNext();) {
+ for (Iterator<StorageDirectory> it = storage.dirIterator(false); it.hasNext();) {
StorageDirectory sd = it.next();
try {
- // Write the version file, since saveFsImage above only makes the
- // fsimage_<txid>, and the directory is otherwise empty.
- storage.writeProperties(sd);
-
- File prevDir = sd.getPreviousDir();
- File tmpDir = sd.getPreviousTmp();
- // rename tmp to previous
- NNStorage.rename(tmpDir, prevDir);
+ NNUpgradeUtil.doUpgrade(sd, storage);
} catch (IOException ioe) {
- LOG.error("Unable to rename temp to previous for " + sd.getRoot(), ioe);
errorSDs.add(sd);
continue;
}
- LOG.info("Upgrade of " + sd.getRoot() + " is complete.");
+ }
+ if (target.isHaEnabled()) {
+ editLog.doUpgradeOfSharedLog();
}
storage.reportErrorsOnDirectories(errorSDs);
-
+
isUpgradeFinalized = false;
if (!storage.getRemovedStorageDirs().isEmpty()) {
- //during upgrade, it's a fatal error to fail any storage directory
+ // during upgrade, it's a fatal error to fail any storage directory
throw new IOException("Upgrade failed in "
+ storage.getRemovedStorageDirs().size()
+ " storage directory(ies), previously logged.");
}
}
- private void doRollback() throws IOException {
+ void doRollback(FSNamesystem fsns) throws IOException {
// Rollback is allowed only if there is
// a previous fs states in at least one of the storage directories.
// Directories that don't have previous state do not rollback
@@ -439,85 +424,46 @@ public class FSImage implements Closeabl
FSImage prevState = new FSImage(conf);
try {
prevState.getStorage().layoutVersion = HdfsConstants.NAMENODE_LAYOUT_VERSION;
- for (Iterator<StorageDirectory> it = storage.dirIterator(); it.hasNext();) {
+ for (Iterator<StorageDirectory> it = storage.dirIterator(false); it.hasNext();) {
StorageDirectory sd = it.next();
- File 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);
+ if (!NNUpgradeUtil.canRollBack(sd, storage, prevState.getStorage(),
+ HdfsConstants.NAMENODE_LAYOUT_VERSION)) {
continue;
}
-
- // read and verify consistency of the prev dir
- prevState.getStorage().readPreviousVersionProperties(sd);
-
- if (prevState.getLayoutVersion() != HdfsConstants.NAMENODE_LAYOUT_VERSION) {
- throw new IOException(
- "Cannot rollback to storage version " +
- prevState.getLayoutVersion() +
- " using this version of the NameNode, which uses storage version " +
- HdfsConstants.NAMENODE_LAYOUT_VERSION + ". " +
- "Please use the previous version of HDFS to perform the rollback.");
- }
canRollback = true;
}
+
+ if (fsns.isHaEnabled()) {
+ // If HA is enabled, check if the shared log can be rolled back as well.
+ editLog.initJournalsForWrite();
+ canRollback |= editLog.canRollBackSharedLog(prevState.getStorage(),
+ HdfsConstants.NAMENODE_LAYOUT_VERSION);
+ }
+
if (!canRollback)
throw new IOException("Cannot rollback. None of the storage "
+ "directories contain previous fs state.");
-
+
// Now that we know all directories are going to be consistent
// Do rollback for each directory containing previous state
- for (Iterator<StorageDirectory> it = storage.dirIterator(); it.hasNext();) {
+ for (Iterator<StorageDirectory> it = storage.dirIterator(false); it.hasNext();) {
StorageDirectory sd = it.next();
- File prevDir = sd.getPreviousDir();
- if (!prevDir.exists())
- continue;
-
LOG.info("Rolling back storage directory " + sd.getRoot()
- + ".\n new LV = " + prevState.getStorage().getLayoutVersion()
- + "; new CTime = " + prevState.getStorage().getCTime());
- File tmpDir = sd.getRemovedTmp();
- assert !tmpDir.exists() : "removed.tmp directory must not exist.";
- // rename current to tmp
- File curDir = sd.getCurrentDir();
- assert curDir.exists() : "Current directory must exist.";
- 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.");
+ + ".\n new LV = " + prevState.getStorage().getLayoutVersion()
+ + "; new CTime = " + prevState.getStorage().getCTime());
+ NNUpgradeUtil.doRollBack(sd);
+ }
+ if (fsns.isHaEnabled()) {
+ // If HA is enabled, try to roll back the shared log as well.
+ editLog.doRollback();
}
+
isUpgradeFinalized = true;
} finally {
prevState.close();
}
}
- private void doFinalize(StorageDirectory sd) throws IOException {
- File 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 for storage directory "
- + sd.getRoot() + "."
- + (storage.getLayoutVersion()==0 ? "" :
- "\n cur LV = " + storage.getLayoutVersion()
- + "; cur CTime = " + storage.getCTime()));
- assert sd.getCurrentDir().exists() : "Current directory must exist.";
- final File tmpDir = sd.getFinalizedTmp();
- // rename previous to tmp and remove
- NNStorage.rename(prevDir, tmpDir);
- NNStorage.deleteDir(tmpDir);
- isUpgradeFinalized = true;
- LOG.info("Finalize upgrade for " + sd.getRoot()+ " is complete.");
- }
-
/**
* Load image from a checkpoint directory and save it into the current one.
* @param target the NameSystem to import into
@@ -561,12 +507,23 @@ public class FSImage implements Closeabl
saveNamespace(target);
getStorage().writeAll();
}
-
- void finalizeUpgrade() throws IOException {
- for (Iterator<StorageDirectory> it = storage.dirIterator(); it.hasNext();) {
+
+ void finalizeUpgrade(boolean finalizeEditLog) throws IOException {
+ LOG.info("Finalizing upgrade for local dirs. " +
+ (storage.getLayoutVersion() == 0 ? "" :
+ "\n cur LV = " + storage.getLayoutVersion()
+ + "; cur CTime = " + storage.getCTime()));
+ for (Iterator<StorageDirectory> it = storage.dirIterator(false); it.hasNext();) {
StorageDirectory sd = it.next();
- doFinalize(sd);
+ NNUpgradeUtil.doFinalize(sd);
}
+ if (finalizeEditLog) {
+ // We only do this in the case that HA is enabled and we're active. In any
+ // other case the NN will have done the upgrade of the edits directories
+ // already by virtue of the fact that they're local.
+ editLog.doFinalizeOfSharedLog();
+ }
+ isUpgradeFinalized = true;
}
boolean isUpgradeFinalized() {
@@ -763,18 +720,33 @@ public class FSImage implements Closeabl
}
}
- public void initEditLog(StartupOption startOpt) {
+ public void initEditLog(StartupOption startOpt) throws IOException {
Preconditions.checkState(getNamespaceID() != 0,
"Must know namespace ID before initting edit log");
String nameserviceId = DFSUtil.getNamenodeNameServiceId(conf);
- if (!HAUtil.isHAEnabled(conf, nameserviceId) ||
- (HAUtil.isHAEnabled(conf, nameserviceId) &&
- RollingUpgradeStartupOption.ROLLBACK.matches(startOpt))) {
- // If this NN is not HA or this NN is HA, but we're doing a rollback of
- // rolling upgrade so init the edit log for write.
+ if (!HAUtil.isHAEnabled(conf, nameserviceId)) {
+ // If this NN is not HA
editLog.initJournalsForWrite();
editLog.recoverUnclosedStreams();
+ } else if (HAUtil.isHAEnabled(conf, nameserviceId)
+ && (startOpt == StartupOption.UPGRADE
+ || RollingUpgradeStartupOption.ROLLBACK.matches(startOpt))) {
+ // This NN is HA, but we're doing an upgrade or a rollback of rolling
+ // upgrade so init the edit log for write.
+ editLog.initJournalsForWrite();
+ if (startOpt == StartupOption.UPGRADE) {
+ long sharedLogCTime = editLog.getSharedLogCTime();
+ if (this.storage.getCTime() < sharedLogCTime) {
+ throw new IOException("It looks like the shared log is already " +
+ "being upgraded but this NN has not been upgraded yet. You " +
+ "should restart this NameNode with the '" +
+ StartupOption.BOOTSTRAPSTANDBY.getName() + "' option to bring " +
+ "this NN in sync with the other.");
+ }
+ }
+ editLog.recoverUnclosedStreams();
} else {
+ // This NN is HA and we're not doing an upgrade.
editLog.initSharedJournalsForRead();
}
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java Mon Mar 24 21:08:50 2014
@@ -159,6 +159,8 @@ import org.apache.hadoop.hdfs.protocol.A
import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.CacheDirectiveEntry;
import org.apache.hadoop.hdfs.protocol.CacheDirectiveInfo;
+import org.apache.hadoop.hdfs.protocol.CachePoolEntry;
+import org.apache.hadoop.hdfs.protocol.CachePoolInfo;
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
import org.apache.hadoop.hdfs.protocol.DatanodeID;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
@@ -170,8 +172,6 @@ import org.apache.hadoop.hdfs.protocol.H
import org.apache.hadoop.hdfs.protocol.HdfsFileStatus;
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
-import org.apache.hadoop.hdfs.protocol.CachePoolEntry;
-import org.apache.hadoop.hdfs.protocol.CachePoolInfo;
import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
import org.apache.hadoop.hdfs.protocol.RecoveryInProgressException;
import org.apache.hadoop.hdfs.protocol.RollingUpgradeException;
@@ -556,6 +556,10 @@ public class FSNamesystem implements Nam
return leaseManager;
}
+ boolean isHaEnabled() {
+ return haEnabled;
+ }
+
/**
* Check the supplied configuration for correctness.
* @param conf Supplies the configuration to validate.
@@ -891,7 +895,7 @@ public class FSNamesystem implements Nam
}
// This will start a new log segment and write to the seen_txid file, so
// we shouldn't do it when coming up in standby state
- if (!haEnabled) {
+ if (!haEnabled || (haEnabled && startOpt == StartupOption.UPGRADE)) {
fsImage.openEditLogForWrite();
}
success = true;
@@ -1017,6 +1021,7 @@ public class FSNamesystem implements Nam
dir.fsImage.editLog.openForWrite();
}
+
if (haEnabled) {
// Renew all of the leases before becoming active.
// This is because, while we were in standby mode,
@@ -1052,14 +1057,17 @@ public class FSNamesystem implements Nam
initializedReplQueues = true;
}
+ private boolean inActiveState() {
+ return haContext != null &&
+ haContext.getState().getServiceState() == HAServiceState.ACTIVE;
+ }
+
/**
* @return Whether the namenode is transitioning to active state and is in the
* middle of the {@link #startActiveServices()}
*/
public boolean inTransitionToActive() {
- return haEnabled && haContext != null
- && haContext.getState().getServiceState() == HAServiceState.ACTIVE
- && startingActiveService;
+ return haEnabled && inActiveState() && startingActiveService;
}
private boolean shouldUseDelegationTokens() {
@@ -4587,11 +4595,11 @@ public class FSNamesystem implements Nam
void finalizeUpgrade() throws IOException {
checkSuperuserPrivilege();
- checkOperation(OperationCategory.WRITE);
+ checkOperation(OperationCategory.UNCHECKED);
writeLock();
try {
- checkOperation(OperationCategory.WRITE);
- getFSImage().finalizeUpgrade();
+ checkOperation(OperationCategory.UNCHECKED);
+ getFSImage().finalizeUpgrade(this.isHaEnabled() && inActiveState());
} finally {
writeUnlock();
}
@@ -7758,5 +7766,6 @@ public class FSNamesystem implements Nam
logger.addAppender(asyncAppender);
}
}
+
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FileJournalManager.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FileJournalManager.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FileJournalManager.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/FileJournalManager.java Mon Mar 24 21:08:50 2014
@@ -17,35 +17,37 @@
*/
package org.apache.hadoop.hdfs.server.namenode;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import java.io.File;
import java.io.IOException;
import java.util.Collection;
-import java.util.List;
-import java.util.Comparator;
import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileUtil;
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
+import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.NodeType;
+import org.apache.hadoop.hdfs.server.common.Storage;
import org.apache.hadoop.hdfs.server.common.Storage.StorageDirectory;
import org.apache.hadoop.hdfs.server.common.StorageErrorReporter;
-import org.apache.hadoop.hdfs.server.namenode.NNStorageRetentionManager.StoragePurger;
+import org.apache.hadoop.hdfs.server.common.StorageInfo;
import org.apache.hadoop.hdfs.server.namenode.FSEditLogLoader.EditLogValidation;
import org.apache.hadoop.hdfs.server.namenode.NNStorage.NameNodeFile;
+import org.apache.hadoop.hdfs.server.namenode.NNStorageRetentionManager.StoragePurger;
import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
import org.apache.hadoop.hdfs.server.protocol.RemoteEditLog;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Lists;
/**
* Journal manager for the common case of edits files being written
@@ -531,4 +533,49 @@ public class FileJournalManager implemen
public void discardSegments(long startTxid) throws IOException {
discardEditLogSegments(startTxid);
}
+
+ @Override
+ public void doPreUpgrade() throws IOException {
+ LOG.info("Starting upgrade of edits directory " + sd.getRoot());
+ try {
+ NNUpgradeUtil.doPreUpgrade(sd);
+ } catch (IOException ioe) {
+ LOG.error("Failed to move aside pre-upgrade storage " +
+ "in image directory " + sd.getRoot(), ioe);
+ throw ioe;
+ }
+ }
+
+ /**
+ * This method assumes that the fields of the {@link Storage} object have
+ * already been updated to the appropriate new values for the upgrade.
+ */
+ @Override
+ public void doUpgrade(Storage storage) throws IOException {
+ NNUpgradeUtil.doUpgrade(sd, storage);
+ }
+
+ @Override
+ public void doFinalize() throws IOException {
+ NNUpgradeUtil.doFinalize(sd);
+ }
+
+ @Override
+ public boolean canRollBack(StorageInfo storage, StorageInfo prevStorage,
+ int targetLayoutVersion) throws IOException {
+ return NNUpgradeUtil.canRollBack(sd, storage,
+ prevStorage, targetLayoutVersion);
+ }
+
+ @Override
+ public void doRollback() throws IOException {
+ NNUpgradeUtil.doRollBack(sd);
+ }
+
+ @Override
+ public long getJournalCTime() throws IOException {
+ StorageInfo sInfo = new StorageInfo((NodeType)null);
+ sInfo.readProperties(sd);
+ return sInfo.getCTime();
+ }
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalManager.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalManager.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalManager.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalManager.java Mon Mar 24 21:08:50 2014
@@ -22,7 +22,9 @@ import java.io.IOException;
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.hdfs.server.common.Storage;
import org.apache.hadoop.hdfs.server.common.Storage.FormatConfirmable;
+import org.apache.hadoop.hdfs.server.common.StorageInfo;
import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
/**
@@ -65,6 +67,54 @@ public interface JournalManager extends
* Recover segments which have not been finalized.
*/
void recoverUnfinalizedSegments() throws IOException;
+
+ /**
+ * Perform any steps that must succeed across all JournalManagers involved in
+ * an upgrade before proceeding onto the actual upgrade stage. If a call to
+ * any JM's doPreUpgrade method fails, then doUpgrade will not be called for
+ * any JM.
+ */
+ void doPreUpgrade() throws IOException;
+
+ /**
+ * Perform the actual upgrade of the JM. After this is completed, the NN can
+ * begin to use the new upgraded metadata. This metadata may later be either
+ * finalized or rolled back to the previous state.
+ *
+ * @param storage info about the new upgraded versions.
+ */
+ void doUpgrade(Storage storage) throws IOException;
+
+ /**
+ * Finalize the upgrade. JMs should purge any state that they had been keeping
+ * around during the upgrade process. After this is completed, rollback is no
+ * longer allowed.
+ */
+ void doFinalize() throws IOException;
+
+ /**
+ * Return true if this JM 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.
+ *
+ * @param storage the storage info for the current state
+ * @param prevStorage the storage info for the previous (unupgraded) state
+ * @param targetLayoutVersion the layout version we intend to roll back to
+ * @return true if this JM can roll back, false otherwise.
+ */
+ boolean canRollBack(StorageInfo storage, StorageInfo prevStorage,
+ int targetLayoutVersion) throws IOException;
+
+ /**
+ * Perform the rollback to the previous FS state. JMs which do not need to
+ * roll back their state should just return without error.
+ */
+ void doRollback() throws IOException;
+
+ /**
+ * @return the CTime of the journal manager.
+ */
+ long getJournalCTime() throws IOException;
/**
* Discard the segments whose first txid is >= the given txid.
@@ -93,4 +143,5 @@ public interface JournalManager extends
super(reason);
}
}
+
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalSet.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalSet.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalSet.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/JournalSet.java Mon Mar 24 21:08:50 2014
@@ -33,6 +33,8 @@ import java.util.concurrent.CopyOnWriteA
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.hdfs.server.common.Storage;
+import org.apache.hadoop.hdfs.server.common.StorageInfo;
import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
import org.apache.hadoop.hdfs.server.protocol.RemoteEditLog;
import org.apache.hadoop.hdfs.server.protocol.RemoteEditLogManifest;
@@ -78,11 +80,14 @@ public class JournalSet implements Journ
private final JournalManager journal;
private boolean disabled = false;
private EditLogOutputStream stream;
- private boolean required = false;
+ private final boolean required;
+ private final boolean shared;
- public JournalAndStream(JournalManager manager, boolean required) {
+ public JournalAndStream(JournalManager manager, boolean required,
+ boolean shared) {
this.journal = manager;
this.required = required;
+ this.shared = shared;
}
public void startLogSegment(long txId, int layoutVersion) throws IOException {
@@ -164,6 +169,10 @@ public class JournalSet implements Journ
public boolean isRequired() {
return required;
}
+
+ public boolean isShared() {
+ return shared;
+ }
}
// COW implementation is necessary since some users (eg the web ui) call
@@ -179,7 +188,7 @@ public class JournalSet implements Journ
@Override
public void format(NamespaceInfo nsInfo) throws IOException {
- // The iteration is done by FSEditLog itself
+ // The operation is done by FSEditLog itself
throw new UnsupportedOperationException();
}
@@ -539,9 +548,13 @@ public class JournalSet implements Journ
}
return jList;
}
-
+
void add(JournalManager j, boolean required) {
- JournalAndStream jas = new JournalAndStream(j, required);
+ add(j, required, false);
+ }
+
+ void add(JournalManager j, boolean required, boolean shared) {
+ JournalAndStream jas = new JournalAndStream(j, required, shared);
journals.add(jas);
}
@@ -663,4 +676,40 @@ public class JournalSet implements Journ
// This operation is handled by FSEditLog directly.
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void doPreUpgrade() throws IOException {
+ // This operation is handled by FSEditLog directly.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void doUpgrade(Storage storage) throws IOException {
+ // This operation is handled by FSEditLog directly.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void doFinalize() throws IOException {
+ // This operation is handled by FSEditLog directly.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean canRollBack(StorageInfo storage, StorageInfo prevStorage, int targetLayoutVersion) throws IOException {
+ // This operation is handled by FSEditLog directly.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void doRollback() throws IOException {
+ // This operation is handled by FSEditLog directly.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getJournalCTime() throws IOException {
+ // This operation is handled by FSEditLog directly.
+ throw new UnsupportedOperationException();
+ }
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNStorage.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNStorage.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNStorage.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNStorage.java Mon Mar 24 21:08:50 2014
@@ -301,7 +301,7 @@ public class NNStorage extends Storage i
if(dirName.getScheme().compareTo("file") == 0) {
this.addStorageDir(new StorageDirectory(new File(dirName.getPath()),
dirType,
- !sharedEditsDirs.contains(dirName))); // Don't lock the dir if it's shared.
+ sharedEditsDirs.contains(dirName))); // Don't lock the dir if it's shared.
}
}
@@ -312,7 +312,7 @@ public class NNStorage extends Storage i
// URI is of type file://
if(dirName.getScheme().compareTo("file") == 0)
this.addStorageDir(new StorageDirectory(new File(dirName.getPath()),
- NameNodeDirType.EDITS, !sharedEditsDirs.contains(dirName)));
+ NameNodeDirType.EDITS, sharedEditsDirs.contains(dirName)));
}
}
@@ -1007,7 +1007,7 @@ public class NNStorage extends Storage i
StringBuilder layoutVersions = new StringBuilder();
// First determine what range of layout versions we're going to inspect
- for (Iterator<StorageDirectory> it = dirIterator();
+ for (Iterator<StorageDirectory> it = dirIterator(false);
it.hasNext();) {
StorageDirectory sd = it.next();
if (!sd.getVersionFile().exists()) {
Added: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNUpgradeUtil.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNUpgradeUtil.java?rev=1581067&view=auto
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNUpgradeUtil.java (added)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NNUpgradeUtil.java Mon Mar 24 21:08:50 2014
@@ -0,0 +1,174 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hdfs.server.namenode;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hdfs.server.common.Storage;
+import org.apache.hadoop.hdfs.server.common.Storage.StorageDirectory;
+import org.apache.hadoop.hdfs.server.common.StorageInfo;
+
+abstract class NNUpgradeUtil {
+
+ private static final Log LOG = LogFactory.getLog(NNUpgradeUtil.class);
+
+ /**
+ * 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.
+ *
+ * @param storage the storage info for the current state
+ * @param prevStorage the storage info for the previous (unupgraded) state
+ * @param targetLayoutVersion the layout version we intend to roll back to
+ * @return true if this JM can roll back, false otherwise.
+ * @throws IOException in the event of error
+ */
+ static boolean canRollBack(StorageDirectory sd, StorageInfo storage,
+ StorageInfo prevStorage, int targetLayoutVersion) throws IOException {
+ File 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;
+ }
+
+ /**
+ * Finalize the upgrade. The previous dir, if any, will be renamed and
+ * removed. After this is completed, rollback is no longer allowed.
+ *
+ * @param sd the storage directory to finalize
+ * @throws IOException in the event of error
+ */
+ static void doFinalize(StorageDirectory sd) throws IOException {
+ File 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());
+ assert sd.getCurrentDir().exists() : "Current directory must exist.";
+ final File 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.");
+ }
+
+ /**
+ * 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.
+ *
+ * @param sd the storage directory to perform the pre-upgrade procedure.
+ * @throws IOException in the event of error
+ */
+ static void doPreUpgrade(StorageDirectory sd) throws IOException {
+ LOG.info("Starting upgrade of storage directory " + sd.getRoot());
+ File curDir = sd.getCurrentDir();
+ File prevDir = sd.getPreviousDir();
+ File tmpDir = sd.getPreviousTmp();
+ assert curDir.exists() : "Current directory must exist.";
+ assert !prevDir.exists() : "previous directory must not exist.";
+ assert !tmpDir.exists() : "previous.tmp directory must not exist.";
+
+ // rename current to tmp
+ NNStorage.rename(curDir, tmpDir);
+
+ if (!curDir.mkdir()) {
+ throw new IOException("Cannot create directory " + curDir);
+ }
+ }
+
+ /**
+ * 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.
+ *
+ * @param sd the storage directory to upgrade
+ * @param storage info about the new upgraded versions.
+ * @throws IOException in the event of error
+ */
+ static void doUpgrade(StorageDirectory sd, Storage storage) throws
+ IOException {
+ 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);
+
+ File prevDir = sd.getPreviousDir();
+ File tmpDir = sd.getPreviousTmp();
+ // rename tmp to previous
+ NNStorage.rename(tmpDir, prevDir);
+ } catch (IOException ioe) {
+ LOG.error("Unable to rename temp to previous for " + sd.getRoot(), ioe);
+ throw ioe;
+ }
+ }
+
+ /**
+ * Perform rollback of the storage dir to the previous state. The existing
+ * current dir is removed, and the previous dir is renamed to current.
+ *
+ * @param sd the storage directory to roll back.
+ * @throws IOException in the event of error
+ */
+ static void doRollBack(StorageDirectory sd)
+ throws IOException {
+ File prevDir = sd.getPreviousDir();
+ if (!prevDir.exists())
+ return;
+
+ File tmpDir = sd.getRemovedTmp();
+ assert !tmpDir.exists() : "removed.tmp directory must not exist.";
+ // rename current to tmp
+ File curDir = sd.getCurrentDir();
+ assert curDir.exists() : "Current directory must exist.";
+ 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.");
+ }
+
+}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/NameNode.java Mon Mar 24 21:08:50 2014
@@ -662,7 +662,7 @@ public class NameNode implements NameNod
String nsId = getNameServiceId(conf);
String namenodeId = HAUtil.getNameNodeId(conf, nsId);
this.haEnabled = HAUtil.isHAEnabled(conf, nsId);
- state = createHAState();
+ state = createHAState(getStartupOption(conf));
this.allowStaleStandbyReads = HAUtil.shouldAllowStandbyReads(conf);
this.haContext = createHAContext();
try {
@@ -684,8 +684,12 @@ public class NameNode implements NameNod
}
}
- protected HAState createHAState() {
- return !haEnabled ? ACTIVE_STATE : STANDBY_STATE;
+ protected HAState createHAState(StartupOption startOpt) {
+ if (!haEnabled || startOpt == StartupOption.UPGRADE) {
+ return ACTIVE_STATE;
+ } else {
+ return STANDBY_STATE;
+ }
}
protected HAContext createHAContext() {
@@ -1037,26 +1041,28 @@ public class NameNode implements NameNod
}
}
}
-
- private static boolean finalize(Configuration conf,
- boolean isConfirmationNeeded
- ) throws IOException {
+
+ @VisibleForTesting
+ public static boolean doRollback(Configuration conf,
+ boolean isConfirmationNeeded) throws IOException {
String nsId = DFSUtil.getNamenodeNameServiceId(conf);
String namenodeId = HAUtil.getNameNodeId(conf, nsId);
initializeGenericKeys(conf, nsId, namenodeId);
FSNamesystem nsys = new FSNamesystem(conf, new FSImage(conf));
System.err.print(
- "\"finalize\" will remove the previous state of the files system.\n"
- + "Recent upgrade will become permanent.\n"
- + "Rollback option will not be available anymore.\n");
+ "\"rollBack\" will remove the current state of the file system,\n"
+ + "returning you to the state prior to initiating your recent.\n"
+ + "upgrade. This action is permanent and cannot be undone. If you\n"
+ + "are performing a rollback in an HA environment, you should be\n"
+ + "certain that no NameNode process is running on any host.");
if (isConfirmationNeeded) {
- if (!confirmPrompt("Finalize filesystem state?")) {
- System.err.println("Finalize aborted.");
+ if (!confirmPrompt("Roll back file system state?")) {
+ System.err.println("Rollback aborted.");
return true;
}
}
- nsys.dir.fsImage.finalizeUpgrade();
+ nsys.dir.fsImage.doRollback(nsys);
return false;
}
@@ -1244,14 +1250,6 @@ public class NameNode implements NameNod
return null;
}
setStartupOption(conf, startOpt);
-
- if (HAUtil.isHAEnabled(conf, DFSUtil.getNamenodeNameServiceId(conf)) &&
- (startOpt == StartupOption.UPGRADE ||
- startOpt == StartupOption.ROLLBACK ||
- startOpt == StartupOption.FINALIZE)) {
- throw new HadoopIllegalArgumentException("Invalid startup option. " +
- "Cannot perform DFS upgrade with HA enabled.");
- }
switch (startOpt) {
case FORMAT: {
@@ -1267,10 +1265,17 @@ public class NameNode implements NameNod
return null;
}
case FINALIZE: {
- boolean aborted = finalize(conf, true);
- terminate(aborted ? 1 : 0);
+ System.err.println("Use of the argument '" + StartupOption.FINALIZE +
+ "' is no longer supported. To finalize an upgrade, start the NN " +
+ " and then run `hdfs dfsadmin -finalizeUpgrade'");
+ terminate(1);
return null; // avoid javac warning
}
+ case ROLLBACK: {
+ boolean aborted = doRollback(conf, true);
+ terminate(aborted ? 1 : 0);
+ return null; // avoid warning
+ }
case BOOTSTRAPSTANDBY: {
String toolArgs[] = Arrays.copyOfRange(argv, 1, argv.length);
int rc = BootstrapStandby.run(toolArgs, conf);
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/BootstrapStandby.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/BootstrapStandby.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/BootstrapStandby.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/ha/BootstrapStandby.java Mon Mar 24 21:08:50 2014
@@ -44,9 +44,9 @@ import org.apache.hadoop.hdfs.server.nam
import org.apache.hadoop.hdfs.server.namenode.FSImage;
import org.apache.hadoop.hdfs.server.namenode.FSNamesystem;
import org.apache.hadoop.hdfs.server.namenode.NNStorage;
+import org.apache.hadoop.hdfs.server.namenode.NNStorage.NameNodeFile;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.hadoop.hdfs.server.namenode.TransferFsImage;
-import org.apache.hadoop.hdfs.server.namenode.NNStorage.NameNodeFile;
import org.apache.hadoop.hdfs.server.protocol.NamenodeProtocol;
import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
import org.apache.hadoop.hdfs.tools.DFSHAAdmin;
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/DFSAdmin.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/DFSAdmin.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/DFSAdmin.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/tools/DFSAdmin.java Mon Mar 24 21:08:50 2014
@@ -21,6 +21,7 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.InetSocketAddress;
+import java.net.URI;
import java.net.URL;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
@@ -47,6 +48,7 @@ import org.apache.hadoop.hdfs.HAUtil;
import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.NameNodeProxies;
import org.apache.hadoop.hdfs.protocol.ClientDatanodeProtocol;
+import org.apache.hadoop.hdfs.protocol.ClientProtocol;
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
import org.apache.hadoop.hdfs.protocol.DatanodeLocalInfo;
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
@@ -871,7 +873,24 @@ public class DFSAdmin extends FsShell {
*/
public int finalizeUpgrade() throws IOException {
DistributedFileSystem dfs = getDFS();
- dfs.finalizeUpgrade();
+
+ Configuration dfsConf = dfs.getConf();
+ URI dfsUri = dfs.getUri();
+ boolean isHaEnabled = HAUtil.isLogicalUri(dfsConf, dfsUri);
+ if (isHaEnabled) {
+ // In the case of HA, run finalizeUpgrade for all NNs in this nameservice
+ String nsId = dfsUri.getHost();
+ List<ClientProtocol> namenodes =
+ HAUtil.getProxiesForAllNameNodesInNameservice(dfsConf, nsId);
+ if (!HAUtil.isAtLeastOneActive(namenodes)) {
+ throw new IOException("Cannot finalize with no NameNode active");
+ }
+ for (ClientProtocol haNn : namenodes) {
+ haNn.finalizeUpgrade();
+ }
+ } else {
+ dfs.finalizeUpgrade();
+ }
return 0;
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/QJournalProtocol.proto
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/QJournalProtocol.proto?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/QJournalProtocol.proto (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/main/proto/QJournalProtocol.proto Mon Mar 24 21:08:50 2014
@@ -146,6 +146,72 @@ message DiscardSegmentsResponseProto {
}
/**
+ * getJournalCTime()
+ */
+message GetJournalCTimeRequestProto {
+ required JournalIdProto jid = 1;
+}
+
+message GetJournalCTimeResponseProto {
+ required int64 resultCTime = 1;
+}
+
+/**
+ * doPreUpgrade()
+ */
+message DoPreUpgradeRequestProto {
+ required JournalIdProto jid = 1;
+}
+
+message DoPreUpgradeResponseProto {
+}
+
+/**
+ * doUpgrade()
+ */
+message DoUpgradeRequestProto {
+ required JournalIdProto jid = 1;
+ required StorageInfoProto sInfo = 2;
+}
+
+message DoUpgradeResponseProto {
+}
+
+/**
+ * doFinalize()
+ */
+message DoFinalizeRequestProto {
+ required JournalIdProto jid = 1;
+}
+
+message DoFinalizeResponseProto {
+}
+
+/**
+ * canRollBack()
+ */
+message CanRollBackRequestProto {
+ required JournalIdProto jid = 1;
+ required StorageInfoProto storage = 2;
+ required StorageInfoProto prevStorage = 3;
+ required int32 targetLayoutVersion = 4;
+}
+
+message CanRollBackResponseProto {
+ required bool canRollBack = 1;
+}
+
+/**
+ * doRollback()
+ */
+message DoRollbackRequestProto {
+ required JournalIdProto jid = 1;
+}
+
+message DoRollbackResponseProto {
+}
+
+/**
* getJournalState()
*/
message GetJournalStateRequestProto {
@@ -250,6 +316,18 @@ service QJournalProtocolService {
rpc discardSegments(DiscardSegmentsRequestProto) returns (DiscardSegmentsResponseProto);
+ rpc getJournalCTime(GetJournalCTimeRequestProto) returns (GetJournalCTimeResponseProto);
+
+ rpc doPreUpgrade(DoPreUpgradeRequestProto) returns (DoPreUpgradeResponseProto);
+
+ rpc doUpgrade(DoUpgradeRequestProto) returns (DoUpgradeResponseProto);
+
+ rpc doFinalize(DoFinalizeRequestProto) returns (DoFinalizeResponseProto);
+
+ rpc canRollBack(CanRollBackRequestProto) returns (CanRollBackResponseProto);
+
+ rpc doRollback(DoRollbackRequestProto) returns (DoRollbackResponseProto);
+
rpc getJournalState(GetJournalStateRequestProto) returns (GetJournalStateResponseProto);
rpc newEpoch(NewEpochRequestProto) returns (NewEpochResponseProto);
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/site/apt/HDFSHighAvailabilityWithQJM.apt.vm
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/site/apt/HDFSHighAvailabilityWithQJM.apt.vm?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/site/apt/HDFSHighAvailabilityWithQJM.apt.vm (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/site/apt/HDFSHighAvailabilityWithQJM.apt.vm Mon Mar 24 21:08:50 2014
@@ -763,3 +763,49 @@ digest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6O
Even if automatic failover is configured, you may initiate a manual failover
using the same <<<hdfs haadmin>>> command. It will perform a coordinated
failover.
+
+* HDFS Upgrade/Finalization/Rollback with HA Enabled
+
+ When moving between versions of HDFS, sometimes the newer software can simply
+ be installed and the cluster restarted. Sometimes, however, upgrading the
+ version of HDFS you're running may require changing on-disk data. In this case,
+ one must use the HDFS Upgrade/Finalize/Rollback facility after installing the
+ new software. This process is made more complex in an HA environment, since the
+ on-disk metadata that the NN relies upon is by definition distributed, both on
+ the two HA NNs in the pair, and on the JournalNodes in the case that QJM is
+ being used for the shared edits storage. This documentation section describes
+ the procedure to use the HDFS Upgrade/Finalize/Rollback facility in an HA setup.
+
+ <<To perform an HA upgrade>>, the operator must do the following:
+
+ [[1]] Shut down all of the NNs as normal, and install the newer software.
+
+ [[2]] Start one of the NNs with the <<<'-upgrade'>>> flag.
+
+ [[3]] On start, this NN will not enter the standby state as usual in an HA
+ setup. Rather, this NN will immediately enter the active state, perform an
+ upgrade of its local storage dirs, and also perform an upgrade of the shared
+ edit log.
+
+ [[4]] At this point the other NN in the HA pair will be out of sync with
+ the upgraded NN. In order to bring it back in sync and once again have a highly
+ available setup, you should re-bootstrap this NameNode by running the NN with
+ the <<<'-bootstrapStandby'>>> flag. It is an error to start this second NN with
+ the <<<'-upgrade'>>> flag.
+
+ Note that if at any time you want to restart the NameNodes before finalizing
+ or rolling back the upgrade, you should start the NNs as normal, i.e. without
+ any special startup flag.
+
+ <<To finalize an HA upgrade>>, the operator will use the <<<`hdfsadmin
+ dfsadmin -finalizeUpgrade'>>> command while the NNs are running and one of them
+ is active. The active NN at the time this happens will perform the finalization
+ of the shared log, and the NN whose local storage directories contain the
+ previous FS state will delete its local state.
+
+ <<To perform a rollback>> of an upgrade, both NNs should first be shut down.
+ The operator should run the roll back command on the NN where they initiated
+ the upgrade procedure, which will perform the rollback on the local dirs there,
+ as well as on the shared log, either NFS or on the JNs. Afterward, this NN
+ should be started and the operator should run <<<`-bootstrapStandby'>>> on the
+ other NN to bring the two NNs in sync with this rolled-back file system state.
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/MiniDFSCluster.java Mon Mar 24 21:08:50 2014
@@ -147,6 +147,7 @@ public class MiniDFSCluster {
private boolean enableManagedDfsDirsRedundancy = true;
private boolean manageDataDfsDirs = true;
private StartupOption option = null;
+ private StartupOption dnOption = null;
private String[] racks = null;
private String [] hosts = null;
private long [] simulatedCapacities = null;
@@ -242,6 +243,14 @@ public class MiniDFSCluster {
this.option = val;
return this;
}
+
+ /**
+ * Default: null
+ */
+ public Builder dnStartupOption(StartupOption val) {
+ this.dnOption = val;
+ return this;
+ }
/**
* Default: null
@@ -371,6 +380,7 @@ public class MiniDFSCluster {
builder.enableManagedDfsDirsRedundancy,
builder.manageDataDfsDirs,
builder.option,
+ builder.dnOption,
builder.racks,
builder.hosts,
builder.simulatedCapacities,
@@ -427,18 +437,24 @@ public class MiniDFSCluster {
/**
* Stores the information related to a namenode in the cluster
*/
- static class NameNodeInfo {
+ public static class NameNodeInfo {
final NameNode nameNode;
final Configuration conf;
final String nameserviceId;
final String nnId;
+ StartupOption startOpt;
NameNodeInfo(NameNode nn, String nameserviceId, String nnId,
- Configuration conf) {
+ StartupOption startOpt, Configuration conf) {
this.nameNode = nn;
this.nameserviceId = nameserviceId;
this.nnId = nnId;
+ this.startOpt = startOpt;
this.conf = conf;
}
+
+ public void setStartOpt(StartupOption startOpt) {
+ this.startOpt = startOpt;
+ }
}
/**
@@ -622,8 +638,8 @@ public class MiniDFSCluster {
long[] simulatedCapacities) throws IOException {
this.nameNodes = new NameNodeInfo[1]; // Single namenode in the cluster
initMiniDFSCluster(conf, numDataNodes, StorageType.DEFAULT, format,
- manageNameDfsDirs, true, true, manageDataDfsDirs,
- operation, racks, hosts,
+ manageNameDfsDirs, true, manageDataDfsDirs, manageDataDfsDirs,
+ operation, null, racks, hosts,
simulatedCapacities, null, true, false,
MiniDFSNNTopology.simpleSingleNN(nameNodePort, 0), true, false, false, null);
}
@@ -632,7 +648,8 @@ public class MiniDFSCluster {
Configuration conf,
int numDataNodes, StorageType storageType, boolean format, boolean manageNameDfsDirs,
boolean manageNameDfsSharedDirs, boolean enableManagedDfsDirsRedundancy,
- boolean manageDataDfsDirs, StartupOption operation, String[] racks,
+ boolean manageDataDfsDirs, StartupOption startOpt,
+ StartupOption dnStartOpt, String[] racks,
String[] hosts, long[] simulatedCapacities, String clusterId,
boolean waitSafeMode, boolean setupHostsFile,
MiniDFSNNTopology nnTopology, boolean checkExitOnShutdown,
@@ -685,7 +702,7 @@ public class MiniDFSCluster {
createNameNodesAndSetConf(
nnTopology, manageNameDfsDirs, manageNameDfsSharedDirs,
enableManagedDfsDirsRedundancy,
- format, operation, clusterId, conf);
+ format, startOpt, clusterId, conf);
} catch (IOException ioe) {
LOG.error("IOE creating namenodes. Permissions dump:\n" +
createPermissionsDiagnosisString(data_dir));
@@ -698,13 +715,14 @@ public class MiniDFSCluster {
}
}
- if (operation == StartupOption.RECOVER) {
+ if (startOpt == StartupOption.RECOVER) {
return;
}
// Start the DataNodes
startDataNodes(conf, numDataNodes, storageType, manageDataDfsDirs,
- operation, racks, hosts, simulatedCapacities, setupHostsFile,
+ dnStartOpt != null ? dnStartOpt : startOpt,
+ racks, hosts, simulatedCapacities, setupHostsFile,
checkDataNodeAddrConfig, checkDataNodeHostConfig, dnConfOverlays);
waitClusterUp();
//make sure ProxyUsers uses the latest conf
@@ -783,6 +801,8 @@ public class MiniDFSCluster {
if (manageNameDfsSharedDirs) {
URI sharedEditsUri = getSharedEditsDir(nnCounter, nnCounter+nnIds.size()-1);
conf.set(DFS_NAMENODE_SHARED_EDITS_DIR_KEY, sharedEditsUri.toString());
+ // Clean out the shared edits dir completely, including all subdirectories.
+ FileUtil.fullyDelete(new File(sharedEditsUri));
}
}
@@ -890,7 +910,8 @@ public class MiniDFSCluster {
URI srcDir = Lists.newArrayList(srcDirs).get(0);
FileSystem dstFS = FileSystem.getLocal(dstConf).getRaw();
for (URI dstDir : dstDirs) {
- Preconditions.checkArgument(!dstDir.equals(srcDir));
+ Preconditions.checkArgument(!dstDir.equals(srcDir),
+ "src and dst are the same: " + dstDir);
File dstDirF = new File(dstDir);
if (dstDirF.exists()) {
if (!FileUtil.fullyDelete(dstDirF)) {
@@ -924,6 +945,18 @@ public class MiniDFSCluster {
conf.set(key, "127.0.0.1:" + nnConf.getIpcPort());
}
+ private static String[] createArgs(StartupOption operation) {
+ if (operation == StartupOption.ROLLINGUPGRADE) {
+ return new String[]{operation.getName(),
+ operation.getRollingUpgradeStartupOption().name()};
+ }
+ String[] args = (operation == null ||
+ operation == StartupOption.FORMAT ||
+ operation == StartupOption.REGULAR) ?
+ new String[] {} : new String[] {operation.getName()};
+ return args;
+ }
+
private void createNameNode(int nnIndex, Configuration conf,
int numDataNodes, boolean format, StartupOption operation,
String clusterId, String nameserviceId,
@@ -938,10 +971,7 @@ public class MiniDFSCluster {
}
// Start the NameNode
- String[] args = (operation == null ||
- operation == StartupOption.FORMAT ||
- operation == StartupOption.REGULAR) ?
- new String[] {} : new String[] {operation.getName()};
+ String[] args = createArgs(operation);
NameNode nn = NameNode.createNameNode(args, conf);
if (operation == StartupOption.RECOVER) {
return;
@@ -963,7 +993,7 @@ public class MiniDFSCluster {
DFSUtil.setGenericConf(conf, nameserviceId, nnId,
DFS_NAMENODE_HTTP_ADDRESS_KEY);
nameNodes[nnIndex] = new NameNodeInfo(nn, nameserviceId, nnId,
- new Configuration(conf));
+ operation, new Configuration(conf));
}
/**
@@ -1544,7 +1574,7 @@ public class MiniDFSCluster {
nn.stop();
nn.join();
Configuration conf = nameNodes[nnIndex].conf;
- nameNodes[nnIndex] = new NameNodeInfo(null, null, null, conf);
+ nameNodes[nnIndex] = new NameNodeInfo(null, null, null, null, conf);
}
}
@@ -1590,10 +1620,17 @@ public class MiniDFSCluster {
String... args) throws IOException {
String nameserviceId = nameNodes[nnIndex].nameserviceId;
String nnId = nameNodes[nnIndex].nnId;
+ StartupOption startOpt = nameNodes[nnIndex].startOpt;
Configuration conf = nameNodes[nnIndex].conf;
shutdownNameNode(nnIndex);
+ if (args.length != 0) {
+ startOpt = null;
+ } else {
+ args = createArgs(startOpt);
+ }
NameNode nn = NameNode.createNameNode(args, conf);
- nameNodes[nnIndex] = new NameNodeInfo(nn, nameserviceId, nnId, conf);
+ nameNodes[nnIndex] = new NameNodeInfo(nn, nameserviceId, nnId, startOpt,
+ conf);
if (waitActive) {
waitClusterUp();
LOG.info("Restarted the namenode");
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSRollback.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSRollback.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSRollback.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSRollback.java Mon Mar 24 21:08:50 2014
@@ -35,6 +35,7 @@ import org.apache.hadoop.hdfs.server.com
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.StartupOption;
import org.apache.hadoop.hdfs.server.common.StorageInfo;
import org.apache.hadoop.hdfs.server.namenode.FSImageTestUtil;
+import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.hadoop.util.StringUtils;
import org.junit.After;
import org.junit.Test;
@@ -98,10 +99,10 @@ public class TestDFSRollback {
* Attempts to start a NameNode with the given operation. Starting
* the NameNode should throw an exception.
*/
- void startNameNodeShouldFail(StartupOption operation, String searchString) {
+ void startNameNodeShouldFail(String searchString) {
try {
+ NameNode.doRollback(conf, false);
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
- .startupOption(operation)
.format(false)
.manageDataDfsDirs(false)
.manageNameDfsDirs(false)
@@ -150,24 +151,19 @@ public class TestDFSRollback {
log("Normal NameNode rollback", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "previous");
- cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
- .format(false)
- .manageDataDfsDirs(false)
- .manageNameDfsDirs(false)
- .startupOption(StartupOption.ROLLBACK)
- .build();
+ NameNode.doRollback(conf, false);
checkResult(NAME_NODE, nameNodeDirs);
- cluster.shutdown();
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
log("Normal DataNode rollback", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "previous");
+ NameNode.doRollback(conf, false);
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
.format(false)
.manageDataDfsDirs(false)
.manageNameDfsDirs(false)
- .startupOption(StartupOption.ROLLBACK)
+ .dnStartupOption(StartupOption.ROLLBACK)
.build();
UpgradeUtilities.createDataNodeStorageDirs(dataNodeDirs, "current");
UpgradeUtilities.createDataNodeStorageDirs(dataNodeDirs, "previous");
@@ -180,11 +176,12 @@ public class TestDFSRollback {
log("Normal BlockPool rollback", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "previous");
+ NameNode.doRollback(conf, false);
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
.format(false)
.manageDataDfsDirs(false)
.manageNameDfsDirs(false)
- .startupOption(StartupOption.ROLLBACK)
+ .dnStartupOption(StartupOption.ROLLBACK)
.build();
UpgradeUtilities.createDataNodeStorageDirs(dataNodeDirs, "current");
UpgradeUtilities.createBlockPoolStorageDirs(dataNodeDirs, "current",
@@ -219,10 +216,10 @@ public class TestDFSRollback {
cluster.shutdown();
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
UpgradeUtilities.createEmptyDirs(dataNodeDirs);
-
+
log("NameNode rollback without existing previous dir", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
- startNameNodeShouldFail(StartupOption.ROLLBACK,
+ startNameNodeShouldFail(
"None of the storage directories contain previous fs state");
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
@@ -239,15 +236,16 @@ public class TestDFSRollback {
cluster.shutdown();
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
UpgradeUtilities.createEmptyDirs(dataNodeDirs);
-
+
log("DataNode rollback with future stored layout version in previous", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "previous");
+ NameNode.doRollback(conf, false);
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
.format(false)
.manageDataDfsDirs(false)
.manageNameDfsDirs(false)
- .startupOption(StartupOption.ROLLBACK)
+ .dnStartupOption(StartupOption.ROLLBACK)
.build();
UpgradeUtilities.createDataNodeStorageDirs(dataNodeDirs, "current");
baseDirs = UpgradeUtilities.createDataNodeStorageDirs(dataNodeDirs, "previous");
@@ -269,11 +267,12 @@ public class TestDFSRollback {
log("DataNode rollback with newer fsscTime in previous", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "previous");
+ NameNode.doRollback(conf, false);
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(0)
.format(false)
.manageDataDfsDirs(false)
.manageNameDfsDirs(false)
- .startupOption(StartupOption.ROLLBACK)
+ .dnStartupOption(StartupOption.ROLLBACK)
.build();
UpgradeUtilities.createDataNodeStorageDirs(dataNodeDirs, "current");
@@ -291,21 +290,19 @@ public class TestDFSRollback {
cluster.shutdown();
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
UpgradeUtilities.createEmptyDirs(dataNodeDirs);
-
+
log("NameNode rollback with no edits file", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
baseDirs = UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "previous");
deleteMatchingFiles(baseDirs, "edits.*");
- startNameNodeShouldFail(StartupOption.ROLLBACK,
- "Gap in transactions");
+ startNameNodeShouldFail("Gap in transactions");
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
log("NameNode rollback with no image file", numDirs);
UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "current");
baseDirs = UpgradeUtilities.createNameNodeStorageDirs(nameNodeDirs, "previous");
deleteMatchingFiles(baseDirs, "fsimage_.*");
- startNameNodeShouldFail(StartupOption.ROLLBACK,
- "No valid image files found");
+ startNameNodeShouldFail("No valid image files found");
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
log("NameNode rollback with corrupt version file", numDirs);
@@ -317,8 +314,7 @@ public class TestDFSRollback {
"layoutVersion".getBytes(Charsets.UTF_8),
"xxxxxxxxxxxxx".getBytes(Charsets.UTF_8));
}
- startNameNodeShouldFail(StartupOption.ROLLBACK,
- "file VERSION has layoutVersion missing");
+ startNameNodeShouldFail("file VERSION has layoutVersion missing");
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
@@ -332,8 +328,7 @@ public class TestDFSRollback {
UpgradeUtilities.createNameNodeVersionFile(conf, baseDirs,
storageInfo, UpgradeUtilities.getCurrentBlockPoolID(cluster));
- startNameNodeShouldFail(StartupOption.ROLLBACK,
- "Cannot rollback to storage version 1 using this version");
+ startNameNodeShouldFail("Cannot rollback to storage version 1 using this version");
UpgradeUtilities.createEmptyDirs(nameNodeDirs);
} // end numDir loop
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDFSUtil.java Mon Mar 24 21:08:50 2014
@@ -61,6 +61,7 @@ import org.apache.hadoop.hdfs.server.nam
import org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.test.GenericTestUtils;
import org.apache.hadoop.util.Shell;
import org.junit.Assume;
import org.junit.Before;
@@ -758,4 +759,37 @@ public class TestDFSUtil {
assertEquals(4*24*60*60*1000l, DFSUtil.parseRelativeTime("4d"));
assertEquals(999*24*60*60*1000l, DFSUtil.parseRelativeTime("999d"));
}
+
+ @Test
+ public void testAssertAllResultsEqual() {
+ checkAllResults(new Long[]{}, true);
+ checkAllResults(new Long[]{1l}, true);
+ checkAllResults(new Long[]{1l, 1l}, true);
+ checkAllResults(new Long[]{1l, 1l, 1l}, true);
+ checkAllResults(new Long[]{new Long(1), new Long(1)}, true);
+ checkAllResults(new Long[]{null, null, null}, true);
+
+ checkAllResults(new Long[]{1l, 2l}, false);
+ checkAllResults(new Long[]{2l, 1l}, false);
+ checkAllResults(new Long[]{1l, 2l, 1l}, false);
+ checkAllResults(new Long[]{2l, 1l, 1l}, false);
+ checkAllResults(new Long[]{1l, 1l, 2l}, false);
+ checkAllResults(new Long[]{1l, null}, false);
+ checkAllResults(new Long[]{null, 1l}, false);
+ checkAllResults(new Long[]{1l, null, 1l}, false);
+ }
+
+ private static void checkAllResults(Long[] toCheck, boolean shouldSucceed) {
+ if (shouldSucceed) {
+ DFSUtil.assertAllResultsEqual(Arrays.asList(toCheck));
+ } else {
+ try {
+ DFSUtil.assertAllResultsEqual(Arrays.asList(toCheck));
+ fail("Should not have succeeded with input: " +
+ Arrays.toString(toCheck));
+ } catch (AssertionError ae) {
+ GenericTestUtils.assertExceptionContains("Not all elements match", ae);
+ }
+ }
+ }
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestRollingUpgrade.java Mon Mar 24 21:08:50 2014
@@ -204,7 +204,7 @@ public class TestRollingUpgrade {
.format(false)
.manageNameDfsDirs(false)
.build();
- DistributedFileSystem dfs2 = cluster2.getFileSystem();
+ final DistributedFileSystem dfs2 = cluster2.getFileSystem();
// Check that cluster2 sees the edits made on cluster1
Assert.assertTrue(dfs2.exists(foo));
@@ -243,7 +243,8 @@ public class TestRollingUpgrade {
Assert.assertEquals(info1.getStartTime(), finalize.getStartTime());
LOG.info("RESTART cluster 2 with regular startup option");
- cluster2.restartNameNode(StartupOption.REGULAR.getName());
+ cluster2.getNameNodeInfos()[0].setStartOpt(StartupOption.REGULAR);
+ cluster2.restartNameNode();
Assert.assertTrue(dfs2.exists(foo));
Assert.assertTrue(dfs2.exists(bar));
Assert.assertTrue(dfs2.exists(baz));
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniJournalCluster.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniJournalCluster.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniJournalCluster.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniJournalCluster.java Mon Mar 24 21:08:50 2014
@@ -167,8 +167,16 @@ public class MiniJournalCluster {
return new File(baseDir, "journalnode-" + idx).getAbsoluteFile();
}
+ public File getJournalDir(int idx, String jid) {
+ return new File(getStorageDir(idx), jid);
+ }
+
public File getCurrentDir(int idx, String jid) {
- return new File(new File(getStorageDir(idx), jid), "current");
+ return new File(getJournalDir(idx, jid), "current");
+ }
+
+ public File getPreviousDir(int idx, String jid) {
+ return new File(getJournalDir(idx, jid), "previous");
}
public JournalNode getJournalNode(int i) {
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniQJMHACluster.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniQJMHACluster.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniQJMHACluster.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/qjournal/MiniQJMHACluster.java Mon Mar 24 21:08:50 2014
@@ -29,6 +29,7 @@ import org.apache.hadoop.hdfs.DFSConfigK
import org.apache.hadoop.hdfs.DFSUtil;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.hdfs.MiniDFSNNTopology;
+import org.apache.hadoop.hdfs.server.common.HdfsServerConstants.StartupOption;
import org.apache.hadoop.hdfs.server.namenode.NameNode;
import org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider;
@@ -47,6 +48,7 @@ public class MiniQJMHACluster {
public static class Builder {
private final Configuration conf;
+ private StartupOption startOpt = null;
private final MiniDFSCluster.Builder dfsBuilder;
public Builder(Configuration conf) {
@@ -61,6 +63,10 @@ public class MiniQJMHACluster {
public MiniQJMHACluster build() throws IOException {
return new MiniQJMHACluster(this);
}
+
+ public void startupOption(StartupOption startOpt) {
+ this.startOpt = startOpt;
+ }
}
public static MiniDFSNNTopology createDefaultTopology() {
@@ -95,6 +101,9 @@ public class MiniQJMHACluster {
Configuration confNN0 = cluster.getConfiguration(0);
NameNode.initializeSharedEdits(confNN0, true);
+ cluster.getNameNodeInfos()[0].setStartOpt(builder.startOpt);
+ cluster.getNameNodeInfos()[1].setStartOpt(builder.startOpt);
+
// restart the cluster
cluster.restartNameNodes();
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestGenericJournalConf.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestGenericJournalConf.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestGenericJournalConf.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/TestGenericJournalConf.java Mon Mar 24 21:08:50 2014
@@ -17,21 +17,22 @@
*/
package org.apache.hadoop.hdfs.server.namenode;
-import static org.junit.Assert.fail;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.io.IOException;
import java.net.URI;
import java.util.Collection;
-import org.apache.hadoop.hdfs.server.common.Storage.FormatConfirmable;
-import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.MiniDFSCluster;
+import org.apache.hadoop.hdfs.server.common.Storage;
+import org.apache.hadoop.hdfs.server.common.StorageInfo;
+import org.apache.hadoop.hdfs.server.protocol.NamespaceInfo;
import org.junit.Test;
public class TestGenericJournalConf {
@@ -198,12 +199,58 @@ public class TestGenericJournalConf {
}
@Override
+ public void doPreUpgrade() throws IOException {}
+
+ @Override
+ public void doUpgrade(Storage storage) throws IOException {}
+
+ @Override
+ public void doFinalize() throws IOException {}
+
+ @Override
+ public boolean canRollBack(StorageInfo storage, StorageInfo prevStorage, int targetLayoutVersion)
+ throws IOException {
+ return false;
+ }
+
+ @Override
+ public void doRollback() throws IOException {}
+
+ @Override
public void discardSegments(long startTxId) throws IOException {}
+
+ @Override
+ public long getJournalCTime() throws IOException {
+ return -1;
+ }
}
public static class BadConstructorJournalManager extends DummyJournalManager {
public BadConstructorJournalManager() {
super(null, null, null);
}
+
+ @Override
+ public void doPreUpgrade() throws IOException {}
+
+ @Override
+ public void doUpgrade(Storage storage) throws IOException {}
+
+ @Override
+ public void doFinalize() throws IOException {}
+
+ @Override
+ public boolean canRollBack(StorageInfo storage, StorageInfo prevStorage, int targetLayoutVersion)
+ throws IOException {
+ return false;
+ }
+
+ @Override
+ public void doRollback() throws IOException {}
+
+ @Override
+ public long getJournalCTime() throws IOException {
+ return -1;
+ }
}
}
Modified: hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestBootstrapStandby.java
URL: http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestBootstrapStandby.java?rev=1581067&r1=1581066&r2=1581067&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestBootstrapStandby.java (original)
+++ hadoop/common/branches/branch-2/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/namenode/ha/TestBootstrapStandby.java Mon Mar 24 21:08:50 2014
@@ -91,7 +91,7 @@ public class TestBootstrapStandby {
fail("Did not throw");
} catch (IOException ioe) {
GenericTestUtils.assertExceptionContains(
- "Cannot start an HA namenode with name dirs that need recovery",
+ "storage directory does not exist or is not accessible",
ioe);
}