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 */ 018package org.apache.hadoop.net; 019 020import java.util.ArrayList; 021import java.util.HashMap; 022import java.util.List; 023import java.util.Map; 024import java.util.concurrent.ConcurrentHashMap; 025 026import org.apache.hadoop.classification.InterfaceAudience; 027import org.apache.hadoop.classification.InterfaceStability; 028 029/** 030 * A cached implementation of DNSToSwitchMapping that takes an 031 * raw DNSToSwitchMapping and stores the resolved network location in 032 * a cache. The following calls to a resolved network location 033 * will get its location from the cache. 034 * 035 */ 036@InterfaceAudience.Public 037@InterfaceStability.Evolving 038public class CachedDNSToSwitchMapping extends AbstractDNSToSwitchMapping { 039 private Map<String, String> cache = new ConcurrentHashMap<String, String>(); 040 041 /** 042 * The uncached mapping 043 */ 044 protected final DNSToSwitchMapping rawMapping; 045 046 /** 047 * cache a raw DNS mapping 048 * @param rawMapping the raw mapping to cache 049 */ 050 public CachedDNSToSwitchMapping(DNSToSwitchMapping rawMapping) { 051 this.rawMapping = rawMapping; 052 } 053 054 /** 055 * @param names a list of hostnames to probe for being cached 056 * @return the hosts from 'names' that have not been cached previously 057 */ 058 private List<String> getUncachedHosts(List<String> names) { 059 // find out all names without cached resolved location 060 List<String> unCachedHosts = new ArrayList<String>(names.size()); 061 for (String name : names) { 062 if (cache.get(name) == null) { 063 unCachedHosts.add(name); 064 } 065 } 066 return unCachedHosts; 067 } 068 069 /** 070 * Caches the resolved host:rack mappings. The two list 071 * parameters must be of equal size. 072 * 073 * @param uncachedHosts a list of hosts that were uncached 074 * @param resolvedHosts a list of resolved host entries where the element 075 * at index(i) is the resolved value for the entry in uncachedHosts[i] 076 */ 077 private void cacheResolvedHosts(List<String> uncachedHosts, 078 List<String> resolvedHosts) { 079 // Cache the result 080 if (resolvedHosts != null) { 081 for (int i=0; i<uncachedHosts.size(); i++) { 082 cache.put(uncachedHosts.get(i), resolvedHosts.get(i)); 083 } 084 } 085 } 086 087 /** 088 * @param names a list of hostnames to look up (can be be empty) 089 * @return the cached resolution of the list of hostnames/addresses. 090 * or null if any of the names are not currently in the cache 091 */ 092 private List<String> getCachedHosts(List<String> names) { 093 List<String> result = new ArrayList<String>(names.size()); 094 // Construct the result 095 for (String name : names) { 096 String networkLocation = cache.get(name); 097 if (networkLocation != null) { 098 result.add(networkLocation); 099 } else { 100 return null; 101 } 102 } 103 return result; 104 } 105 106 @Override 107 public List<String> resolve(List<String> names) { 108 // normalize all input names to be in the form of IP addresses 109 names = NetUtils.normalizeHostNames(names); 110 111 List <String> result = new ArrayList<String>(names.size()); 112 if (names.isEmpty()) { 113 return result; 114 } 115 116 List<String> uncachedHosts = getUncachedHosts(names); 117 118 // Resolve the uncached hosts 119 List<String> resolvedHosts = rawMapping.resolve(uncachedHosts); 120 //cache them 121 cacheResolvedHosts(uncachedHosts, resolvedHosts); 122 //now look up the entire list in the cache 123 return getCachedHosts(names); 124 125 } 126 127 /** 128 * Get the (host x switch) map. 129 * @return a copy of the cached map of hosts to rack 130 */ 131 @Override 132 public Map<String, String> getSwitchMap() { 133 Map<String, String > switchMap = new HashMap<String, String>(cache); 134 return switchMap; 135 } 136 137 138 @Override 139 public String toString() { 140 return "cached switch mapping relaying to " + rawMapping; 141 } 142 143 /** 144 * Delegate the switch topology query to the raw mapping, via 145 * {@link AbstractDNSToSwitchMapping#isMappingSingleSwitch(DNSToSwitchMapping)} 146 * @return true iff the raw mapper is considered single-switch. 147 */ 148 @Override 149 public boolean isSingleSwitch() { 150 return isMappingSingleSwitch(rawMapping); 151 } 152 153 @Override 154 public void reloadCachedMappings() { 155 cache.clear(); 156 } 157 158 @Override 159 public void reloadCachedMappings(List<String> names) { 160 for (String name : names) { 161 cache.remove(name); 162 } 163 } 164}