HDFS-13536. [PROVIDED Storage] HA for InMemoryAliasMap. Contributed by Virajith Jalaparti.
This commit is contained in:
parent
5cc2541a16
commit
1804a31515
@ -396,7 +396,7 @@ static String concatSuffixes(String... suffixes) {
|
|||||||
* @param keys Set of keys to look for in the order of preference
|
* @param keys Set of keys to look for in the order of preference
|
||||||
* @return a map(nameserviceId to map(namenodeId to InetSocketAddress))
|
* @return a map(nameserviceId to map(namenodeId to InetSocketAddress))
|
||||||
*/
|
*/
|
||||||
static Map<String, Map<String, InetSocketAddress>> getAddresses(
|
public static Map<String, Map<String, InetSocketAddress>> getAddresses(
|
||||||
Configuration conf, String defaultAddress, String... keys) {
|
Configuration conf, String defaultAddress, String... keys) {
|
||||||
Collection<String> nameserviceIds = getNameServiceIds(conf);
|
Collection<String> nameserviceIds = getNameServiceIds(conf);
|
||||||
return getAddressesForNsIds(conf, nameserviceIds, defaultAddress, keys);
|
return getAddressesForNsIds(conf, nameserviceIds, defaultAddress, keys);
|
||||||
@ -426,7 +426,7 @@ static Map<String, Map<String, InetSocketAddress>> getAddressesForNsIds(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, InetSocketAddress> getAddressesForNameserviceId(
|
public static Map<String, InetSocketAddress> getAddressesForNameserviceId(
|
||||||
Configuration conf, String nsId, String defaultValue, String... keys) {
|
Configuration conf, String nsId, String defaultValue, String... keys) {
|
||||||
Collection<String> nnIds = getNameNodeIds(conf, nsId);
|
Collection<String> nnIds = getNameNodeIds(conf, nsId);
|
||||||
Map<String, InetSocketAddress> ret = Maps.newLinkedHashMap();
|
Map<String, InetSocketAddress> ret = Maps.newLinkedHashMap();
|
||||||
|
@ -184,6 +184,9 @@ public interface HdfsClientConfigKeys {
|
|||||||
"dfs.namenode.snapshot.capture.openfiles";
|
"dfs.namenode.snapshot.capture.openfiles";
|
||||||
boolean DFS_NAMENODE_SNAPSHOT_CAPTURE_OPENFILES_DEFAULT = false;
|
boolean DFS_NAMENODE_SNAPSHOT_CAPTURE_OPENFILES_DEFAULT = false;
|
||||||
|
|
||||||
|
String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS =
|
||||||
|
"dfs.provided.aliasmap.inmemory.dnrpc-address";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These are deprecated config keys to client code.
|
* These are deprecated config keys to client code.
|
||||||
*/
|
*/
|
||||||
|
@ -37,6 +37,8 @@
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hdfs.client.HdfsClientConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A FailoverProxyProvider implementation which allows one to configure
|
* A FailoverProxyProvider implementation which allows one to configure
|
||||||
* multiple URIs to connect to during fail-over. A random configured address is
|
* multiple URIs to connect to during fail-over. A random configured address is
|
||||||
@ -60,6 +62,11 @@ public class ConfiguredFailoverProxyProvider<T> extends
|
|||||||
|
|
||||||
public ConfiguredFailoverProxyProvider(Configuration conf, URI uri,
|
public ConfiguredFailoverProxyProvider(Configuration conf, URI uri,
|
||||||
Class<T> xface, HAProxyFactory<T> factory) {
|
Class<T> xface, HAProxyFactory<T> factory) {
|
||||||
|
this(conf, uri, xface, factory, DFS_NAMENODE_RPC_ADDRESS_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfiguredFailoverProxyProvider(Configuration conf, URI uri,
|
||||||
|
Class<T> xface, HAProxyFactory<T> factory, String addressKey) {
|
||||||
this.xface = xface;
|
this.xface = xface;
|
||||||
this.conf = new Configuration(conf);
|
this.conf = new Configuration(conf);
|
||||||
int maxRetries = this.conf.getInt(
|
int maxRetries = this.conf.getInt(
|
||||||
@ -81,7 +88,7 @@ public ConfiguredFailoverProxyProvider(Configuration conf, URI uri,
|
|||||||
ugi = UserGroupInformation.getCurrentUser();
|
ugi = UserGroupInformation.getCurrentUser();
|
||||||
|
|
||||||
Map<String, Map<String, InetSocketAddress>> map =
|
Map<String, Map<String, InetSocketAddress>> map =
|
||||||
DFSUtilClient.getHaNnRpcAddresses(conf);
|
DFSUtilClient.getAddresses(conf, null, addressKey);
|
||||||
Map<String, InetSocketAddress> addressesInNN = map.get(uri.getHost());
|
Map<String, InetSocketAddress> addressesInNN = map.get(uri.getHost());
|
||||||
|
|
||||||
if (addressesInNN == null || addressesInNN.size() == 0) {
|
if (addressesInNN == null || addressesInNN.size() == 0) {
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* 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.ha;
|
||||||
|
|
||||||
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hdfs.client.HdfsClientConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link ConfiguredFailoverProxyProvider} implementation used to connect
|
||||||
|
* to an InMemoryAliasMap.
|
||||||
|
*/
|
||||||
|
public class InMemoryAliasMapFailoverProxyProvider<T>
|
||||||
|
extends ConfiguredFailoverProxyProvider<T> {
|
||||||
|
|
||||||
|
public InMemoryAliasMapFailoverProxyProvider(
|
||||||
|
Configuration conf, URI uri, Class<T> xface, HAProxyFactory<T> factory) {
|
||||||
|
super(conf, uri, xface, factory,
|
||||||
|
DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS);
|
||||||
|
}
|
||||||
|
}
|
@ -86,8 +86,11 @@ public class DFSConfigKeys extends CommonConfigurationKeys {
|
|||||||
HdfsClientConfigKeys.DeprecatedKeys.DFS_NAMENODE_BACKUP_HTTP_ADDRESS_KEY;
|
HdfsClientConfigKeys.DeprecatedKeys.DFS_NAMENODE_BACKUP_HTTP_ADDRESS_KEY;
|
||||||
public static final String DFS_NAMENODE_BACKUP_HTTP_ADDRESS_DEFAULT = "0.0.0.0:50105";
|
public static final String DFS_NAMENODE_BACKUP_HTTP_ADDRESS_DEFAULT = "0.0.0.0:50105";
|
||||||
public static final String DFS_NAMENODE_BACKUP_SERVICE_RPC_ADDRESS_KEY = "dfs.namenode.backup.dnrpc-address";
|
public static final String DFS_NAMENODE_BACKUP_SERVICE_RPC_ADDRESS_KEY = "dfs.namenode.backup.dnrpc-address";
|
||||||
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS = "dfs.provided.aliasmap.inmemory.dnrpc-address";
|
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS =
|
||||||
|
HdfsClientConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS;
|
||||||
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT = "0.0.0.0:50200";
|
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT = "0.0.0.0:50200";
|
||||||
|
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_BIND_HOST = "dfs.provided.aliasmap.inmemory.rpc.bind-host";
|
||||||
|
|
||||||
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR = "dfs.provided.aliasmap.inmemory.leveldb.dir";
|
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR = "dfs.provided.aliasmap.inmemory.leveldb.dir";
|
||||||
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_BATCH_SIZE = "dfs.provided.aliasmap.inmemory.batch-size";
|
public static final String DFS_PROVIDED_ALIASMAP_INMEMORY_BATCH_SIZE = "dfs.provided.aliasmap.inmemory.batch-size";
|
||||||
public static final int DFS_PROVIDED_ALIASMAP_INMEMORY_BATCH_SIZE_DEFAULT = 500;
|
public static final int DFS_PROVIDED_ALIASMAP_INMEMORY_BATCH_SIZE_DEFAULT = 500;
|
||||||
|
@ -1131,6 +1131,41 @@ private static String getNameServiceId(Configuration conf, String addressKey) {
|
|||||||
return getSuffixIDs(conf, addressKey, null, nnId, LOCAL_ADDRESS_MATCHER)[0];
|
return getSuffixIDs(conf, addressKey, null, nnId, LOCAL_ADDRESS_MATCHER)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine the {@link InetSocketAddress} to bind to, for any service.
|
||||||
|
* In case of HA or federation, the address is assumed to specified as
|
||||||
|
* {@code confKey}.NAMESPACEID.NAMENODEID as appropriate.
|
||||||
|
*
|
||||||
|
* @param conf configuration.
|
||||||
|
* @param confKey configuration key (prefix if HA/federation) used to
|
||||||
|
* specify the address for the service.
|
||||||
|
* @param defaultValue default value for the address.
|
||||||
|
* @param bindHostKey configuration key (prefix if HA/federation)
|
||||||
|
* specifying host to bind to.
|
||||||
|
* @return the address to bind to.
|
||||||
|
*/
|
||||||
|
public static InetSocketAddress getBindAddress(Configuration conf,
|
||||||
|
String confKey, String defaultValue, String bindHostKey) {
|
||||||
|
InetSocketAddress address;
|
||||||
|
String nsId = DFSUtil.getNamenodeNameServiceId(conf);
|
||||||
|
String bindHostActualKey;
|
||||||
|
if (nsId != null) {
|
||||||
|
String namenodeId = HAUtil.getNameNodeId(conf, nsId);
|
||||||
|
address = DFSUtilClient.getAddressesForNameserviceId(
|
||||||
|
conf, nsId, null, confKey).get(namenodeId);
|
||||||
|
bindHostActualKey = DFSUtil.addKeySuffixes(bindHostKey, nsId, namenodeId);
|
||||||
|
} else {
|
||||||
|
address = NetUtils.createSocketAddr(conf.get(confKey, defaultValue));
|
||||||
|
bindHostActualKey = bindHostKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
String bindHost = conf.get(bindHostActualKey);
|
||||||
|
if (bindHost == null || bindHost.isEmpty()) {
|
||||||
|
bindHost = address.getHostName();
|
||||||
|
}
|
||||||
|
return new InetSocketAddress(bindHost, address.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns nameservice Id and namenode Id when the local host matches the
|
* Returns nameservice Id and namenode Id when the local host matches the
|
||||||
* configuration parameter {@code addressKey}.<nameservice Id>.<namenode Id>
|
* configuration parameter {@code addressKey}.<nameservice Id>.<namenode Id>
|
||||||
|
@ -31,10 +31,13 @@
|
|||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hdfs.NameNodeProxiesClient.ProxyAndInfo;
|
import org.apache.hadoop.hdfs.NameNodeProxiesClient.ProxyAndInfo;
|
||||||
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
|
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
|
||||||
|
import org.apache.hadoop.hdfs.protocolPB.AliasMapProtocolPB;
|
||||||
|
import org.apache.hadoop.hdfs.protocolPB.InMemoryAliasMapProtocolClientSideTranslatorPB;
|
||||||
import org.apache.hadoop.hdfs.protocolPB.JournalProtocolPB;
|
import org.apache.hadoop.hdfs.protocolPB.JournalProtocolPB;
|
||||||
import org.apache.hadoop.hdfs.protocolPB.JournalProtocolTranslatorPB;
|
import org.apache.hadoop.hdfs.protocolPB.JournalProtocolTranslatorPB;
|
||||||
import org.apache.hadoop.hdfs.protocolPB.NamenodeProtocolPB;
|
import org.apache.hadoop.hdfs.protocolPB.NamenodeProtocolPB;
|
||||||
import org.apache.hadoop.hdfs.protocolPB.NamenodeProtocolTranslatorPB;
|
import org.apache.hadoop.hdfs.protocolPB.NamenodeProtocolTranslatorPB;
|
||||||
|
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMapProtocol;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.ha.AbstractNNFailoverProxyProvider;
|
import org.apache.hadoop.hdfs.server.namenode.ha.AbstractNNFailoverProxyProvider;
|
||||||
import org.apache.hadoop.hdfs.server.namenode.ha.NameNodeHAProxyFactory;
|
import org.apache.hadoop.hdfs.server.namenode.ha.NameNodeHAProxyFactory;
|
||||||
import org.apache.hadoop.hdfs.server.protocol.JournalProtocol;
|
import org.apache.hadoop.hdfs.server.protocol.JournalProtocol;
|
||||||
@ -184,6 +187,8 @@ public static <T> ProxyAndInfo<T> createNonHAProxy(
|
|||||||
conf, ugi);
|
conf, ugi);
|
||||||
} else if (xface == RefreshCallQueueProtocol.class) {
|
} else if (xface == RefreshCallQueueProtocol.class) {
|
||||||
proxy = (T) createNNProxyWithRefreshCallQueueProtocol(nnAddr, conf, ugi);
|
proxy = (T) createNNProxyWithRefreshCallQueueProtocol(nnAddr, conf, ugi);
|
||||||
|
} else if (xface == InMemoryAliasMapProtocol.class) {
|
||||||
|
proxy = (T) createNNProxyWithInMemoryAliasMapProtocol(nnAddr, conf, ugi);
|
||||||
} else {
|
} else {
|
||||||
String message = "Unsupported protocol found when creating the proxy " +
|
String message = "Unsupported protocol found when creating the proxy " +
|
||||||
"connection to NameNode: " +
|
"connection to NameNode: " +
|
||||||
@ -195,6 +200,14 @@ public static <T> ProxyAndInfo<T> createNonHAProxy(
|
|||||||
return new ProxyAndInfo<T>(proxy, dtService, nnAddr);
|
return new ProxyAndInfo<T>(proxy, dtService, nnAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static InMemoryAliasMapProtocol createNNProxyWithInMemoryAliasMapProtocol(
|
||||||
|
InetSocketAddress address, Configuration conf, UserGroupInformation ugi)
|
||||||
|
throws IOException {
|
||||||
|
AliasMapProtocolPB proxy = (AliasMapProtocolPB) createNameNodeProxy(
|
||||||
|
address, conf, ugi, AliasMapProtocolPB.class, 30000);
|
||||||
|
return new InMemoryAliasMapProtocolClientSideTranslatorPB(proxy);
|
||||||
|
}
|
||||||
|
|
||||||
private static JournalProtocol createNNProxyWithJournalProtocol(
|
private static JournalProtocol createNNProxyWithJournalProtocol(
|
||||||
InetSocketAddress address, Configuration conf, UserGroupInformation ugi)
|
InetSocketAddress address, Configuration conf, UserGroupInformation ugi)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@ -20,27 +20,38 @@
|
|||||||
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;
|
||||||
|
import org.apache.hadoop.hdfs.HAUtil;
|
||||||
|
import org.apache.hadoop.hdfs.NameNodeProxies;
|
||||||
import org.apache.hadoop.hdfs.protocol.Block;
|
import org.apache.hadoop.hdfs.protocol.Block;
|
||||||
|
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
|
||||||
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
||||||
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMap;
|
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMap;
|
||||||
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMapProtocol;
|
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMapProtocol;
|
||||||
import org.apache.hadoop.hdfs.server.common.FileRegion;
|
import org.apache.hadoop.hdfs.server.common.FileRegion;
|
||||||
|
import org.apache.hadoop.hdfs.server.namenode.ha.AbstractNNFailoverProxyProvider;
|
||||||
|
import org.apache.hadoop.hdfs.server.namenode.ha.InMemoryAliasMapFailoverProxyProvider;
|
||||||
import org.apache.hadoop.ipc.ProtobufHelper;
|
import org.apache.hadoop.ipc.ProtobufHelper;
|
||||||
import org.apache.hadoop.ipc.ProtobufRpcEngine;
|
|
||||||
import org.apache.hadoop.ipc.RPC;
|
import org.apache.hadoop.ipc.RPC;
|
||||||
import org.apache.hadoop.net.NetUtils;
|
import org.apache.hadoop.net.NetUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS;
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS;
|
||||||
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT;
|
import static org.apache.hadoop.hdfs.DFSUtil.addKeySuffixes;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSUtil.createUri;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSUtilClient.getNameServiceIds;
|
||||||
|
import static org.apache.hadoop.hdfs.client.HdfsClientConfigKeys.Failover.PROXY_PROVIDER_KEY_PREFIX;
|
||||||
import static org.apache.hadoop.hdfs.protocol.proto.AliasMapProtocolProtos.*;
|
import static org.apache.hadoop.hdfs.protocol.proto.AliasMapProtocolProtos.*;
|
||||||
import static org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.*;
|
import static org.apache.hadoop.hdfs.protocol.proto.HdfsProtos.*;
|
||||||
|
|
||||||
@ -52,7 +63,7 @@
|
|||||||
@InterfaceAudience.Private
|
@InterfaceAudience.Private
|
||||||
@InterfaceStability.Unstable
|
@InterfaceStability.Unstable
|
||||||
public class InMemoryAliasMapProtocolClientSideTranslatorPB
|
public class InMemoryAliasMapProtocolClientSideTranslatorPB
|
||||||
implements InMemoryAliasMapProtocol {
|
implements InMemoryAliasMapProtocol, Closeable {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
LoggerFactory
|
LoggerFactory
|
||||||
@ -60,22 +71,61 @@ public class InMemoryAliasMapProtocolClientSideTranslatorPB
|
|||||||
|
|
||||||
private AliasMapProtocolPB rpcProxy;
|
private AliasMapProtocolPB rpcProxy;
|
||||||
|
|
||||||
public InMemoryAliasMapProtocolClientSideTranslatorPB(Configuration conf) {
|
public InMemoryAliasMapProtocolClientSideTranslatorPB(
|
||||||
String addr = conf.getTrimmed(DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS,
|
AliasMapProtocolPB rpcProxy) {
|
||||||
DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT);
|
this.rpcProxy = rpcProxy;
|
||||||
InetSocketAddress aliasMapAddr = NetUtils.createSocketAddr(addr);
|
}
|
||||||
|
|
||||||
RPC.setProtocolEngine(conf, AliasMapProtocolPB.class,
|
public static Collection<InMemoryAliasMapProtocol> init(Configuration conf) {
|
||||||
ProtobufRpcEngine.class);
|
Collection<InMemoryAliasMapProtocol> aliasMaps = new ArrayList<>();
|
||||||
LOG.info("Connecting to address: " + addr);
|
// Try to connect to all configured nameservices as it is not known which
|
||||||
try {
|
// nameservice supports the AliasMap.
|
||||||
rpcProxy = RPC.getProxy(AliasMapProtocolPB.class,
|
for (String nsId : getNameServiceIds(conf)) {
|
||||||
RPC.getProtocolVersion(AliasMapProtocolPB.class), aliasMapAddr, null,
|
try {
|
||||||
conf, NetUtils.getDefaultSocketFactory(conf), 0);
|
URI namenodeURI = null;
|
||||||
} catch (IOException e) {
|
Configuration newConf = new Configuration(conf);
|
||||||
throw new RuntimeException(
|
if (HAUtil.isHAEnabled(conf, nsId)) {
|
||||||
"Error in connecting to " + addr + " Got: " + e);
|
// set the failover-proxy provider if HA is enabled.
|
||||||
|
newConf.setClass(
|
||||||
|
addKeySuffixes(PROXY_PROVIDER_KEY_PREFIX, nsId),
|
||||||
|
InMemoryAliasMapFailoverProxyProvider.class,
|
||||||
|
AbstractNNFailoverProxyProvider.class);
|
||||||
|
namenodeURI = new URI(HdfsConstants.HDFS_URI_SCHEME + "://" + nsId);
|
||||||
|
} else {
|
||||||
|
String key =
|
||||||
|
addKeySuffixes(DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS, nsId);
|
||||||
|
String addr = conf.get(key);
|
||||||
|
if (addr != null) {
|
||||||
|
namenodeURI = createUri(HdfsConstants.HDFS_URI_SCHEME,
|
||||||
|
NetUtils.createSocketAddr(addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (namenodeURI != null) {
|
||||||
|
aliasMaps.add(NameNodeProxies
|
||||||
|
.createProxy(newConf, namenodeURI, InMemoryAliasMapProtocol.class)
|
||||||
|
.getProxy());
|
||||||
|
LOG.info("Connected to InMemoryAliasMap at {}", namenodeURI);
|
||||||
|
}
|
||||||
|
} catch (IOException | URISyntaxException e) {
|
||||||
|
LOG.warn("Exception in connecting to InMemoryAliasMap for nameservice "
|
||||||
|
+ "{}: {}", nsId, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// if a separate AliasMap is configured using
|
||||||
|
// DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS, try to connect it.
|
||||||
|
if (conf.get(DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS) != null) {
|
||||||
|
URI uri = createUri("hdfs", NetUtils.createSocketAddr(
|
||||||
|
conf.get(DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS)));
|
||||||
|
try {
|
||||||
|
aliasMaps.add(NameNodeProxies
|
||||||
|
.createProxy(conf, uri, InMemoryAliasMapProtocol.class).getProxy());
|
||||||
|
LOG.info("Connected to InMemoryAliasMap at {}", uri);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.warn("Exception in connecting to InMemoryAliasMap at {}: {}", uri,
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aliasMaps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -168,7 +218,12 @@ public String getBlockPoolId() throws IOException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
@Override
|
||||||
RPC.stopProxy(rpcProxy);
|
public void close() throws IOException {
|
||||||
|
LOG.info("Stopping rpcProxy in" +
|
||||||
|
"InMemoryAliasMapProtocolClientSideTranslatorPB");
|
||||||
|
if (rpcProxy != null) {
|
||||||
|
RPC.stopProxy(rpcProxy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
import org.apache.hadoop.hdfs.protocol.Block;
|
import org.apache.hadoop.hdfs.protocol.Block;
|
||||||
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
||||||
import org.apache.hadoop.hdfs.server.common.FileRegion;
|
import org.apache.hadoop.hdfs.server.common.FileRegion;
|
||||||
|
import org.apache.hadoop.io.retry.Idempotent;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -69,6 +70,7 @@ public Optional<Block> getNextBlock() {
|
|||||||
* FileRegions and the next marker.
|
* FileRegions and the next marker.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
|
@Idempotent
|
||||||
InMemoryAliasMap.IterationResult list(Optional<Block> marker)
|
InMemoryAliasMap.IterationResult list(Optional<Block> marker)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
@ -80,6 +82,7 @@ InMemoryAliasMap.IterationResult list(Optional<Block> marker)
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
|
@Idempotent
|
||||||
Optional<ProvidedStorageLocation> read(@Nonnull Block block)
|
Optional<ProvidedStorageLocation> read(@Nonnull Block block)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
@ -90,6 +93,7 @@ Optional<ProvidedStorageLocation> read(@Nonnull Block block)
|
|||||||
* @param providedStorageLocation
|
* @param providedStorageLocation
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
|
@Idempotent
|
||||||
void write(@Nonnull Block block,
|
void write(@Nonnull Block block,
|
||||||
@Nonnull ProvidedStorageLocation providedStorageLocation)
|
@Nonnull ProvidedStorageLocation providedStorageLocation)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
@ -99,5 +103,6 @@ void write(@Nonnull Block block,
|
|||||||
* @return the block pool id associated with the Namenode running
|
* @return the block pool id associated with the Namenode running
|
||||||
* the in-memory alias map.
|
* the in-memory alias map.
|
||||||
*/
|
*/
|
||||||
|
@Idempotent
|
||||||
String getBlockPoolId() throws IOException;
|
String getBlockPoolId() throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.apache.hadoop.conf.Configurable;
|
import org.apache.hadoop.conf.Configurable;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
|
||||||
import org.apache.hadoop.hdfs.protocol.Block;
|
import org.apache.hadoop.hdfs.protocol.Block;
|
||||||
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
||||||
import org.apache.hadoop.hdfs.protocolPB.AliasMapProtocolPB;
|
import org.apache.hadoop.hdfs.protocolPB.AliasMapProtocolPB;
|
||||||
@ -34,9 +33,13 @@
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS;
|
||||||
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT;
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_BIND_HOST;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSUtil.getBindAddress;
|
||||||
import static org.apache.hadoop.hdfs.protocol.proto.AliasMapProtocolProtos.*;
|
import static org.apache.hadoop.hdfs.protocol.proto.AliasMapProtocolProtos.*;
|
||||||
import static org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMap.CheckedFunction2;
|
import static org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMap.CheckedFunction2;
|
||||||
|
|
||||||
@ -79,18 +82,16 @@ public void start() throws IOException {
|
|||||||
AliasMapProtocolService
|
AliasMapProtocolService
|
||||||
.newReflectiveBlockingService(aliasMapProtocolXlator);
|
.newReflectiveBlockingService(aliasMapProtocolXlator);
|
||||||
|
|
||||||
String rpcAddress =
|
InetSocketAddress rpcAddress = getBindAddress(conf,
|
||||||
conf.get(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS,
|
DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS,
|
||||||
DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT);
|
DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS_DEFAULT,
|
||||||
String[] split = rpcAddress.split(":");
|
DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_BIND_HOST);
|
||||||
String bindHost = split[0];
|
|
||||||
Integer port = Integer.valueOf(split[1]);
|
|
||||||
|
|
||||||
aliasMapServer = new RPC.Builder(conf)
|
aliasMapServer = new RPC.Builder(conf)
|
||||||
.setProtocol(AliasMapProtocolPB.class)
|
.setProtocol(AliasMapProtocolPB.class)
|
||||||
.setInstance(aliasMapProtocolService)
|
.setInstance(aliasMapProtocolService)
|
||||||
.setBindAddress(bindHost)
|
.setBindAddress(rpcAddress.getHostName())
|
||||||
.setPort(port)
|
.setPort(rpcAddress.getPort())
|
||||||
.setNumHandlers(1)
|
.setNumHandlers(1)
|
||||||
.setVerbose(true)
|
.setVerbose(true)
|
||||||
.build();
|
.build();
|
||||||
|
@ -24,11 +24,17 @@
|
|||||||
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
import org.apache.hadoop.hdfs.protocol.ProvidedStorageLocation;
|
||||||
import org.apache.hadoop.hdfs.protocolPB.InMemoryAliasMapProtocolClientSideTranslatorPB;
|
import org.apache.hadoop.hdfs.protocolPB.InMemoryAliasMapProtocolClientSideTranslatorPB;
|
||||||
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMap;
|
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMap;
|
||||||
|
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMapProtocol;
|
||||||
import org.apache.hadoop.hdfs.server.common.blockaliasmap.BlockAliasMap;
|
import org.apache.hadoop.hdfs.server.common.blockaliasmap.BlockAliasMap;
|
||||||
import org.apache.hadoop.hdfs.server.common.FileRegion;
|
import org.apache.hadoop.hdfs.server.common.FileRegion;
|
||||||
|
import org.apache.hadoop.ipc.RPC;
|
||||||
import org.apache.hadoop.security.UserGroupInformation;
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
@ -44,17 +50,28 @@
|
|||||||
public class InMemoryLevelDBAliasMapClient extends BlockAliasMap<FileRegion>
|
public class InMemoryLevelDBAliasMapClient extends BlockAliasMap<FileRegion>
|
||||||
implements Configurable {
|
implements Configurable {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
LoggerFactory.getLogger(InMemoryLevelDBAliasMapClient.class);
|
||||||
private Configuration conf;
|
private Configuration conf;
|
||||||
private InMemoryAliasMapProtocolClientSideTranslatorPB aliasMap;
|
private Collection<InMemoryAliasMapProtocol> aliasMaps;
|
||||||
private String blockPoolID;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
aliasMap.stop();
|
if (aliasMaps != null) {
|
||||||
|
for (InMemoryAliasMapProtocol aliasMap : aliasMaps) {
|
||||||
|
RPC.stopProxy(aliasMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LevelDbReader extends BlockAliasMap.Reader<FileRegion> {
|
class LevelDbReader extends BlockAliasMap.Reader<FileRegion> {
|
||||||
|
|
||||||
|
private InMemoryAliasMapProtocol aliasMap;
|
||||||
|
|
||||||
|
LevelDbReader(InMemoryAliasMapProtocol aliasMap) {
|
||||||
|
this.aliasMap = aliasMap;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<FileRegion> resolve(Block block) throws IOException {
|
public Optional<FileRegion> resolve(Block block) throws IOException {
|
||||||
Optional<ProvidedStorageLocation> read = aliasMap.read(block);
|
Optional<ProvidedStorageLocation> read = aliasMap.read(block);
|
||||||
@ -114,6 +131,13 @@ public Iterator<FileRegion> iterator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LevelDbWriter extends BlockAliasMap.Writer<FileRegion> {
|
class LevelDbWriter extends BlockAliasMap.Writer<FileRegion> {
|
||||||
|
|
||||||
|
private InMemoryAliasMapProtocol aliasMap;
|
||||||
|
|
||||||
|
LevelDbWriter(InMemoryAliasMapProtocol aliasMap) {
|
||||||
|
this.aliasMap = aliasMap;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void store(FileRegion fileRegion) throws IOException {
|
public void store(FileRegion fileRegion) throws IOException {
|
||||||
aliasMap.write(fileRegion.getBlock(),
|
aliasMap.write(fileRegion.getBlock(),
|
||||||
@ -130,40 +154,53 @@ public void close() throws IOException {
|
|||||||
throw new UnsupportedOperationException("Unable to start "
|
throw new UnsupportedOperationException("Unable to start "
|
||||||
+ "InMemoryLevelDBAliasMapClient as security is enabled");
|
+ "InMemoryLevelDBAliasMapClient as security is enabled");
|
||||||
}
|
}
|
||||||
|
aliasMaps = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private InMemoryAliasMapProtocol getAliasMap(String blockPoolID)
|
||||||
|
throws IOException {
|
||||||
|
if (blockPoolID == null) {
|
||||||
|
throw new IOException("Block pool id required to get aliasmap reader");
|
||||||
|
}
|
||||||
|
// if a block pool id has been supplied, and doesn't match the associated
|
||||||
|
// block pool ids, return null.
|
||||||
|
for (InMemoryAliasMapProtocol aliasMap : aliasMaps) {
|
||||||
|
try {
|
||||||
|
String aliasMapBlockPoolId = aliasMap.getBlockPoolId();
|
||||||
|
if (aliasMapBlockPoolId != null &&
|
||||||
|
aliasMapBlockPoolId.equals(blockPoolID)) {
|
||||||
|
return aliasMap;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOG.error("Exception in retrieving block pool id {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IOException(
|
||||||
|
"Unable to retrive InMemoryAliasMap for block pool id " + blockPoolID);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reader<FileRegion> getReader(Reader.Options opts, String blockPoolID)
|
public Reader<FileRegion> getReader(Reader.Options opts, String blockPoolID)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (this.blockPoolID == null) {
|
InMemoryAliasMapProtocol aliasMap = getAliasMap(blockPoolID);
|
||||||
this.blockPoolID = aliasMap.getBlockPoolId();
|
LOG.info("Loading InMemoryAliasMapReader for block pool id {}",
|
||||||
}
|
blockPoolID);
|
||||||
// if a block pool id has been supplied, and doesn't match the associated
|
return new LevelDbReader(aliasMap);
|
||||||
// block pool id, return null.
|
|
||||||
if (blockPoolID != null && this.blockPoolID != null
|
|
||||||
&& !this.blockPoolID.equals(blockPoolID)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new LevelDbReader();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Writer<FileRegion> getWriter(Writer.Options opts, String blockPoolID)
|
public Writer<FileRegion> getWriter(Writer.Options opts, String blockPoolID)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (this.blockPoolID == null) {
|
InMemoryAliasMapProtocol aliasMap = getAliasMap(blockPoolID);
|
||||||
this.blockPoolID = aliasMap.getBlockPoolId();
|
LOG.info("Loading InMemoryAliasMapWriter for block pool id {}",
|
||||||
}
|
blockPoolID);
|
||||||
if (blockPoolID != null && !this.blockPoolID.equals(blockPoolID)) {
|
return new LevelDbWriter(aliasMap);
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new LevelDbWriter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setConf(Configuration conf) {
|
public void setConf(Configuration conf) {
|
||||||
this.conf = conf;
|
this.conf = conf;
|
||||||
this.aliasMap = new InMemoryAliasMapProtocolClientSideTranslatorPB(conf);
|
aliasMaps = InMemoryAliasMapProtocolClientSideTranslatorPB.init(conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -174,5 +211,4 @@ public Configuration getConf() {
|
|||||||
@Override
|
@Override
|
||||||
public void refresh() throws IOException {
|
public void refresh() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4817,9 +4817,27 @@
|
|||||||
|
|
||||||
<property>
|
<property>
|
||||||
<name>dfs.provided.aliasmap.inmemory.dnrpc-address</name>
|
<name>dfs.provided.aliasmap.inmemory.dnrpc-address</name>
|
||||||
<value>0.0.0.0:50200</value>
|
<value></value>
|
||||||
<description>
|
<description>
|
||||||
The address where the aliasmap server will be running
|
The address where the aliasmap server will be running. In the case of
|
||||||
|
HA/Federation where multiple namenodes exist, and if the Namenode is
|
||||||
|
configured to run the aliasmap server
|
||||||
|
(dfs.provided.aliasmap.inmemory.enabled is set to true),
|
||||||
|
the name service id is added to the name, e.g.,
|
||||||
|
dfs.provided.aliasmap.inmemory.rpc.address.EXAMPLENAMESERVICE.
|
||||||
|
The value of this property will take the form of host:rpc-port.
|
||||||
|
</description>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<property>
|
||||||
|
<name>dfs.provided.aliasmap.inmemory.rpc.bind-host</name>
|
||||||
|
<value></value>
|
||||||
|
<description>
|
||||||
|
The actual address the in-memory aliasmap server will bind to.
|
||||||
|
If this optional address is set, it overrides the hostname portion of
|
||||||
|
dfs.provided.aliasmap.inmemory.rpc.address.
|
||||||
|
This is useful for making the name node listen on all interfaces by
|
||||||
|
setting it to 0.0.0.0.
|
||||||
</description>
|
</description>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
@ -1187,7 +1187,7 @@ public NameNodeInfo[] getNameNodeInfos(String nameservice) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initNameNodeConf(Configuration conf, String nameserviceId, int nsIndex, String nnId,
|
protected void initNameNodeConf(Configuration conf, String nameserviceId, int nsIndex, String nnId,
|
||||||
boolean manageNameDfsDirs, boolean enableManagedDfsDirsRedundancy, int nnIndex)
|
boolean manageNameDfsDirs, boolean enableManagedDfsDirsRedundancy, int nnIndex)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (nameserviceId != null) {
|
if (nameserviceId != null) {
|
||||||
@ -1379,6 +1379,17 @@ private NameNodeInfo getNN(int nnIndex) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Integer> getNNIndexes(String nameserviceId) {
|
||||||
|
int count = 0;
|
||||||
|
List<Integer> nnIndexes = new ArrayList<>();
|
||||||
|
for (NameNodeInfo nn : namenodes.values()) {
|
||||||
|
if (nn.getNameserviceId().equals(nameserviceId)) {
|
||||||
|
nnIndexes.add(count);
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return nnIndexes;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wait for the given namenode to get out of safemode.
|
* wait for the given namenode to get out of safemode.
|
||||||
|
@ -227,7 +227,7 @@ public NNConf(String nnId) {
|
|||||||
this.nnId = nnId;
|
this.nnId = nnId;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getNnId() {
|
public String getNnId() {
|
||||||
return nnId;
|
return nnId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SERVICE_RPC_BIND_HOST_KEY;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@ -341,4 +342,10 @@ public void multipleReads() throws IOException {
|
|||||||
assertThat(actualFileRegions).containsExactlyInAnyOrder(
|
assertThat(actualFileRegions).containsExactlyInAnyOrder(
|
||||||
expectedFileRegions.toArray(new FileRegion[0]));
|
expectedFileRegions.toArray(new FileRegion[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testServerBindHost() throws Exception {
|
||||||
|
conf.set(DFS_NAMENODE_SERVICE_RPC_BIND_HOST_KEY, "0.0.0.0");
|
||||||
|
writeRead();
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,12 +24,18 @@
|
|||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.URI;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.ReadableByteChannel;
|
||||||
import java.nio.file.Files;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -44,14 +50,14 @@
|
|||||||
import org.apache.hadoop.hdfs.DFSClient;
|
import org.apache.hadoop.hdfs.DFSClient;
|
||||||
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
import org.apache.hadoop.hdfs.DFSConfigKeys;
|
||||||
import org.apache.hadoop.hdfs.DFSTestUtil;
|
import org.apache.hadoop.hdfs.DFSTestUtil;
|
||||||
|
import org.apache.hadoop.hdfs.DFSUtil;
|
||||||
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
import org.apache.hadoop.hdfs.DistributedFileSystem;
|
||||||
import org.apache.hadoop.hdfs.HdfsConfiguration;
|
import org.apache.hadoop.hdfs.HdfsConfiguration;
|
||||||
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
import org.apache.hadoop.hdfs.MiniDFSCluster;
|
||||||
|
import org.apache.hadoop.hdfs.MiniDFSNNTopology;
|
||||||
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
import org.apache.hadoop.hdfs.protocol.DatanodeInfo;
|
||||||
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
|
import org.apache.hadoop.hdfs.protocol.LocatedBlock;
|
||||||
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
|
import org.apache.hadoop.hdfs.protocol.LocatedBlocks;
|
||||||
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryAliasMap;
|
|
||||||
import org.apache.hadoop.hdfs.server.aliasmap.InMemoryLevelDBAliasMapServer;
|
|
||||||
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
|
import org.apache.hadoop.hdfs.server.blockmanagement.BlockInfo;
|
||||||
import org.apache.hadoop.hdfs.server.blockmanagement.BlockManager;
|
import org.apache.hadoop.hdfs.server.blockmanagement.BlockManager;
|
||||||
import org.apache.hadoop.hdfs.server.blockmanagement.BlockManagerTestUtil;
|
import org.apache.hadoop.hdfs.server.blockmanagement.BlockManagerTestUtil;
|
||||||
@ -60,8 +66,10 @@
|
|||||||
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeStatistics;
|
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeStatistics;
|
||||||
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeStorageInfo;
|
import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeStorageInfo;
|
||||||
import org.apache.hadoop.hdfs.server.blockmanagement.ProvidedStorageMap;
|
import org.apache.hadoop.hdfs.server.blockmanagement.ProvidedStorageMap;
|
||||||
|
import org.apache.hadoop.hdfs.server.common.HdfsServerConstants;
|
||||||
import org.apache.hadoop.hdfs.server.common.blockaliasmap.BlockAliasMap;
|
import org.apache.hadoop.hdfs.server.common.blockaliasmap.BlockAliasMap;
|
||||||
import org.apache.hadoop.hdfs.server.common.blockaliasmap.impl.InMemoryLevelDBAliasMapClient;
|
import org.apache.hadoop.hdfs.server.common.blockaliasmap.impl.InMemoryLevelDBAliasMapClient;
|
||||||
|
import org.apache.hadoop.hdfs.server.common.blockaliasmap.impl.LevelDBFileRegionAliasMap;
|
||||||
import org.apache.hadoop.hdfs.server.common.blockaliasmap.impl.TextFileRegionAliasMap;
|
import org.apache.hadoop.hdfs.server.common.blockaliasmap.impl.TextFileRegionAliasMap;
|
||||||
import org.apache.hadoop.hdfs.server.datanode.DataNode;
|
import org.apache.hadoop.hdfs.server.datanode.DataNode;
|
||||||
|
|
||||||
@ -71,6 +79,8 @@
|
|||||||
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeSpi;
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.FsVolumeSpi;
|
||||||
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsVolumeImpl;
|
import org.apache.hadoop.hdfs.server.datanode.fsdataset.impl.FsVolumeImpl;
|
||||||
import org.apache.hadoop.hdfs.server.protocol.StorageReport;
|
import org.apache.hadoop.hdfs.server.protocol.StorageReport;
|
||||||
|
import org.apache.hadoop.ipc.RemoteException;
|
||||||
|
import org.apache.hadoop.net.NetUtils;
|
||||||
import org.apache.hadoop.net.NodeBase;
|
import org.apache.hadoop.net.NodeBase;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@ -80,6 +90,12 @@
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_ENABLED;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_BIND_HOST;
|
||||||
|
import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_PROVIDED_ALIASMAP_LEVELDB_PATH;
|
||||||
|
import static org.apache.hadoop.hdfs.server.common.Util.fileAsURI;
|
||||||
import static org.apache.hadoop.hdfs.server.common.blockaliasmap.impl.TextFileRegionAliasMap.fileNameFromBlockPoolID;
|
import static org.apache.hadoop.hdfs.server.common.blockaliasmap.impl.TextFileRegionAliasMap.fileNameFromBlockPoolID;
|
||||||
import static org.apache.hadoop.net.NodeBase.PATH_SEPARATOR_STR;
|
import static org.apache.hadoop.net.NodeBase.PATH_SEPARATOR_STR;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
@ -106,6 +122,7 @@ public class ITestProvidedImplementation {
|
|||||||
private final int baseFileLen = 1024;
|
private final int baseFileLen = 1024;
|
||||||
private long providedDataSize = 0;
|
private long providedDataSize = 0;
|
||||||
private final String bpid = "BP-1234-10.1.1.1-1224";
|
private final String bpid = "BP-1234-10.1.1.1-1224";
|
||||||
|
private static final String clusterID = "CID-PROVIDED";
|
||||||
|
|
||||||
private Configuration conf;
|
private Configuration conf;
|
||||||
private MiniDFSCluster cluster;
|
private MiniDFSCluster cluster;
|
||||||
@ -214,36 +231,78 @@ void startCluster(Path nspath, int numDatanodes,
|
|||||||
StorageType[] storageTypes,
|
StorageType[] storageTypes,
|
||||||
StorageType[][] storageTypesPerDatanode,
|
StorageType[][] storageTypesPerDatanode,
|
||||||
boolean doFormat, String[] racks) throws IOException {
|
boolean doFormat, String[] racks) throws IOException {
|
||||||
|
startCluster(nspath, numDatanodes,
|
||||||
|
storageTypes, storageTypesPerDatanode,
|
||||||
|
doFormat, racks, null,
|
||||||
|
new MiniDFSCluster.Builder(conf));
|
||||||
|
}
|
||||||
|
|
||||||
|
void startCluster(Path nspath, int numDatanodes,
|
||||||
|
StorageType[] storageTypes,
|
||||||
|
StorageType[][] storageTypesPerDatanode,
|
||||||
|
boolean doFormat, String[] racks,
|
||||||
|
MiniDFSNNTopology topo,
|
||||||
|
MiniDFSCluster.Builder builder) throws IOException {
|
||||||
conf.set(DFS_NAMENODE_NAME_DIR_KEY, nspath.toString());
|
conf.set(DFS_NAMENODE_NAME_DIR_KEY, nspath.toString());
|
||||||
|
|
||||||
|
builder.format(doFormat)
|
||||||
|
.manageNameDfsDirs(doFormat)
|
||||||
|
.numDataNodes(numDatanodes)
|
||||||
|
.racks(racks);
|
||||||
if (storageTypesPerDatanode != null) {
|
if (storageTypesPerDatanode != null) {
|
||||||
cluster = new MiniDFSCluster.Builder(conf)
|
builder.storageTypes(storageTypesPerDatanode);
|
||||||
.format(doFormat)
|
|
||||||
.manageNameDfsDirs(doFormat)
|
|
||||||
.numDataNodes(numDatanodes)
|
|
||||||
.storageTypes(storageTypesPerDatanode)
|
|
||||||
.racks(racks)
|
|
||||||
.build();
|
|
||||||
} else if (storageTypes != null) {
|
} else if (storageTypes != null) {
|
||||||
cluster = new MiniDFSCluster.Builder(conf)
|
builder.storagesPerDatanode(storageTypes.length)
|
||||||
.format(doFormat)
|
.storageTypes(storageTypes);
|
||||||
.manageNameDfsDirs(doFormat)
|
|
||||||
.numDataNodes(numDatanodes)
|
|
||||||
.storagesPerDatanode(storageTypes.length)
|
|
||||||
.storageTypes(storageTypes)
|
|
||||||
.racks(racks)
|
|
||||||
.build();
|
|
||||||
} else {
|
|
||||||
cluster = new MiniDFSCluster.Builder(conf)
|
|
||||||
.format(doFormat)
|
|
||||||
.manageNameDfsDirs(doFormat)
|
|
||||||
.numDataNodes(numDatanodes)
|
|
||||||
.racks(racks)
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
if (topo != null) {
|
||||||
|
builder.nnTopology(topo);
|
||||||
|
// If HA or Federation is enabled and formatting is set to false,
|
||||||
|
// copy the FSImage to all Namenode directories.
|
||||||
|
if ((topo.isHA() || topo.isFederated()) && !doFormat) {
|
||||||
|
builder.manageNameDfsDirs(true);
|
||||||
|
builder.enableManagedDfsDirsRedundancy(false);
|
||||||
|
builder.manageNameDfsSharedDirs(false);
|
||||||
|
List<File> nnDirs =
|
||||||
|
getProvidedNamenodeDirs(MiniDFSCluster.getBaseDirectory(), topo);
|
||||||
|
for (File nnDir : nnDirs) {
|
||||||
|
MiniDFSCluster.copyNameDirs(
|
||||||
|
Collections.singletonList(nspath.toUri()),
|
||||||
|
Collections.singletonList(fileAsURI(nnDir)),
|
||||||
|
conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cluster = builder.build();
|
||||||
cluster.waitActive();
|
cluster.waitActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<File> getProvidedNamenodeDirs(String baseDir,
|
||||||
|
MiniDFSNNTopology topo) {
|
||||||
|
List<File> nnDirs = new ArrayList<>();
|
||||||
|
int nsCounter = 0;
|
||||||
|
for (MiniDFSNNTopology.NSConf nsConf : topo.getNameservices()) {
|
||||||
|
int nnCounter = nsCounter;
|
||||||
|
for (MiniDFSNNTopology.NNConf nnConf : nsConf.getNNs()) {
|
||||||
|
if (providedNameservice.equals(nsConf.getId())) {
|
||||||
|
// only add the first one
|
||||||
|
File[] nnFiles =
|
||||||
|
MiniDFSCluster.getNameNodeDirectory(
|
||||||
|
baseDir, nsCounter, nnCounter);
|
||||||
|
if (nnFiles == null || nnFiles.length == 0) {
|
||||||
|
throw new RuntimeException("Failed to get a location for the"
|
||||||
|
+ "Namenode directory for namespace: " + nsConf.getId()
|
||||||
|
+ " and namenodeId: " + nnConf.getNnId());
|
||||||
|
}
|
||||||
|
nnDirs.add(nnFiles[0]);
|
||||||
|
}
|
||||||
|
nnCounter++;
|
||||||
|
}
|
||||||
|
nsCounter = nnCounter;
|
||||||
|
}
|
||||||
|
return nnDirs;
|
||||||
|
}
|
||||||
|
|
||||||
@Test(timeout=20000)
|
@Test(timeout=20000)
|
||||||
public void testLoadImage() throws Exception {
|
public void testLoadImage() throws Exception {
|
||||||
final long seed = r.nextLong();
|
final long seed = r.nextLong();
|
||||||
@ -405,8 +464,8 @@ static Path removePrefix(Path base, Path walk) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyFileSystemContents() throws Exception {
|
private void verifyFileSystemContents(int nnIndex) throws Exception {
|
||||||
FileSystem fs = cluster.getFileSystem();
|
FileSystem fs = cluster.getFileSystem(nnIndex);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
// read NN metadata, verify contents match
|
// read NN metadata, verify contents match
|
||||||
for (TreePath e : new FSTreeWalk(providedPath, conf)) {
|
for (TreePath e : new FSTreeWalk(providedPath, conf)) {
|
||||||
@ -766,41 +825,255 @@ public void testNumberOfProvidedLocationsManyBlocks() throws Exception {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private File createInMemoryAliasMapImage() throws Exception {
|
||||||
@Test
|
conf.setClass(ImageWriter.Options.UGI_CLASS, FsUGIResolver.class,
|
||||||
public void testInMemoryAliasMap() throws Exception {
|
UGIResolver.class);
|
||||||
conf.setClass(ImageWriter.Options.UGI_CLASS,
|
|
||||||
FsUGIResolver.class, UGIResolver.class);
|
|
||||||
conf.setClass(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_CLASS,
|
conf.setClass(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_CLASS,
|
||||||
InMemoryLevelDBAliasMapClient.class, BlockAliasMap.class);
|
InMemoryLevelDBAliasMapClient.class, BlockAliasMap.class);
|
||||||
conf.set(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS,
|
conf.set(DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS, "localhost:32445");
|
||||||
"localhost:32445");
|
|
||||||
File tempDirectory =
|
File tempDirectory =
|
||||||
Files.createTempDirectory("in-memory-alias-map").toFile();
|
new File(new Path(nnDirPath, "in-memory-alias-map").toUri());
|
||||||
File leveDBPath = new File(tempDirectory, bpid);
|
File levelDBDir = new File(tempDirectory, bpid);
|
||||||
leveDBPath.mkdirs();
|
levelDBDir.mkdirs();
|
||||||
conf.set(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR,
|
conf.set(DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR,
|
||||||
tempDirectory.getAbsolutePath());
|
tempDirectory.getAbsolutePath());
|
||||||
conf.setBoolean(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_INMEMORY_ENABLED, true);
|
|
||||||
conf.setInt(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_LOAD_RETRIES, 10);
|
conf.setInt(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_LOAD_RETRIES, 10);
|
||||||
InMemoryLevelDBAliasMapServer levelDBAliasMapServer =
|
conf.set(DFS_PROVIDED_ALIASMAP_LEVELDB_PATH,
|
||||||
new InMemoryLevelDBAliasMapServer(InMemoryAliasMap::init, bpid);
|
tempDirectory.getAbsolutePath());
|
||||||
levelDBAliasMapServer.setConf(conf);
|
|
||||||
levelDBAliasMapServer.start();
|
|
||||||
|
|
||||||
createImage(new FSTreeWalk(providedPath, conf),
|
createImage(new FSTreeWalk(providedPath, conf),
|
||||||
nnDirPath,
|
nnDirPath,
|
||||||
FixedBlockResolver.class, "",
|
FixedBlockResolver.class, clusterID,
|
||||||
InMemoryLevelDBAliasMapClient.class);
|
LevelDBFileRegionAliasMap.class);
|
||||||
levelDBAliasMapServer.close();
|
|
||||||
|
|
||||||
|
return tempDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInMemoryAliasMap() throws Exception {
|
||||||
|
File aliasMapImage = createInMemoryAliasMapImage();
|
||||||
// start cluster with two datanodes,
|
// start cluster with two datanodes,
|
||||||
// each with 1 PROVIDED volume and other DISK volume
|
// each with 1 PROVIDED volume and other DISK volume
|
||||||
|
conf.setBoolean(DFS_PROVIDED_ALIASMAP_INMEMORY_ENABLED, true);
|
||||||
|
conf.setInt(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_LOAD_RETRIES, 10);
|
||||||
startCluster(nnDirPath, 2,
|
startCluster(nnDirPath, 2,
|
||||||
new StorageType[] {StorageType.PROVIDED, StorageType.DISK},
|
new StorageType[] {StorageType.PROVIDED, StorageType.DISK},
|
||||||
null, false);
|
null, false);
|
||||||
verifyFileSystemContents();
|
verifyFileSystemContents(0);
|
||||||
FileUtils.deleteDirectory(tempDirectory);
|
FileUtils.deleteDirectory(aliasMapImage);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a free port that hasn't been assigned yet.
|
||||||
|
*
|
||||||
|
* @param usedPorts set of ports that have already been assigned.
|
||||||
|
* @param maxTrials maximum number of random ports to try before failure.
|
||||||
|
* @return an unassigned port.
|
||||||
|
*/
|
||||||
|
private int getUnAssignedPort(Set<Integer> usedPorts, int maxTrials) {
|
||||||
|
int count = 0;
|
||||||
|
while (count < maxTrials) {
|
||||||
|
int port = NetUtils.getFreeSocketPort();
|
||||||
|
if (usedPorts.contains(port)) {
|
||||||
|
count++;
|
||||||
|
} else {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String providedNameservice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends the {@link MiniDFSCluster.Builder} to create instances of
|
||||||
|
* {@link MiniDFSClusterBuilderAliasMap}.
|
||||||
|
*/
|
||||||
|
private static class MiniDFSClusterBuilderAliasMap
|
||||||
|
extends MiniDFSCluster.Builder {
|
||||||
|
|
||||||
|
MiniDFSClusterBuilderAliasMap(Configuration conf) {
|
||||||
|
super(conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MiniDFSCluster build() throws IOException {
|
||||||
|
return new MiniDFSClusterAliasMap(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends {@link MiniDFSCluster} to correctly configure the InMemoryAliasMap.
|
||||||
|
*/
|
||||||
|
private static class MiniDFSClusterAliasMap extends MiniDFSCluster {
|
||||||
|
|
||||||
|
private Map<String, Collection<URI>> formattedDirsByNamespaceId;
|
||||||
|
private Set<Integer> completedNNs;
|
||||||
|
|
||||||
|
MiniDFSClusterAliasMap(MiniDFSCluster.Builder builder) throws IOException {
|
||||||
|
super(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initNameNodeConf(Configuration conf, String nameserviceId,
|
||||||
|
int nsIndex, String nnId, boolean manageNameDfsDirs,
|
||||||
|
boolean enableManagedDfsDirsRedundancy, int nnIndex)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
if (formattedDirsByNamespaceId == null) {
|
||||||
|
formattedDirsByNamespaceId = new HashMap<>();
|
||||||
|
completedNNs = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
super.initNameNodeConf(conf, nameserviceId, nsIndex, nnId,
|
||||||
|
manageNameDfsDirs, enableManagedDfsDirsRedundancy, nnIndex);
|
||||||
|
|
||||||
|
if (providedNameservice.equals(nameserviceId)) {
|
||||||
|
// configure the InMemoryAliasMp.
|
||||||
|
conf.setBoolean(DFS_PROVIDED_ALIASMAP_INMEMORY_ENABLED, true);
|
||||||
|
String directory = conf.get(DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR);
|
||||||
|
if (directory == null) {
|
||||||
|
throw new IllegalArgumentException("In-memory alias map configured"
|
||||||
|
+ "with the proper location; Set "
|
||||||
|
+ DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR);
|
||||||
|
}
|
||||||
|
// get the name of the directory (final component in path) used for map.
|
||||||
|
// Assume that the aliasmap configured with the same final component
|
||||||
|
// name in all Namenodes but is located in the path specified by
|
||||||
|
// DFS_NAMENODE_NAME_DIR_KEY
|
||||||
|
String dirName = new Path(directory).getName();
|
||||||
|
String nnDir =
|
||||||
|
conf.getTrimmedStringCollection(DFS_NAMENODE_NAME_DIR_KEY)
|
||||||
|
.iterator().next();
|
||||||
|
conf.set(DFS_PROVIDED_ALIASMAP_INMEMORY_LEVELDB_DIR,
|
||||||
|
new File(new Path(nnDir, dirName).toUri()).getAbsolutePath());
|
||||||
|
conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_PROVIDED_ENABLED, true);
|
||||||
|
} else {
|
||||||
|
if (!completedNNs.contains(nnIndex)) {
|
||||||
|
// format the NN directories for non-provided namespaces
|
||||||
|
// if the directory for a namespace has been formatted, copy it over.
|
||||||
|
Collection<URI> namespaceDirs = FSNamesystem.getNamespaceDirs(conf);
|
||||||
|
if (formattedDirsByNamespaceId.containsKey(nameserviceId)) {
|
||||||
|
copyNameDirs(formattedDirsByNamespaceId.get(nameserviceId),
|
||||||
|
namespaceDirs, conf);
|
||||||
|
} else {
|
||||||
|
for (URI nameDirUri : namespaceDirs) {
|
||||||
|
File nameDir = new File(nameDirUri);
|
||||||
|
if (nameDir.exists() && !FileUtil.fullyDelete(nameDir)) {
|
||||||
|
throw new IOException("Could not fully delete " + nameDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HdfsServerConstants.StartupOption.FORMAT.setClusterId(clusterID);
|
||||||
|
DFSTestUtil.formatNameNode(conf);
|
||||||
|
formattedDirsByNamespaceId.put(nameserviceId, namespaceDirs);
|
||||||
|
}
|
||||||
|
conf.setBoolean(DFSConfigKeys.DFS_NAMENODE_PROVIDED_ENABLED, false);
|
||||||
|
completedNNs.add(nnIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the addresseses of the InMemoryAliasMap.
|
||||||
|
*
|
||||||
|
* @param topology the MiniDFS topology to use.
|
||||||
|
* @param providedNameservice the nameservice id that supports provided.
|
||||||
|
*/
|
||||||
|
private void configureAliasMapAddresses(MiniDFSNNTopology topology,
|
||||||
|
String providedNameservice) {
|
||||||
|
conf.unset(DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS);
|
||||||
|
Set<Integer> assignedPorts = new HashSet<>();
|
||||||
|
for (MiniDFSNNTopology.NSConf nsConf : topology.getNameservices()) {
|
||||||
|
for (MiniDFSNNTopology.NNConf nnConf : nsConf.getNNs()) {
|
||||||
|
if (providedNameservice.equals(nsConf.getId())) {
|
||||||
|
String key =
|
||||||
|
DFSUtil.addKeySuffixes(DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_ADDRESS,
|
||||||
|
nsConf.getId(), nnConf.getNnId());
|
||||||
|
int port = getUnAssignedPort(assignedPorts, 10);
|
||||||
|
if (port == -1) {
|
||||||
|
throw new RuntimeException("No free ports available");
|
||||||
|
}
|
||||||
|
assignedPorts.add(port);
|
||||||
|
conf.set(key, "127.0.0.1:" + port);
|
||||||
|
|
||||||
|
String binHostKey =
|
||||||
|
DFSUtil.addKeySuffixes(
|
||||||
|
DFS_PROVIDED_ALIASMAP_INMEMORY_RPC_BIND_HOST,
|
||||||
|
nsConf.getId(), nnConf.getNnId());
|
||||||
|
conf.set(binHostKey, "0.0.0.0");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the mounted contents of the Filesystem.
|
||||||
|
*
|
||||||
|
* @param topology the topology of the cluster.
|
||||||
|
* @param providedNameservice the namespace id of the provided namenodes.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private void verifyPathsWithHAFailoverIfNecessary(MiniDFSNNTopology topology,
|
||||||
|
String providedNameservice) throws Exception {
|
||||||
|
List<Integer> nnIndexes = cluster.getNNIndexes(providedNameservice);
|
||||||
|
if (topology.isHA()) {
|
||||||
|
int nn1 = nnIndexes.get(0);
|
||||||
|
int nn2 = nnIndexes.get(1);
|
||||||
|
try {
|
||||||
|
verifyFileSystemContents(nn1);
|
||||||
|
fail("Read operation should fail as no Namenode is active");
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
LOG.info("verifyPaths failed!. Expected exception: {}" + e);
|
||||||
|
}
|
||||||
|
cluster.transitionToActive(nn1);
|
||||||
|
LOG.info("Verifying data from NN with index = {}", nn1);
|
||||||
|
verifyFileSystemContents(nn1);
|
||||||
|
// transition to the second namenode.
|
||||||
|
cluster.transitionToStandby(nn1);
|
||||||
|
cluster.transitionToActive(nn2);
|
||||||
|
LOG.info("Verifying data from NN with index = {}", nn2);
|
||||||
|
verifyFileSystemContents(nn2);
|
||||||
|
|
||||||
|
cluster.shutdownNameNodes();
|
||||||
|
try {
|
||||||
|
verifyFileSystemContents(nn2);
|
||||||
|
fail("Read operation should fail as no Namenode is active");
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
LOG.info("verifyPaths failed!. Expected exception: {}" + e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
verifyFileSystemContents(nnIndexes.get(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInMemoryAliasMapMultiTopologies() throws Exception {
|
||||||
|
MiniDFSNNTopology[] topologies =
|
||||||
|
new MiniDFSNNTopology[] {
|
||||||
|
MiniDFSNNTopology.simpleHATopology(),
|
||||||
|
MiniDFSNNTopology.simpleFederatedTopology(3),
|
||||||
|
MiniDFSNNTopology.simpleHAFederatedTopology(3)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (MiniDFSNNTopology topology : topologies) {
|
||||||
|
LOG.info("Starting test with topology with HA = {}, federation = {}",
|
||||||
|
topology.isHA(), topology.isFederated());
|
||||||
|
setSeed();
|
||||||
|
createInMemoryAliasMapImage();
|
||||||
|
conf.setBoolean(DFS_PROVIDED_ALIASMAP_INMEMORY_ENABLED, true);
|
||||||
|
conf.setInt(DFSConfigKeys.DFS_PROVIDED_ALIASMAP_LOAD_RETRIES, 10);
|
||||||
|
providedNameservice = topology.getNameservices().get(0).getId();
|
||||||
|
// configure the AliasMap addresses
|
||||||
|
configureAliasMapAddresses(topology, providedNameservice);
|
||||||
|
startCluster(nnDirPath, 2,
|
||||||
|
new StorageType[] {StorageType.PROVIDED, StorageType.DISK},
|
||||||
|
null, false, null, topology,
|
||||||
|
new MiniDFSClusterBuilderAliasMap(conf));
|
||||||
|
|
||||||
|
verifyPathsWithHAFailoverIfNecessary(topology, providedNameservice);
|
||||||
|
shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DatanodeDescriptor getDatanodeDescriptor(DatanodeManager dnm,
|
private DatanodeDescriptor getDatanodeDescriptor(DatanodeManager dnm,
|
||||||
@ -919,7 +1192,7 @@ public void testProvidedWithHierarchicalTopology() throws Exception {
|
|||||||
startCluster(nnDirPath, racks.length,
|
startCluster(nnDirPath, racks.length,
|
||||||
new StorageType[]{StorageType.PROVIDED, StorageType.DISK},
|
new StorageType[]{StorageType.PROVIDED, StorageType.DISK},
|
||||||
null, false, racks);
|
null, false, racks);
|
||||||
verifyFileSystemContents();
|
verifyFileSystemContents(0);
|
||||||
setAndUnsetReplication("/" + filePrefix + (numFiles - 1) + fileSuffix);
|
setAndUnsetReplication("/" + filePrefix + (numFiles - 1) + fileSuffix);
|
||||||
cluster.shutdown();
|
cluster.shutdown();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user