HDFS-8578. On upgrade, Datanode should process all storage/data dirs in parallel. Contributed by vinayakumarb and szetszwo

This commit is contained in:
Tsz-Wo Nicholas Sze 2016-02-22 15:01:15 -08:00
parent a2fdfff02d
commit 66289a3bf4
4 changed files with 160 additions and 48 deletions

View File

@ -2840,6 +2840,9 @@ Release 2.7.3 - UNRELEASED
HDFS-4946. Allow preferLocalNode in BlockPlacementPolicyDefault to be HDFS-4946. Allow preferLocalNode in BlockPlacementPolicyDefault to be
configurable (James Kinley and Nathan Roberts via kihwal) configurable (James Kinley and Nathan Roberts via kihwal)
HDFS-8578. On upgrade, Datanode should process all storage/data dirs in
parallel. (vinayakumarb and szetszwo via szetszwo)
OPTIMIZATIONS OPTIMIZATIONS
BUG FIXES BUG FIXES

View File

@ -836,6 +836,9 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
"dfs.datanode.slow.io.warning.threshold.ms"; "dfs.datanode.slow.io.warning.threshold.ms";
public static final long DFS_DATANODE_SLOW_IO_WARNING_THRESHOLD_DEFAULT = 300; public static final long DFS_DATANODE_SLOW_IO_WARNING_THRESHOLD_DEFAULT = 300;
// Number of parallel threads to load multiple datanode volumes
public static final String DFS_DATANODE_PARALLEL_VOLUME_LOAD_THREADS_NUM_KEY =
"dfs.datanode.parallel.volumes.load.threads.num";
public static final String DFS_DATANODE_BLOCK_ID_LAYOUT_UPGRADE_THREADS_KEY = public static final String DFS_DATANODE_BLOCK_ID_LAYOUT_UPGRADE_THREADS_KEY =
"dfs.datanode.block.id.layout.upgrade.threads"; "dfs.datanode.block.id.layout.upgrade.threads";
public static final int DFS_DATANODE_BLOCK_ID_LAYOUT_UPGRADE_THREADS = 12; public static final int DFS_DATANODE_BLOCK_ID_LAYOUT_UPGRADE_THREADS = 12;

View File

@ -27,6 +27,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -145,7 +146,8 @@ public class BlockPoolSliceStorage extends Storage {
* @throws IOException * @throws IOException
*/ */
private StorageDirectory loadStorageDirectory(NamespaceInfo nsInfo, private StorageDirectory loadStorageDirectory(NamespaceInfo nsInfo,
File dataDir, StartupOption startOpt, Configuration conf) File dataDir, StartupOption startOpt,
List<Callable<StorageDirectory>> callables, Configuration conf)
throws IOException { throws IOException {
StorageDirectory sd = new StorageDirectory(dataDir, null, true); StorageDirectory sd = new StorageDirectory(dataDir, null, true);
try { try {
@ -172,18 +174,16 @@ public class BlockPoolSliceStorage extends Storage {
// Each storage directory is treated individually. // Each storage directory is treated individually.
// During startup some of them can upgrade or roll back // During startup some of them can upgrade or roll back
// while others could be up-to-date for the regular startup. // while others could be up-to-date for the regular startup.
if (doTransition(sd, nsInfo, startOpt, conf)) { if (!doTransition(sd, nsInfo, startOpt, callables, conf)) {
return sd;
}
// 3. Check CTime and update successfully loaded storage.
if (getCTime() != nsInfo.getCTime()) { if (getCTime() != nsInfo.getCTime()) {
throw new IOException("Datanode CTime (=" + getCTime() throw new IOException("Datanode CTime (=" + getCTime()
+ ") is not equal to namenode CTime (=" + nsInfo.getCTime() + ")"); + ") is not equal to namenode CTime (=" + nsInfo.getCTime() + ")");
} }
// 3. Update successfully loaded storage.
setServiceLayoutVersion(getServiceLayoutVersion()); setServiceLayoutVersion(getServiceLayoutVersion());
writeProperties(sd); writeProperties(sd);
}
return sd; return sd;
} catch (IOException ioe) { } catch (IOException ioe) {
@ -208,7 +208,8 @@ public class BlockPoolSliceStorage extends Storage {
*/ */
List<StorageDirectory> loadBpStorageDirectories(NamespaceInfo nsInfo, List<StorageDirectory> loadBpStorageDirectories(NamespaceInfo nsInfo,
Collection<File> dataDirs, StartupOption startOpt, Collection<File> dataDirs, StartupOption startOpt,
Configuration conf) throws IOException { List<Callable<StorageDirectory>> callables, Configuration conf)
throws IOException {
List<StorageDirectory> succeedDirs = Lists.newArrayList(); List<StorageDirectory> succeedDirs = Lists.newArrayList();
try { try {
for (File dataDir : dataDirs) { for (File dataDir : dataDirs) {
@ -218,7 +219,7 @@ public class BlockPoolSliceStorage extends Storage {
"attempt to load an used block storage: " + dataDir); "attempt to load an used block storage: " + dataDir);
} }
final StorageDirectory sd = loadStorageDirectory( final StorageDirectory sd = loadStorageDirectory(
nsInfo, dataDir, startOpt, conf); nsInfo, dataDir, startOpt, callables, conf);
succeedDirs.add(sd); succeedDirs.add(sd);
} }
} catch (IOException e) { } catch (IOException e) {
@ -242,11 +243,12 @@ public class BlockPoolSliceStorage extends Storage {
* @throws IOException on error * @throws IOException on error
*/ */
List<StorageDirectory> recoverTransitionRead(NamespaceInfo nsInfo, List<StorageDirectory> recoverTransitionRead(NamespaceInfo nsInfo,
Collection<File> dataDirs, StartupOption startOpt, Configuration conf) Collection<File> dataDirs, StartupOption startOpt,
List<Callable<StorageDirectory>> callables, Configuration conf)
throws IOException { throws IOException {
LOG.info("Analyzing storage directories for bpid " + nsInfo.getBlockPoolID()); LOG.info("Analyzing storage directories for bpid " + nsInfo.getBlockPoolID());
final List<StorageDirectory> loaded = loadBpStorageDirectories( final List<StorageDirectory> loaded = loadBpStorageDirectories(
nsInfo, dataDirs, startOpt, conf); nsInfo, dataDirs, startOpt, callables, conf);
for (StorageDirectory sd : loaded) { for (StorageDirectory sd : loaded) {
addStorageDir(sd); addStorageDir(sd);
} }
@ -353,7 +355,8 @@ public class BlockPoolSliceStorage extends Storage {
* @return true if the new properties has been written. * @return true if the new properties has been written.
*/ */
private boolean doTransition(StorageDirectory sd, NamespaceInfo nsInfo, private boolean doTransition(StorageDirectory sd, NamespaceInfo nsInfo,
StartupOption startOpt, Configuration conf) throws IOException { StartupOption startOpt, List<Callable<StorageDirectory>> callables,
Configuration conf) throws IOException {
if (startOpt == StartupOption.ROLLBACK && sd.getPreviousDir().exists()) { if (startOpt == StartupOption.ROLLBACK && sd.getPreviousDir().exists()) {
Preconditions.checkState(!getTrashRootDir(sd).exists(), Preconditions.checkState(!getTrashRootDir(sd).exists(),
sd.getPreviousDir() + " and " + getTrashRootDir(sd) + " should not " + sd.getPreviousDir() + " and " + getTrashRootDir(sd) + " should not " +
@ -395,7 +398,7 @@ public class BlockPoolSliceStorage extends Storage {
} }
if (this.layoutVersion > HdfsServerConstants.DATANODE_LAYOUT_VERSION if (this.layoutVersion > HdfsServerConstants.DATANODE_LAYOUT_VERSION
|| this.cTime < nsInfo.getCTime()) { || this.cTime < nsInfo.getCTime()) {
doUpgrade(sd, nsInfo, conf); // upgrade doUpgrade(sd, nsInfo, callables, conf); // upgrade
return true; return true;
} }
// layoutVersion == LAYOUT_VERSION && this.cTime > nsInfo.cTime // layoutVersion == LAYOUT_VERSION && this.cTime > nsInfo.cTime
@ -425,7 +428,9 @@ public class BlockPoolSliceStorage extends Storage {
* @throws IOException on error * @throws IOException on error
*/ */
private void doUpgrade(final StorageDirectory bpSd, private void doUpgrade(final StorageDirectory bpSd,
final NamespaceInfo nsInfo, final Configuration conf) throws IOException { final NamespaceInfo nsInfo,
final List<Callable<StorageDirectory>> callables,
final Configuration conf) throws IOException {
// Upgrading is applicable only to release with federation or after // Upgrading is applicable only to release with federation or after
if (!DataNodeLayoutVersion.supports( if (!DataNodeLayoutVersion.supports(
LayoutVersion.Feature.FEDERATION, layoutVersion)) { LayoutVersion.Feature.FEDERATION, layoutVersion)) {
@ -463,10 +468,21 @@ public class BlockPoolSliceStorage extends Storage {
rename(bpCurDir, bpTmpDir); rename(bpCurDir, bpTmpDir);
final String name = "block pool " + blockpoolID + " at " + bpSd.getRoot(); final String name = "block pool " + blockpoolID + " at " + bpSd.getRoot();
doUgrade(name, bpSd, nsInfo, bpPrevDir, bpTmpDir, bpCurDir, oldLV, conf); if (callables == null) {
doUpgrade(name, bpSd, nsInfo, bpPrevDir, bpTmpDir, bpCurDir, oldLV, conf);
} else {
callables.add(new Callable<StorageDirectory>() {
@Override
public StorageDirectory call() throws Exception {
doUpgrade(name, bpSd, nsInfo, bpPrevDir, bpTmpDir, bpCurDir, oldLV,
conf);
return bpSd;
}
});
}
} }
private void doUgrade(String name, final StorageDirectory bpSd, private void doUpgrade(String name, final StorageDirectory bpSd,
NamespaceInfo nsInfo, final File bpPrevDir, final File bpTmpDir, NamespaceInfo nsInfo, final File bpPrevDir, final File bpTmpDir,
final File bpCurDir, final int oldLV, Configuration conf) final File bpCurDir, final int oldLV, Configuration conf)
throws IOException { throws IOException {

View File

@ -37,10 +37,12 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import org.apache.hadoop.HadoopIllegalArgumentException;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
@ -51,6 +53,7 @@ import org.apache.hadoop.fs.LocalFileSystem;
import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.DFSConfigKeys; import org.apache.hadoop.hdfs.DFSConfigKeys;
import org.apache.hadoop.hdfs.DFSUtilClient;
import org.apache.hadoop.hdfs.HdfsConfiguration; import org.apache.hadoop.hdfs.HdfsConfiguration;
import org.apache.hadoop.hdfs.protocol.Block; import org.apache.hadoop.hdfs.protocol.Block;
import org.apache.hadoop.hdfs.protocol.LayoutVersion; import org.apache.hadoop.hdfs.protocol.LayoutVersion;
@ -260,8 +263,8 @@ public class DataStorage extends Storage {
} }
private StorageDirectory loadStorageDirectory(DataNode datanode, private StorageDirectory loadStorageDirectory(DataNode datanode,
NamespaceInfo nsInfo, File dataDir, StartupOption startOpt) NamespaceInfo nsInfo, File dataDir, StartupOption startOpt,
throws IOException { List<Callable<StorageDirectory>> callables) throws IOException {
StorageDirectory sd = new StorageDirectory(dataDir, null, false); StorageDirectory sd = new StorageDirectory(dataDir, null, false);
try { try {
StorageState curState = sd.analyzeStorage(startOpt, this); StorageState curState = sd.analyzeStorage(startOpt, this);
@ -287,13 +290,12 @@ public class DataStorage extends Storage {
// Each storage directory is treated individually. // Each storage directory is treated individually.
// During startup some of them can upgrade or roll back // During startup some of them can upgrade or roll back
// while others could be up-to-date for the regular startup. // while others could be up-to-date for the regular startup.
if (doTransition(sd, nsInfo, startOpt, datanode.getConf())) { if (!doTransition(sd, nsInfo, startOpt, callables, datanode.getConf())) {
return sd;
}
// 3. Update successfully loaded storage. // 3. Update successfully loaded storage.
setServiceLayoutVersion(getServiceLayoutVersion()); setServiceLayoutVersion(getServiceLayoutVersion());
writeProperties(sd); writeProperties(sd);
}
return sd; return sd;
} catch (IOException ioe) { } catch (IOException ioe) {
@ -325,7 +327,7 @@ public class DataStorage extends Storage {
} }
StorageDirectory sd = loadStorageDirectory( StorageDirectory sd = loadStorageDirectory(
datanode, nsInfos.get(0), volume, StartupOption.HOTSWAP); datanode, nsInfos.get(0), volume, StartupOption.HOTSWAP, null);
VolumeBuilder builder = VolumeBuilder builder =
new VolumeBuilder(this, sd); new VolumeBuilder(this, sd);
for (NamespaceInfo nsInfo : nsInfos) { for (NamespaceInfo nsInfo : nsInfos) {
@ -336,12 +338,35 @@ public class DataStorage extends Storage {
final BlockPoolSliceStorage bpStorage = getBlockPoolSliceStorage(nsInfo); final BlockPoolSliceStorage bpStorage = getBlockPoolSliceStorage(nsInfo);
final List<StorageDirectory> dirs = bpStorage.loadBpStorageDirectories( final List<StorageDirectory> dirs = bpStorage.loadBpStorageDirectories(
nsInfo, bpDataDirs, StartupOption.HOTSWAP, datanode.getConf()); nsInfo, bpDataDirs, StartupOption.HOTSWAP, null, datanode.getConf());
builder.addBpStorageDirectories(nsInfo.getBlockPoolID(), dirs); builder.addBpStorageDirectories(nsInfo.getBlockPoolID(), dirs);
} }
return builder; return builder;
} }
static int getParallelVolumeLoadThreadsNum(int dataDirs, Configuration conf) {
final String key
= DFSConfigKeys.DFS_DATANODE_PARALLEL_VOLUME_LOAD_THREADS_NUM_KEY;
final int n = conf.getInt(key, dataDirs);
if (n < 1) {
throw new HadoopIllegalArgumentException(key + " = " + n + " < 1");
}
final int min = Math.min(n, dataDirs);
LOG.info("Using " + min + " threads to upgrade data directories ("
+ key + "=" + n + ", dataDirs=" + dataDirs + ")");
return min;
}
static class UpgradeTask {
private final StorageLocation dataDir;
private final Future<StorageDirectory> future;
UpgradeTask(StorageLocation dataDir, Future<StorageDirectory> future) {
this.dataDir = dataDir;
this.future = future;
}
}
/** /**
* Add a list of volumes to be managed by DataStorage. If the volume is empty, * Add a list of volumes to be managed by DataStorage. If the volume is empty,
* format it, otherwise recover it from previous transitions if required. * format it, otherwise recover it from previous transitions if required.
@ -356,43 +381,74 @@ public class DataStorage extends Storage {
synchronized List<StorageDirectory> addStorageLocations(DataNode datanode, synchronized List<StorageDirectory> addStorageLocations(DataNode datanode,
NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs, NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs,
StartupOption startOpt) throws IOException { StartupOption startOpt) throws IOException {
final int numThreads = getParallelVolumeLoadThreadsNum(
dataDirs.size(), datanode.getConf());
final ExecutorService executor = Executors.newFixedThreadPool(numThreads);
try {
final List<StorageLocation> successLocations = loadDataStorage( final List<StorageLocation> successLocations = loadDataStorage(
datanode, nsInfo, dataDirs, startOpt); datanode, nsInfo, dataDirs, startOpt, executor);
return loadBlockPoolSliceStorage( return loadBlockPoolSliceStorage(
datanode, nsInfo, successLocations, startOpt); datanode, nsInfo, successLocations, startOpt, executor);
} finally {
executor.shutdown();
}
} }
private List<StorageLocation> loadDataStorage(DataNode datanode, private List<StorageLocation> loadDataStorage(DataNode datanode,
NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs, NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs,
StartupOption startOpt) throws IOException { StartupOption startOpt, ExecutorService executor) throws IOException {
final List<StorageLocation> success = Lists.newArrayList(); final List<StorageLocation> success = Lists.newArrayList();
final List<UpgradeTask> tasks = Lists.newArrayList();
for (StorageLocation dataDir : dataDirs) { for (StorageLocation dataDir : dataDirs) {
File root = dataDir.getFile(); File root = dataDir.getFile();
if (!containsStorageDir(root)) { if (!containsStorageDir(root)) {
try { try {
// It first ensures the datanode level format is completed. // It first ensures the datanode level format is completed.
final List<Callable<StorageDirectory>> callables
= Lists.newArrayList();
final StorageDirectory sd = loadStorageDirectory( final StorageDirectory sd = loadStorageDirectory(
datanode, nsInfo, root, startOpt); datanode, nsInfo, root, startOpt, callables);
if (callables.isEmpty()) {
addStorageDir(sd); addStorageDir(sd);
success.add(dataDir);
} else {
for(Callable<StorageDirectory> c : callables) {
tasks.add(new UpgradeTask(dataDir, executor.submit(c)));
}
}
} catch (IOException e) { } catch (IOException e) {
LOG.warn("Failed to add storage directory " + dataDir, e); LOG.warn("Failed to add storage directory " + dataDir, e);
continue;
} }
} else { } else {
LOG.info("Storage directory " + dataDir + " has already been used."); LOG.info("Storage directory " + dataDir + " has already been used.");
}
success.add(dataDir); success.add(dataDir);
} }
}
if (!tasks.isEmpty()) {
LOG.info("loadDataStorage: " + tasks.size() + " upgrade tasks");
for(UpgradeTask t : tasks) {
try {
addStorageDir(t.future.get());
success.add(t.dataDir);
} catch (ExecutionException e) {
LOG.warn("Failed to upgrade storage directory " + t.dataDir, e);
} catch (InterruptedException e) {
throw DFSUtilClient.toInterruptedIOException("Task interrupted", e);
}
}
}
return success; return success;
} }
private List<StorageDirectory> loadBlockPoolSliceStorage(DataNode datanode, private List<StorageDirectory> loadBlockPoolSliceStorage(DataNode datanode,
NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs, NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs,
StartupOption startOpt) throws IOException { StartupOption startOpt, ExecutorService executor) throws IOException {
final String bpid = nsInfo.getBlockPoolID(); final String bpid = nsInfo.getBlockPoolID();
final BlockPoolSliceStorage bpStorage = getBlockPoolSliceStorage(nsInfo); final BlockPoolSliceStorage bpStorage = getBlockPoolSliceStorage(nsInfo);
final List<StorageDirectory> success = Lists.newArrayList(); final List<StorageDirectory> success = Lists.newArrayList();
final List<UpgradeTask> tasks = Lists.newArrayList();
for (StorageLocation dataDir : dataDirs) { for (StorageLocation dataDir : dataDirs) {
final File curDir = new File(dataDir.getFile(), STORAGE_DIR_CURRENT); final File curDir = new File(dataDir.getFile(), STORAGE_DIR_CURRENT);
List<File> bpDataDirs = new ArrayList<File>(); List<File> bpDataDirs = new ArrayList<File>();
@ -400,17 +456,38 @@ public class DataStorage extends Storage {
try { try {
makeBlockPoolDataDir(bpDataDirs, null); makeBlockPoolDataDir(bpDataDirs, null);
final List<Callable<StorageDirectory>> callables = Lists.newArrayList();
final List<StorageDirectory> dirs = bpStorage.recoverTransitionRead( final List<StorageDirectory> dirs = bpStorage.recoverTransitionRead(
nsInfo, bpDataDirs, startOpt, datanode.getConf()); nsInfo, bpDataDirs, startOpt, callables, datanode.getConf());
if (callables.isEmpty()) {
for(StorageDirectory sd : dirs) { for(StorageDirectory sd : dirs) {
success.add(sd); success.add(sd);
} }
} else {
for(Callable<StorageDirectory> c : callables) {
tasks.add(new UpgradeTask(dataDir, executor.submit(c)));
}
}
} catch (IOException e) { } catch (IOException e) {
LOG.warn("Failed to add storage directory " + dataDir LOG.warn("Failed to add storage directory " + dataDir
+ " for block pool " + bpid, e); + " for block pool " + bpid, e);
} }
} }
if (!tasks.isEmpty()) {
LOG.info("loadBlockPoolSliceStorage: " + tasks.size() + " upgrade tasks");
for(UpgradeTask t : tasks) {
try {
success.add(t.future.get());
} catch (ExecutionException e) {
LOG.warn("Failed to upgrade storage directory " + t.dataDir
+ " for block pool " + bpid, e);
} catch (InterruptedException e) {
throw DFSUtilClient.toInterruptedIOException("Task interrupted", e);
}
}
}
return success; return success;
} }
@ -655,7 +732,8 @@ public class DataStorage extends Storage {
* @return true if the new properties has been written. * @return true if the new properties has been written.
*/ */
private boolean doTransition(StorageDirectory sd, NamespaceInfo nsInfo, private boolean doTransition(StorageDirectory sd, NamespaceInfo nsInfo,
StartupOption startOpt, Configuration conf) throws IOException { StartupOption startOpt, List<Callable<StorageDirectory>> callables,
Configuration conf) throws IOException {
if (startOpt == StartupOption.ROLLBACK) { if (startOpt == StartupOption.ROLLBACK) {
doRollback(sd, nsInfo); // rollback if applicable doRollback(sd, nsInfo); // rollback if applicable
} }
@ -697,7 +775,7 @@ public class DataStorage extends Storage {
// simply update the properties. // simply update the properties.
upgradeProperties(sd); upgradeProperties(sd);
} else { } else {
doUpgradePreFederation(sd, nsInfo, conf); doUpgradePreFederation(sd, nsInfo, callables, conf);
} }
return true; // doUgrade already has written properties return true; // doUgrade already has written properties
} }
@ -734,7 +812,9 @@ public class DataStorage extends Storage {
* @param sd storage directory * @param sd storage directory
*/ */
void doUpgradePreFederation(final StorageDirectory sd, void doUpgradePreFederation(final StorageDirectory sd,
final NamespaceInfo nsInfo, final Configuration conf) throws IOException { final NamespaceInfo nsInfo,
final List<Callable<StorageDirectory>> callables,
final Configuration conf) throws IOException {
final int oldLV = getLayoutVersion(); final int oldLV = getLayoutVersion();
LOG.info("Upgrading storage directory " + sd.getRoot() LOG.info("Upgrading storage directory " + sd.getRoot()
+ ".\n old LV = " + oldLV + ".\n old LV = " + oldLV
@ -767,10 +847,20 @@ public class DataStorage extends Storage {
bpStorage.format(curDir, nsInfo); bpStorage.format(curDir, nsInfo);
final File toDir = new File(curBpDir, STORAGE_DIR_CURRENT); final File toDir = new File(curBpDir, STORAGE_DIR_CURRENT);
doUgrade(sd, nsInfo, prevDir, tmpDir, bbwDir, toDir, oldLV, conf); if (callables == null) {
doUpgrade(sd, nsInfo, prevDir, tmpDir, bbwDir, toDir, oldLV, conf);
} else {
callables.add(new Callable<StorageDirectory>() {
@Override
public StorageDirectory call() throws Exception {
doUpgrade(sd, nsInfo, prevDir, tmpDir, bbwDir, toDir, oldLV, conf);
return sd;
}
});
}
} }
private void doUgrade(final StorageDirectory sd, private void doUpgrade(final StorageDirectory sd,
final NamespaceInfo nsInfo, final File prevDir, final NamespaceInfo nsInfo, final File prevDir,
final File tmpDir, final File bbwDir, final File toDir, final int oldLV, final File tmpDir, final File bbwDir, final File toDir, final int oldLV,
Configuration conf) throws IOException { Configuration conf) throws IOException {