001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.hadoop.net; 019 020 import java.util.ArrayList; 021 import java.util.List; 022 import java.util.Map; 023 import java.util.concurrent.ConcurrentHashMap; 024 025 import org.apache.hadoop.classification.InterfaceAudience; 026 import org.apache.hadoop.classification.InterfaceStability; 027 028 /** 029 * A cached implementation of DNSToSwitchMapping that takes an 030 * raw DNSToSwitchMapping and stores the resolved network location in 031 * a cache. The following calls to a resolved network location 032 * will get its location from the cache. 033 * 034 */ 035 @InterfaceAudience.Public 036 @InterfaceStability.Evolving 037 public class CachedDNSToSwitchMapping extends AbstractDNSToSwitchMapping { 038 private Map<String, String> cache = new ConcurrentHashMap<String, String>(); 039 040 /** 041 * The uncached mapping 042 */ 043 protected final DNSToSwitchMapping rawMapping; 044 045 /** 046 * cache a raw DNS mapping 047 * @param rawMapping the raw mapping to cache 048 */ 049 public CachedDNSToSwitchMapping(DNSToSwitchMapping rawMapping) { 050 this.rawMapping = rawMapping; 051 } 052 053 /** 054 * @param names a list of hostnames to probe for being cached 055 * @return the hosts from 'names' that have not been cached previously 056 */ 057 private List<String> getUncachedHosts(List<String> names) { 058 // find out all names without cached resolved location 059 List<String> unCachedHosts = new ArrayList<String>(names.size()); 060 for (String name : names) { 061 if (cache.get(name) == null) { 062 unCachedHosts.add(name); 063 } 064 } 065 return unCachedHosts; 066 } 067 068 /** 069 * Caches the resolved host:rack mappings. The two list 070 * parameters must be of equal size. 071 * 072 * @param uncachedHosts a list of hosts that were uncached 073 * @param resolvedHosts a list of resolved host entries where the element 074 * at index(i) is the resolved value for the entry in uncachedHosts[i] 075 */ 076 private void cacheResolvedHosts(List<String> uncachedHosts, 077 List<String> resolvedHosts) { 078 // Cache the result 079 if (resolvedHosts != null) { 080 for (int i=0; i<uncachedHosts.size(); i++) { 081 cache.put(uncachedHosts.get(i), resolvedHosts.get(i)); 082 } 083 } 084 } 085 086 /** 087 * @param names a list of hostnames to look up (can be be empty) 088 * @return the cached resolution of the list of hostnames/addresses. 089 * or null if any of the names are not currently in the cache 090 */ 091 private List<String> getCachedHosts(List<String> names) { 092 List<String> result = new ArrayList<String>(names.size()); 093 // Construct the result 094 for (String name : names) { 095 String networkLocation = cache.get(name); 096 if (networkLocation != null) { 097 result.add(networkLocation); 098 } else { 099 return null; 100 } 101 } 102 return result; 103 } 104 105 @Override 106 public List<String> resolve(List<String> names) { 107 // normalize all input names to be in the form of IP addresses 108 names = NetUtils.normalizeHostNames(names); 109 110 List <String> result = new ArrayList<String>(names.size()); 111 if (names.isEmpty()) { 112 return result; 113 } 114 115 List<String> uncachedHosts = getUncachedHosts(names); 116 117 // Resolve the uncached hosts 118 List<String> resolvedHosts = rawMapping.resolve(uncachedHosts); 119 //cache them 120 cacheResolvedHosts(uncachedHosts, resolvedHosts); 121 //now look up the entire list in the cache 122 return getCachedHosts(names); 123 124 } 125 126 /** 127 * Delegate the switch topology query to the raw mapping, via 128 * {@link AbstractDNSToSwitchMapping#isMappingSingleSwitch(DNSToSwitchMapping)} 129 * @return true iff the raw mapper is considered single-switch. 130 */ 131 @Override 132 public boolean isSingleSwitch() { 133 return isMappingSingleSwitch(rawMapping); 134 } 135 }