svn merge -c 1545322 merging from trunk to branch-2 to fix HDFS-5266. Datanode cannot roll back to previous layout version.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1545324 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c0bcf404d5
commit
204a17c736
|
@ -3675,6 +3675,8 @@ Release 0.23.10 - UNRELEASED
|
||||||
HDFS-4329. DFSShell issues with directories with spaces in name (Cristina
|
HDFS-4329. DFSShell issues with directories with spaces in name (Cristina
|
||||||
L. Abad via jeagles)
|
L. Abad via jeagles)
|
||||||
|
|
||||||
|
HDFS-5526. Datanode cannot roll back to previous layout version (kihwal)
|
||||||
|
|
||||||
Release 0.23.9 - 2013-07-08
|
Release 0.23.9 - 2013-07-08
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
|
|
@ -299,7 +299,16 @@ public class DataStorage extends Storage {
|
||||||
@Override
|
@Override
|
||||||
protected void setFieldsFromProperties(Properties props, StorageDirectory sd)
|
protected void setFieldsFromProperties(Properties props, StorageDirectory sd)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
setLayoutVersion(props, sd);
|
setFieldsFromProperties(props, sd, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setFieldsFromProperties(Properties props, StorageDirectory sd,
|
||||||
|
boolean overrideLayoutVersion, int toLayoutVersion) throws IOException {
|
||||||
|
if (overrideLayoutVersion) {
|
||||||
|
this.layoutVersion = toLayoutVersion;
|
||||||
|
} else {
|
||||||
|
setLayoutVersion(props, sd);
|
||||||
|
}
|
||||||
setcTime(props, sd);
|
setcTime(props, sd);
|
||||||
setStorageType(props, sd);
|
setStorageType(props, sd);
|
||||||
setClusterId(props, layoutVersion, sd);
|
setClusterId(props, layoutVersion, sd);
|
||||||
|
@ -347,13 +356,20 @@ public class DataStorage extends Storage {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Read VERSION file for rollback */
|
||||||
|
void readProperties(StorageDirectory sd, int rollbackLayoutVersion)
|
||||||
|
throws IOException {
|
||||||
|
Properties props = readPropertiesFile(sd.getVersionFile());
|
||||||
|
setFieldsFromProperties(props, sd, true, rollbackLayoutVersion);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analize which and whether a transition of the fs state is required
|
* Analize which and whether a transition of the fs state is required
|
||||||
* and perform it if necessary.
|
* and perform it if necessary.
|
||||||
*
|
*
|
||||||
* Rollback if previousLV >= LAYOUT_VERSION && prevCTime <= namenode.cTime
|
* Rollback if the rollback startup option was specified.
|
||||||
* Upgrade if this.LV > LAYOUT_VERSION || this.cTime < namenode.cTime
|
* Upgrade if this.LV > LAYOUT_VERSION
|
||||||
* Regular startup if this.LV = LAYOUT_VERSION && this.cTime = namenode.cTime
|
* Regular startup if this.LV = LAYOUT_VERSION
|
||||||
*
|
*
|
||||||
* @param datanode Datanode to which this storage belongs to
|
* @param datanode Datanode to which this storage belongs to
|
||||||
* @param sd storage directory
|
* @param sd storage directory
|
||||||
|
@ -393,25 +409,28 @@ public class DataStorage extends Storage {
|
||||||
+ nsInfo.getClusterID() + "; datanode clusterID = " + getClusterID());
|
+ nsInfo.getClusterID() + "; datanode clusterID = " + getClusterID());
|
||||||
}
|
}
|
||||||
|
|
||||||
// regular start up
|
// After addition of the federation feature, ctime check is only
|
||||||
if (this.layoutVersion == HdfsConstants.LAYOUT_VERSION
|
// meaningful at BlockPoolSliceStorage level.
|
||||||
&& this.cTime == nsInfo.getCTime())
|
|
||||||
|
// regular start up.
|
||||||
|
if (this.layoutVersion == HdfsConstants.LAYOUT_VERSION)
|
||||||
return; // regular startup
|
return; // regular startup
|
||||||
|
|
||||||
// do upgrade
|
// do upgrade
|
||||||
if (this.layoutVersion > HdfsConstants.LAYOUT_VERSION
|
if (this.layoutVersion > HdfsConstants.LAYOUT_VERSION) {
|
||||||
|| this.cTime < nsInfo.getCTime()) {
|
|
||||||
doUpgrade(sd, nsInfo); // upgrade
|
doUpgrade(sd, nsInfo); // upgrade
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// layoutVersion == LAYOUT_VERSION && this.cTime > nsInfo.cTime
|
// layoutVersion < LAYOUT_VERSION. I.e. stored layout version is newer
|
||||||
// must shutdown
|
// than the version supported by datanode. This should have been caught
|
||||||
throw new IOException("Datanode state: LV = " + this.getLayoutVersion()
|
// in readProperties(), even if rollback was not carried out or somehow
|
||||||
+ " CTime = " + this.getCTime()
|
// failed.
|
||||||
+ " is newer than the namespace state: LV = "
|
throw new IOException("BUG: The stored LV = " + this.getLayoutVersion()
|
||||||
+ nsInfo.getLayoutVersion()
|
+ " is newer than the supported LV = "
|
||||||
+ " CTime = " + nsInfo.getCTime());
|
+ HdfsConstants.LAYOUT_VERSION
|
||||||
|
+ " or name node LV = "
|
||||||
|
+ nsInfo.getLayoutVersion());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -437,8 +456,13 @@ public class DataStorage extends Storage {
|
||||||
* @throws IOException on error
|
* @throws IOException on error
|
||||||
*/
|
*/
|
||||||
void doUpgrade(StorageDirectory sd, NamespaceInfo nsInfo) throws IOException {
|
void doUpgrade(StorageDirectory sd, NamespaceInfo nsInfo) throws IOException {
|
||||||
|
// If the existing on-disk layout version supportes federation, simply
|
||||||
|
// update its layout version.
|
||||||
if (LayoutVersion.supports(Feature.FEDERATION, layoutVersion)) {
|
if (LayoutVersion.supports(Feature.FEDERATION, layoutVersion)) {
|
||||||
clusterID = nsInfo.getClusterID();
|
// The VERSION file is already read in. Override the layoutVersion
|
||||||
|
// field and overwrite the file.
|
||||||
|
LOG.info("Updating layout version from " + layoutVersion + " to "
|
||||||
|
+ nsInfo.getLayoutVersion() + " for storage " + sd.getRoot());
|
||||||
layoutVersion = nsInfo.getLayoutVersion();
|
layoutVersion = nsInfo.getLayoutVersion();
|
||||||
writeProperties(sd);
|
writeProperties(sd);
|
||||||
return;
|
return;
|
||||||
|
@ -523,15 +547,32 @@ public class DataStorage extends Storage {
|
||||||
* <li> Remove removed.tmp </li>
|
* <li> Remove removed.tmp </li>
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* Do nothing, if previous directory does not exist.
|
* If previous directory does not exist and the current version supports
|
||||||
|
* federation, perform a simple rollback of layout version. This does not
|
||||||
|
* involve saving/restoration of actual data.
|
||||||
*/
|
*/
|
||||||
void doRollback( StorageDirectory sd,
|
void doRollback( StorageDirectory sd,
|
||||||
NamespaceInfo nsInfo
|
NamespaceInfo nsInfo
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
File prevDir = sd.getPreviousDir();
|
File prevDir = sd.getPreviousDir();
|
||||||
// regular startup if previous dir does not exist
|
// This is a regular startup or a post-federation rollback
|
||||||
if (!prevDir.exists())
|
if (!prevDir.exists()) {
|
||||||
|
// The current datanode version supports federation and the layout
|
||||||
|
// version from namenode matches what the datanode supports. An invalid
|
||||||
|
// rollback may happen if namenode didn't rollback and datanode is
|
||||||
|
// running a wrong version. But this will be detected in block pool
|
||||||
|
// level and the invalid VERSION content will be overwritten when
|
||||||
|
// the error is corrected and rollback is retried.
|
||||||
|
if (LayoutVersion.supports(Feature.FEDERATION,
|
||||||
|
HdfsConstants.LAYOUT_VERSION) &&
|
||||||
|
HdfsConstants.LAYOUT_VERSION == nsInfo.getLayoutVersion()) {
|
||||||
|
readProperties(sd, nsInfo.getLayoutVersion());
|
||||||
|
writeProperties(sd);
|
||||||
|
LOG.info("Layout version rolled back to " +
|
||||||
|
nsInfo.getLayoutVersion() + " for storage " + sd.getRoot());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
DataStorage prevInfo = new DataStorage();
|
DataStorage prevInfo = new DataStorage();
|
||||||
prevInfo.readPreviousVersionProperties(sd);
|
prevInfo.readPreviousVersionProperties(sd);
|
||||||
|
|
||||||
|
|
|
@ -191,21 +191,25 @@ public class TestDFSRollback {
|
||||||
// Create a previous snapshot for the blockpool
|
// Create a previous snapshot for the blockpool
|
||||||
UpgradeUtilities.createBlockPoolStorageDirs(dataNodeDirs, "previous",
|
UpgradeUtilities.createBlockPoolStorageDirs(dataNodeDirs, "previous",
|
||||||
UpgradeUtilities.getCurrentBlockPoolID(cluster));
|
UpgradeUtilities.getCurrentBlockPoolID(cluster));
|
||||||
// Older LayoutVersion to make it rollback
|
// Put newer layout version in current.
|
||||||
storageInfo = new StorageInfo(
|
storageInfo = new StorageInfo(
|
||||||
UpgradeUtilities.getCurrentLayoutVersion()+1,
|
UpgradeUtilities.getCurrentLayoutVersion()-1,
|
||||||
UpgradeUtilities.getCurrentNamespaceID(cluster),
|
UpgradeUtilities.getCurrentNamespaceID(cluster),
|
||||||
UpgradeUtilities.getCurrentClusterID(cluster),
|
UpgradeUtilities.getCurrentClusterID(cluster),
|
||||||
UpgradeUtilities.getCurrentFsscTime(cluster));
|
UpgradeUtilities.getCurrentFsscTime(cluster));
|
||||||
// Create old VERSION file for each data dir
|
|
||||||
|
// Overwrite VERSION file in the current directory of
|
||||||
|
// volume directories and block pool slice directories
|
||||||
|
// with a layout version from future.
|
||||||
|
File[] dataCurrentDirs = new File[dataNodeDirs.length];
|
||||||
for (int i=0; i<dataNodeDirs.length; i++) {
|
for (int i=0; i<dataNodeDirs.length; i++) {
|
||||||
Path bpPrevPath = new Path(dataNodeDirs[i] + "/current/"
|
dataCurrentDirs[i] = new File((new Path(dataNodeDirs[i]
|
||||||
+ UpgradeUtilities.getCurrentBlockPoolID(cluster));
|
+ "/current")).toString());
|
||||||
UpgradeUtilities.createBlockPoolVersionFile(
|
|
||||||
new File(bpPrevPath.toString()),
|
|
||||||
storageInfo,
|
|
||||||
UpgradeUtilities.getCurrentBlockPoolID(cluster));
|
|
||||||
}
|
}
|
||||||
|
UpgradeUtilities.createDataNodeVersionFile(
|
||||||
|
dataCurrentDirs,
|
||||||
|
storageInfo,
|
||||||
|
UpgradeUtilities.getCurrentBlockPoolID(cluster));
|
||||||
|
|
||||||
cluster.startDataNodes(conf, 1, false, StartupOption.ROLLBACK, null);
|
cluster.startDataNodes(conf, 1, false, StartupOption.ROLLBACK, null);
|
||||||
assertTrue(cluster.isDataNodeUp());
|
assertTrue(cluster.isDataNodeUp());
|
||||||
|
|
Loading…
Reference in New Issue