HDFS-5000. DataNode configuration should allow specifying storage type
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-2832@1517417 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c41df254fe
commit
73d14311bc
@ -460,9 +460,9 @@ void start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String formatThreadName() {
|
private String formatThreadName() {
|
||||||
Collection<URI> dataDirs = DataNode.getStorageDirs(dn.getConf());
|
Collection<StorageLocation> dataDirs =
|
||||||
return "DataNode: [" +
|
DataNode.getStorageLocations(dn.getConf());
|
||||||
StringUtils.uriToString(dataDirs.toArray(new URI[0])) + "] " +
|
return "DataNode: [" + dataDirs.toString() + "] " +
|
||||||
" heartbeating to " + nnAddr;
|
" heartbeating to " + nnAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ public static InetSocketAddress createSocketAddr(String target) {
|
|||||||
private JvmPauseMonitor pauseMonitor;
|
private JvmPauseMonitor pauseMonitor;
|
||||||
|
|
||||||
private SecureResources secureResources = null;
|
private SecureResources secureResources = null;
|
||||||
private AbstractList<File> dataDirs;
|
private AbstractList<StorageLocation> dataDirs;
|
||||||
private Configuration conf;
|
private Configuration conf;
|
||||||
|
|
||||||
private final List<String> usersWithLocalPathAccess;
|
private final List<String> usersWithLocalPathAccess;
|
||||||
@ -280,21 +280,12 @@ public static InetSocketAddress createSocketAddr(String target) {
|
|||||||
ReadaheadPool readaheadPool;
|
ReadaheadPool readaheadPool;
|
||||||
private final boolean getHdfsBlockLocationsEnabled;
|
private final boolean getHdfsBlockLocationsEnabled;
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the DataNode given a configuration and an array of dataDirs.
|
|
||||||
* 'dataDirs' is where the blocks are stored.
|
|
||||||
*/
|
|
||||||
DataNode(final Configuration conf,
|
|
||||||
final AbstractList<File> dataDirs) throws IOException {
|
|
||||||
this(conf, dataDirs, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the DataNode given a configuration, an array of dataDirs,
|
* Create the DataNode given a configuration, an array of dataDirs,
|
||||||
* and a namenode proxy
|
* and a namenode proxy
|
||||||
*/
|
*/
|
||||||
DataNode(final Configuration conf,
|
DataNode(final Configuration conf,
|
||||||
final AbstractList<File> dataDirs,
|
final AbstractList<StorageLocation> dataDirs,
|
||||||
final SecureResources resources) throws IOException {
|
final SecureResources resources) throws IOException {
|
||||||
super(conf);
|
super(conf);
|
||||||
|
|
||||||
@ -711,7 +702,7 @@ boolean areHeartbeatsDisabledForTests() {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
void startDataNode(Configuration conf,
|
void startDataNode(Configuration conf,
|
||||||
AbstractList<File> dataDirs,
|
AbstractList<StorageLocation> dataDirs,
|
||||||
// DatanodeProtocol namenode,
|
// DatanodeProtocol namenode,
|
||||||
SecureResources resources
|
SecureResources resources
|
||||||
) throws IOException {
|
) throws IOException {
|
||||||
@ -861,7 +852,7 @@ void shutdownBlockPool(BPOfferService bpos) {
|
|||||||
* If this is the first block pool to register, this also initializes
|
* If this is the first block pool to register, this also initializes
|
||||||
* the datanode-scoped storage.
|
* the datanode-scoped storage.
|
||||||
*
|
*
|
||||||
* @param nsInfo the handshake response from the NN.
|
* @param bpos block pool to initialize and register with the NameNode.
|
||||||
* @throws IOException if the NN is inconsistent with the local storage.
|
* @throws IOException if the NN is inconsistent with the local storage.
|
||||||
*/
|
*/
|
||||||
void initBlockPool(BPOfferService bpos) throws IOException {
|
void initBlockPool(BPOfferService bpos) throws IOException {
|
||||||
@ -1688,17 +1679,39 @@ public static DataNode instantiateDataNode(String args [], Configuration conf,
|
|||||||
printUsage(System.err);
|
printUsage(System.err);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
Collection<URI> dataDirs = getStorageDirs(conf);
|
Collection<StorageLocation> dataLocations = getStorageLocations(conf);
|
||||||
UserGroupInformation.setConfiguration(conf);
|
UserGroupInformation.setConfiguration(conf);
|
||||||
SecurityUtil.login(conf, DFS_DATANODE_KEYTAB_FILE_KEY,
|
SecurityUtil.login(conf, DFS_DATANODE_KEYTAB_FILE_KEY,
|
||||||
DFS_DATANODE_USER_NAME_KEY);
|
DFS_DATANODE_USER_NAME_KEY);
|
||||||
return makeInstance(dataDirs, conf, resources);
|
return makeInstance(dataLocations, conf, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Collection<URI> getStorageDirs(Configuration conf) {
|
static Collection<StorageLocation> parseStorageLocations(
|
||||||
Collection<String> dirNames =
|
Collection<String> rawLocations) {
|
||||||
conf.getTrimmedStringCollection(DFS_DATANODE_DATA_DIR_KEY);
|
List<StorageLocation> locations =
|
||||||
return Util.stringCollectionAsURIs(dirNames);
|
new ArrayList<StorageLocation>(rawLocations.size());
|
||||||
|
|
||||||
|
for(String locationString : rawLocations) {
|
||||||
|
StorageLocation location;
|
||||||
|
try {
|
||||||
|
location = StorageLocation.parse(locationString);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
LOG.error("Failed to parse storage location " + locationString);
|
||||||
|
continue;
|
||||||
|
} catch (IllegalArgumentException iae) {
|
||||||
|
LOG.error(iae.toString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
locations.add(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Collection<StorageLocation> getStorageLocations(Configuration conf) {
|
||||||
|
return parseStorageLocations(
|
||||||
|
conf.getTrimmedStringCollection(DFS_DATANODE_DATA_DIR_KEY));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Instantiate & Start a single datanode daemon and wait for it to finish.
|
/** Instantiate & Start a single datanode daemon and wait for it to finish.
|
||||||
@ -1764,51 +1777,45 @@ public void checkDir(LocalFileSystem localFS, Path path)
|
|||||||
* no directory from this directory list can be created.
|
* no directory from this directory list can be created.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
static DataNode makeInstance(Collection<URI> dataDirs, Configuration conf,
|
static DataNode makeInstance(Collection<StorageLocation> dataDirs,
|
||||||
SecureResources resources) throws IOException {
|
Configuration conf, SecureResources resources) throws IOException {
|
||||||
LocalFileSystem localFS = FileSystem.getLocal(conf);
|
LocalFileSystem localFS = FileSystem.getLocal(conf);
|
||||||
FsPermission permission = new FsPermission(
|
FsPermission permission = new FsPermission(
|
||||||
conf.get(DFS_DATANODE_DATA_DIR_PERMISSION_KEY,
|
conf.get(DFS_DATANODE_DATA_DIR_PERMISSION_KEY,
|
||||||
DFS_DATANODE_DATA_DIR_PERMISSION_DEFAULT));
|
DFS_DATANODE_DATA_DIR_PERMISSION_DEFAULT));
|
||||||
DataNodeDiskChecker dataNodeDiskChecker =
|
DataNodeDiskChecker dataNodeDiskChecker =
|
||||||
new DataNodeDiskChecker(permission);
|
new DataNodeDiskChecker(permission);
|
||||||
ArrayList<File> dirs =
|
ArrayList<StorageLocation> locations =
|
||||||
getDataDirsFromURIs(dataDirs, localFS, dataNodeDiskChecker);
|
checkStorageLocations(dataDirs, localFS, dataNodeDiskChecker);
|
||||||
DefaultMetricsSystem.initialize("DataNode");
|
DefaultMetricsSystem.initialize("DataNode");
|
||||||
|
|
||||||
assert dirs.size() > 0 : "number of data directories should be > 0";
|
assert locations.size() > 0 : "number of data directories should be > 0";
|
||||||
return new DataNode(conf, dirs, resources);
|
return new DataNode(conf, locations, resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataNode ctor expects AbstractList instead of List or Collection...
|
// DataNode ctor expects AbstractList instead of List or Collection...
|
||||||
static ArrayList<File> getDataDirsFromURIs(Collection<URI> dataDirs,
|
static ArrayList<StorageLocation> checkStorageLocations(
|
||||||
|
Collection<StorageLocation> dataDirs,
|
||||||
LocalFileSystem localFS, DataNodeDiskChecker dataNodeDiskChecker)
|
LocalFileSystem localFS, DataNodeDiskChecker dataNodeDiskChecker)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
ArrayList<File> dirs = new ArrayList<File>();
|
ArrayList<StorageLocation> locations = new ArrayList<StorageLocation>();
|
||||||
StringBuilder invalidDirs = new StringBuilder();
|
StringBuilder invalidDirs = new StringBuilder();
|
||||||
for (URI dirURI : dataDirs) {
|
for (StorageLocation location : dataDirs) {
|
||||||
if (!"file".equalsIgnoreCase(dirURI.getScheme())) {
|
|
||||||
LOG.warn("Unsupported URI schema in " + dirURI + ". Ignoring ...");
|
|
||||||
invalidDirs.append("\"").append(dirURI).append("\" ");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// drop any (illegal) authority in the URI for backwards compatibility
|
|
||||||
File dir = new File(dirURI.getPath());
|
|
||||||
try {
|
try {
|
||||||
dataNodeDiskChecker.checkDir(localFS, new Path(dir.toURI()));
|
dataNodeDiskChecker.checkDir(localFS, new Path(location.getUri()));
|
||||||
dirs.add(dir);
|
locations.add(location);
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
LOG.warn("Invalid " + DFS_DATANODE_DATA_DIR_KEY + " "
|
LOG.warn("Invalid " + DFS_DATANODE_DATA_DIR_KEY + " "
|
||||||
+ dir + " : ", ioe);
|
+ location.getFile() + " : ", ioe);
|
||||||
invalidDirs.append("\"").append(dir.getCanonicalPath()).append("\" ");
|
invalidDirs.append("\"").append(location.getFile().getCanonicalPath()).append("\" ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (dirs.size() == 0) {
|
if (locations.size() == 0) {
|
||||||
throw new IOException("All directories in "
|
throw new IOException("All directories in "
|
||||||
+ DFS_DATANODE_DATA_DIR_KEY + " are invalid: "
|
+ DFS_DATANODE_DATA_DIR_KEY + " are invalid: "
|
||||||
+ invalidDirs);
|
+ invalidDirs);
|
||||||
}
|
}
|
||||||
return dirs;
|
return locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -129,7 +129,8 @@ public synchronized void createStorageID() {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
synchronized void recoverTransitionRead(DataNode datanode,
|
synchronized void recoverTransitionRead(DataNode datanode,
|
||||||
NamespaceInfo nsInfo, Collection<File> dataDirs, StartupOption startOpt)
|
NamespaceInfo nsInfo, Collection<StorageLocation> dataDirs,
|
||||||
|
StartupOption startOpt)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (initialized) {
|
if (initialized) {
|
||||||
// DN storage has been initialized, no need to do anything
|
// DN storage has been initialized, no need to do anything
|
||||||
@ -145,8 +146,8 @@ synchronized void recoverTransitionRead(DataNode datanode,
|
|||||||
// Format and recover.
|
// Format and recover.
|
||||||
this.storageDirs = new ArrayList<StorageDirectory>(dataDirs.size());
|
this.storageDirs = new ArrayList<StorageDirectory>(dataDirs.size());
|
||||||
ArrayList<StorageState> dataDirStates = new ArrayList<StorageState>(dataDirs.size());
|
ArrayList<StorageState> dataDirStates = new ArrayList<StorageState>(dataDirs.size());
|
||||||
for(Iterator<File> it = dataDirs.iterator(); it.hasNext();) {
|
for(Iterator<StorageLocation> it = dataDirs.iterator(); it.hasNext();) {
|
||||||
File dataDir = it.next();
|
File dataDir = it.next().getFile();
|
||||||
StorageDirectory sd = new StorageDirectory(dataDir);
|
StorageDirectory sd = new StorageDirectory(dataDir);
|
||||||
StorageState curState;
|
StorageState curState;
|
||||||
try {
|
try {
|
||||||
@ -215,14 +216,14 @@ synchronized void recoverTransitionRead(DataNode datanode,
|
|||||||
* @throws IOException on error
|
* @throws IOException on error
|
||||||
*/
|
*/
|
||||||
void recoverTransitionRead(DataNode datanode, String bpID, NamespaceInfo nsInfo,
|
void recoverTransitionRead(DataNode datanode, String bpID, NamespaceInfo nsInfo,
|
||||||
Collection<File> dataDirs, StartupOption startOpt) throws IOException {
|
Collection<StorageLocation> dataDirs, StartupOption startOpt) throws IOException {
|
||||||
// First ensure datanode level format/snapshot/rollback is completed
|
// First ensure datanode level format/snapshot/rollback is completed
|
||||||
recoverTransitionRead(datanode, nsInfo, dataDirs, startOpt);
|
recoverTransitionRead(datanode, nsInfo, dataDirs, startOpt);
|
||||||
|
|
||||||
// Create list of storage directories for the block pool
|
// Create list of storage directories for the block pool
|
||||||
Collection<File> bpDataDirs = new ArrayList<File>();
|
Collection<File> bpDataDirs = new ArrayList<File>();
|
||||||
for(Iterator<File> it = dataDirs.iterator(); it.hasNext();) {
|
for(Iterator<StorageLocation> it = dataDirs.iterator(); it.hasNext();) {
|
||||||
File dnRoot = it.next();
|
File dnRoot = it.next().getFile();
|
||||||
File bpRoot = BlockPoolSliceStorage.getBpRoot(bpID, new File(dnRoot,
|
File bpRoot = BlockPoolSliceStorage.getBpRoot(bpID, new File(dnRoot,
|
||||||
STORAGE_DIR_CURRENT));
|
STORAGE_DIR_CURRENT));
|
||||||
bpDataDirs.add(bpRoot);
|
bpDataDirs.add(bpRoot);
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -44,18 +46,9 @@
|
|||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.commons.logging.impl.Log4JLogger;
|
import org.apache.commons.logging.impl.Log4JLogger;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.fs.CommonConfigurationKeys;
|
import org.apache.hadoop.fs.*;
|
||||||
import org.apache.hadoop.fs.FSDataOutputStream;
|
|
||||||
import org.apache.hadoop.fs.FileSystem;
|
|
||||||
import org.apache.hadoop.fs.FileUtil;
|
|
||||||
import org.apache.hadoop.fs.Path;
|
|
||||||
import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
|
import org.apache.hadoop.ha.HAServiceProtocol.HAServiceState;
|
||||||
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
import org.apache.hadoop.hdfs.*;
|
||||||
import org.apache.hadoop.hdfs.DFSTestUtil;
|
|
||||||
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
|
||||||
import org.apache.hadoop.hdfs.HdfsConfiguration;
|
|
||||||
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
|
||||||
import org.apache.hadoop.hdfs.MiniDFSNNTopology;
|
|
||||||
import org.apache.hadoop.hdfs.protocol.DatanodeID;
|
import org.apache.hadoop.hdfs.protocol.DatanodeID;
|
||||||
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
||||||
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
|
import org.apache.hadoop.hdfs.protocol.ExtendedBlock;
|
||||||
@ -80,10 +73,7 @@
|
|||||||
import org.apache.hadoop.util.Daemon;
|
import org.apache.hadoop.util.Daemon;
|
||||||
import org.apache.hadoop.util.DataChecksum;
|
import org.apache.hadoop.util.DataChecksum;
|
||||||
import org.apache.log4j.Level;
|
import org.apache.log4j.Level;
|
||||||
import org.junit.After;
|
import org.junit.*;
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
@ -121,7 +111,7 @@ public class TestBlockRecovery {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Before
|
@Before
|
||||||
public void startUp() throws IOException {
|
public void startUp() throws IOException, URISyntaxException {
|
||||||
tearDownDone = false;
|
tearDownDone = false;
|
||||||
conf = new HdfsConfiguration();
|
conf = new HdfsConfiguration();
|
||||||
conf.set(DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY, DATA_DIR);
|
conf.set(DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY, DATA_DIR);
|
||||||
@ -131,11 +121,12 @@ public void startUp() throws IOException {
|
|||||||
conf.setInt(CommonConfigurationKeys.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 0);
|
conf.setInt(CommonConfigurationKeys.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 0);
|
||||||
FileSystem.setDefaultUri(conf,
|
FileSystem.setDefaultUri(conf,
|
||||||
"hdfs://" + NN_ADDR.getHostName() + ":" + NN_ADDR.getPort());
|
"hdfs://" + NN_ADDR.getHostName() + ":" + NN_ADDR.getPort());
|
||||||
ArrayList<File> dirs = new ArrayList<File>();
|
ArrayList<StorageLocation> locations = new ArrayList<StorageLocation>();
|
||||||
File dataDir = new File(DATA_DIR);
|
File dataDir = new File(DATA_DIR);
|
||||||
FileUtil.fullyDelete(dataDir);
|
FileUtil.fullyDelete(dataDir);
|
||||||
dataDir.mkdirs();
|
dataDir.mkdirs();
|
||||||
dirs.add(dataDir);
|
StorageLocation location = new StorageLocation(new URI(dataDir.getPath()));
|
||||||
|
locations.add(location);
|
||||||
final DatanodeProtocolClientSideTranslatorPB namenode =
|
final DatanodeProtocolClientSideTranslatorPB namenode =
|
||||||
mock(DatanodeProtocolClientSideTranslatorPB.class);
|
mock(DatanodeProtocolClientSideTranslatorPB.class);
|
||||||
|
|
||||||
@ -161,7 +152,7 @@ public DatanodeRegistration answer(InvocationOnMock invocation)
|
|||||||
new DatanodeCommand[0],
|
new DatanodeCommand[0],
|
||||||
new NNHAStatusHeartbeat(HAServiceState.ACTIVE, 1)));
|
new NNHAStatusHeartbeat(HAServiceState.ACTIVE, 1)));
|
||||||
|
|
||||||
dn = new DataNode(conf, dirs, null) {
|
dn = new DataNode(conf, locations, null) {
|
||||||
@Override
|
@Override
|
||||||
DatanodeProtocolClientSideTranslatorPB connectToNN(
|
DatanodeProtocolClientSideTranslatorPB connectToNN(
|
||||||
InetSocketAddress nnAddr) throws IOException {
|
InetSocketAddress nnAddr) throws IOException {
|
||||||
|
@ -20,11 +20,14 @@
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.hdfs.StorageType;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_DATANODE_DATA_DIR_KEY;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
@ -34,19 +37,71 @@
|
|||||||
|
|
||||||
public class TestDataDirs {
|
public class TestDataDirs {
|
||||||
|
|
||||||
@Test (timeout = 10000)
|
@Test (timeout = 30000)
|
||||||
public void testGetDataDirsFromURIs() throws Throwable {
|
public void testDataDirParsing() throws Throwable {
|
||||||
|
Configuration conf = new Configuration();
|
||||||
|
ArrayList<StorageLocation> locations;
|
||||||
|
File dir0 = new File("/dir0");
|
||||||
|
File dir1 = new File("/dir1");
|
||||||
|
File dir2 = new File("/dir2");
|
||||||
|
File dir3 = new File("/dir3");
|
||||||
|
|
||||||
|
// Verify that a valid string is correctly parsed, and that storage
|
||||||
|
// type is not case-sensitive
|
||||||
|
String locations1 = "[disk]/dir0,[DISK]/dir1,[sSd]/dir2,[disK]/dir3";
|
||||||
|
conf.set(DFS_DATANODE_DATA_DIR_KEY, locations1);
|
||||||
|
locations = new ArrayList<StorageLocation>(DataNode.getStorageLocations(conf));
|
||||||
|
assertThat(locations.size(), is(4));
|
||||||
|
assertThat(locations.get(0).getStorageType(), is(StorageType.DISK));
|
||||||
|
assertThat(locations.get(0).getUri(), is(dir0.toURI()));
|
||||||
|
assertThat(locations.get(1).getStorageType(), is(StorageType.DISK));
|
||||||
|
assertThat(locations.get(1).getUri(), is(dir1.toURI()));
|
||||||
|
assertThat(locations.get(2).getStorageType(), is(StorageType.SSD));
|
||||||
|
assertThat(locations.get(2).getUri(), is(dir2.toURI()));
|
||||||
|
assertThat(locations.get(3).getStorageType(), is(StorageType.DISK));
|
||||||
|
assertThat(locations.get(3).getUri(), is(dir3.toURI()));
|
||||||
|
|
||||||
|
// Verify that an unrecognized storage type is ignored.
|
||||||
|
String locations2 = "[BadMediaType]/dir0,[ssd]/dir1,[disk]/dir2";
|
||||||
|
conf.set(DFS_DATANODE_DATA_DIR_KEY, locations2);
|
||||||
|
locations = new ArrayList<StorageLocation>(DataNode.getStorageLocations(conf));
|
||||||
|
assertThat(locations.size(), is(3));
|
||||||
|
assertThat(locations.get(0).getStorageType(), is(StorageType.DISK));
|
||||||
|
assertThat(locations.get(0).getUri(), is(dir0.toURI()));
|
||||||
|
assertThat(locations.get(1).getStorageType(), is(StorageType.SSD));
|
||||||
|
assertThat(locations.get(1).getUri(), is(dir1.toURI()));
|
||||||
|
assertThat(locations.get(2).getStorageType(), is(StorageType.DISK));
|
||||||
|
assertThat(locations.get(2).getUri(), is(dir2.toURI()));
|
||||||
|
|
||||||
|
// Assert that a string with no storage type specified is
|
||||||
|
// correctly parsed and the default storage type is picked up.
|
||||||
|
String locations3 = "/dir0,/dir1";
|
||||||
|
conf.set(DFS_DATANODE_DATA_DIR_KEY, locations3);
|
||||||
|
locations = new ArrayList<StorageLocation>(DataNode.getStorageLocations(conf));
|
||||||
|
assertThat(locations.size(), is(2));
|
||||||
|
assertThat(locations.get(0).getStorageType(), is(StorageType.DISK));
|
||||||
|
assertThat(locations.get(0).getUri(), is(dir0.toURI()));
|
||||||
|
assertThat(locations.get(1).getStorageType(), is(StorageType.DISK));
|
||||||
|
assertThat(locations.get(1).getUri(), is(dir1.toURI()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test (timeout = 30000)
|
||||||
|
public void testDataDirValidation() throws Throwable {
|
||||||
|
|
||||||
DataNodeDiskChecker diskChecker = mock(DataNodeDiskChecker.class);
|
DataNodeDiskChecker diskChecker = mock(DataNodeDiskChecker.class);
|
||||||
doThrow(new IOException()).doThrow(new IOException()).doNothing()
|
doThrow(new IOException()).doThrow(new IOException()).doNothing()
|
||||||
.when(diskChecker).checkDir(any(LocalFileSystem.class), any(Path.class));
|
.when(diskChecker).checkDir(any(LocalFileSystem.class), any(Path.class));
|
||||||
LocalFileSystem fs = mock(LocalFileSystem.class);
|
LocalFileSystem fs = mock(LocalFileSystem.class);
|
||||||
Collection<URI> uris = Arrays.asList(new URI("file:/p1/"),
|
AbstractList<StorageLocation> locations = new ArrayList<StorageLocation>();
|
||||||
new URI("file:/p2/"), new URI("file:/p3/"));
|
|
||||||
|
|
||||||
List<File> dirs = DataNode.getDataDirsFromURIs(uris, fs, diskChecker);
|
locations.add(new StorageLocation(new URI("file:/p1/")));
|
||||||
assertEquals("number of valid data dirs", 1, dirs.size());
|
locations.add(new StorageLocation(new URI("file:/p2/")));
|
||||||
String validDir = dirs.iterator().next().getPath();
|
locations.add(new StorageLocation(new URI("file:/p3/")));
|
||||||
assertEquals("p3 should be valid", new File("/p3").getPath(), validDir);
|
|
||||||
|
ArrayList<StorageLocation> checkedLocations =
|
||||||
|
DataNode.checkStorageLocations(locations, fs, diskChecker);
|
||||||
|
assertEquals("number of valid data dirs", 1, checkedLocations.size());
|
||||||
|
String validDir = checkedLocations.iterator().next().getFile().getPath();
|
||||||
|
assertThat("p3 should be valid", new File("/p3/").getPath(), is(validDir));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user