| /** |
| * 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.net; |
| |
| import java.util.*; |
| import java.util.concurrent.ConcurrentHashMap; |
| |
| import org.apache.hadoop.classification.InterfaceAudience; |
| import org.apache.hadoop.classification.InterfaceStability; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.hadoop.fs.CommonConfigurationKeys; |
| |
| |
| /** |
| * This class extends ScriptBasedMapping class and implements |
| * the {@link DNSToSwitchMappingWithDependency} interface using |
| * a script configured via the |
| * {@link CommonConfigurationKeys#NET_DEPENDENCY_SCRIPT_FILE_NAME_KEY} option. |
| * <p> |
| * It contains a static class <code>RawScriptBasedMappingWithDependency</code> |
| * that performs the getDependency work. |
| */ |
| @InterfaceAudience.Private |
| @InterfaceStability.Evolving |
| public class ScriptBasedMappingWithDependency extends ScriptBasedMapping |
| implements DNSToSwitchMappingWithDependency { |
| /** |
| * key to the dependency script filename {@value} |
| */ |
| static final String DEPENDENCY_SCRIPT_FILENAME_KEY = |
| CommonConfigurationKeys.NET_DEPENDENCY_SCRIPT_FILE_NAME_KEY; |
| |
| private Map<String, List<String>> dependencyCache = |
| new ConcurrentHashMap<String, List<String>>(); |
| |
| /** |
| * Create an instance with the default configuration. |
| * <p> |
| * Calling {@link #setConf(Configuration)} will trigger a |
| * re-evaluation of the configuration settings and so be used to |
| * set up the mapping script. |
| */ |
| public ScriptBasedMappingWithDependency() { |
| super(new RawScriptBasedMappingWithDependency()); |
| } |
| |
| /** |
| * Get the cached mapping and convert it to its real type |
| * @return the inner raw script mapping. |
| */ |
| private RawScriptBasedMappingWithDependency getRawMapping() { |
| return (RawScriptBasedMappingWithDependency)rawMapping; |
| } |
| |
| @Override |
| public String toString() { |
| return "script-based mapping with " + getRawMapping().toString(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * This will get called in the superclass constructor, so a check is needed |
| * to ensure that the raw mapping is defined before trying to relaying a null |
| * configuration. |
| * @param conf |
| */ |
| @Override |
| public void setConf(Configuration conf) { |
| super.setConf(conf); |
| getRawMapping().setConf(conf); |
| } |
| |
| /** |
| * Get dependencies in the topology for a given host |
| * @param name - host name for which we are getting dependency |
| * @return a list of hosts dependent on the provided host name |
| */ |
| @Override |
| public List<String> getDependency(String name) { |
| //normalize all input names to be in the form of IP addresses |
| name = NetUtils.normalizeHostName(name); |
| |
| if (name==null) { |
| return Collections.emptyList(); |
| } |
| |
| List<String> dependencies = dependencyCache.get(name); |
| if (dependencies == null) { |
| //not cached |
| dependencies = getRawMapping().getDependency(name); |
| if(dependencies != null) { |
| dependencyCache.put(name, dependencies); |
| } |
| } |
| |
| return dependencies; |
| } |
| |
| /** |
| * This is the uncached script mapping that is fed into the cache managed |
| * by the superclass {@link CachedDNSToSwitchMapping} |
| */ |
| private static final class RawScriptBasedMappingWithDependency |
| extends ScriptBasedMapping.RawScriptBasedMapping |
| implements DNSToSwitchMappingWithDependency { |
| private String dependencyScriptName; |
| |
| /** |
| * Set the configuration and extract the configuration parameters of interest |
| * @param conf the new configuration |
| */ |
| @Override |
| public void setConf (Configuration conf) { |
| super.setConf(conf); |
| if (conf != null) { |
| dependencyScriptName = conf.get(DEPENDENCY_SCRIPT_FILENAME_KEY); |
| } else { |
| dependencyScriptName = null; |
| } |
| } |
| |
| /** |
| * Constructor. The mapping is not ready to use until |
| * {@link #setConf(Configuration)} has been called |
| */ |
| public RawScriptBasedMappingWithDependency() {} |
| |
| @Override |
| public List<String> getDependency(String name) { |
| if (name==null || dependencyScriptName==null) { |
| return Collections.emptyList(); |
| } |
| |
| List <String> m = new LinkedList<String>(); |
| List <String> args = new ArrayList<String>(1); |
| args.add(name); |
| |
| String output = runResolveCommand(args,dependencyScriptName); |
| if (output != null) { |
| StringTokenizer allSwitchInfo = new StringTokenizer(output); |
| while (allSwitchInfo.hasMoreTokens()) { |
| String switchInfo = allSwitchInfo.nextToken(); |
| m.add(switchInfo); |
| } |
| } else { |
| // an error occurred. return null to signify this. |
| // (exn was already logged in runResolveCommand) |
| return null; |
| } |
| |
| return m; |
| } |
| |
| @Override |
| public String toString() { |
| return "dependency script " + dependencyScriptName; |
| } |
| } |
| } |