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 019 package org.apache.hadoop.hdfs; 020 021 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_HA_NAMENODES_KEY_PREFIX; 022 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_HA_NAMENODE_ID_KEY; 023 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_BACKUP_ADDRESS_KEY; 024 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTPS_ADDRESS_DEFAULT; 025 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTPS_ADDRESS_KEY; 026 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTP_ADDRESS_DEFAULT; 027 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_HTTP_ADDRESS_KEY; 028 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY; 029 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SECONDARY_HTTP_ADDRESS_KEY; 030 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY; 031 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMESERVICES; 032 import static org.apache.hadoop.hdfs.DFSConfigKeys.DFS_NAMESERVICE_ID; 033 034 import java.io.IOException; 035 import java.io.PrintStream; 036 import java.io.UnsupportedEncodingException; 037 import java.net.InetSocketAddress; 038 import java.net.URI; 039 import java.net.URISyntaxException; 040 import java.security.SecureRandom; 041 import java.util.Collection; 042 import java.util.Collections; 043 import java.util.Comparator; 044 import java.util.HashMap; 045 import java.util.HashSet; 046 import java.util.List; 047 import java.util.Map; 048 import java.util.Random; 049 import java.util.Set; 050 import java.util.concurrent.TimeUnit; 051 052 import javax.net.SocketFactory; 053 054 import org.apache.commons.cli.CommandLine; 055 import org.apache.commons.cli.CommandLineParser; 056 import org.apache.commons.cli.Option; 057 import org.apache.commons.cli.Options; 058 import org.apache.commons.cli.ParseException; 059 import org.apache.commons.cli.PosixParser; 060 import org.apache.commons.logging.Log; 061 import org.apache.commons.logging.LogFactory; 062 import org.apache.hadoop.HadoopIllegalArgumentException; 063 import org.apache.hadoop.classification.InterfaceAudience; 064 import org.apache.hadoop.conf.Configuration; 065 import org.apache.hadoop.fs.BlockLocation; 066 import org.apache.hadoop.fs.FileSystem; 067 import org.apache.hadoop.fs.Path; 068 import org.apache.hadoop.hdfs.protocol.AlreadyBeingCreatedException; 069 import org.apache.hadoop.hdfs.protocol.ClientDatanodeProtocol; 070 import org.apache.hadoop.hdfs.protocol.DatanodeID; 071 import org.apache.hadoop.hdfs.protocol.DatanodeInfo; 072 import org.apache.hadoop.hdfs.protocol.HdfsConstants; 073 import org.apache.hadoop.hdfs.protocol.LocatedBlock; 074 import org.apache.hadoop.hdfs.protocol.LocatedBlocks; 075 import org.apache.hadoop.hdfs.protocolPB.ClientDatanodeProtocolTranslatorPB; 076 import org.apache.hadoop.hdfs.server.namenode.NameNode; 077 import org.apache.hadoop.io.retry.RetryPolicies; 078 import org.apache.hadoop.io.retry.RetryPolicy; 079 import org.apache.hadoop.io.retry.RetryProxy; 080 import org.apache.hadoop.ipc.ProtobufRpcEngine; 081 import org.apache.hadoop.ipc.RPC; 082 import org.apache.hadoop.net.NetUtils; 083 import org.apache.hadoop.net.NodeBase; 084 import org.apache.hadoop.security.SecurityUtil; 085 import org.apache.hadoop.security.UserGroupInformation; 086 import org.apache.hadoop.util.StringUtils; 087 import org.apache.hadoop.util.ToolRunner; 088 089 import com.google.common.base.Charsets; 090 import com.google.common.base.Joiner; 091 import com.google.common.base.Preconditions; 092 import com.google.common.collect.Lists; 093 import com.google.common.collect.Maps; 094 import com.google.common.primitives.SignedBytes; 095 import com.google.protobuf.BlockingService; 096 097 @InterfaceAudience.Private 098 public class DFSUtil { 099 public static final Log LOG = LogFactory.getLog(DFSUtil.class.getName()); 100 101 public static final byte[] EMPTY_BYTES = {}; 102 103 /** Compare two byte arrays by lexicographical order. */ 104 public static int compareBytes(byte[] left, byte[] right) { 105 if (left == null) { 106 left = EMPTY_BYTES; 107 } 108 if (right == null) { 109 right = EMPTY_BYTES; 110 } 111 return SignedBytes.lexicographicalComparator().compare(left, right); 112 } 113 114 private DFSUtil() { /* Hidden constructor */ } 115 private static final ThreadLocal<Random> RANDOM = new ThreadLocal<Random>() { 116 @Override 117 protected Random initialValue() { 118 return new Random(); 119 } 120 }; 121 122 private static final ThreadLocal<SecureRandom> SECURE_RANDOM = new ThreadLocal<SecureRandom>() { 123 @Override 124 protected SecureRandom initialValue() { 125 return new SecureRandom(); 126 } 127 }; 128 129 /** @return a pseudo random number generator. */ 130 public static Random getRandom() { 131 return RANDOM.get(); 132 } 133 134 /** @return a pseudo secure random number generator. */ 135 public static SecureRandom getSecureRandom() { 136 return SECURE_RANDOM.get(); 137 } 138 139 /** 140 * Compartor for sorting DataNodeInfo[] based on decommissioned states. 141 * Decommissioned nodes are moved to the end of the array on sorting with 142 * this compartor. 143 */ 144 public static final Comparator<DatanodeInfo> DECOM_COMPARATOR = 145 new Comparator<DatanodeInfo>() { 146 @Override 147 public int compare(DatanodeInfo a, DatanodeInfo b) { 148 return a.isDecommissioned() == b.isDecommissioned() ? 0 : 149 a.isDecommissioned() ? 1 : -1; 150 } 151 }; 152 153 154 /** 155 * Comparator for sorting DataNodeInfo[] based on decommissioned/stale states. 156 * Decommissioned/stale nodes are moved to the end of the array on sorting 157 * with this comparator. 158 */ 159 @InterfaceAudience.Private 160 public static class DecomStaleComparator implements Comparator<DatanodeInfo> { 161 private long staleInterval; 162 163 /** 164 * Constructor of DecomStaleComparator 165 * 166 * @param interval 167 * The time interval for marking datanodes as stale is passed from 168 * outside, since the interval may be changed dynamically 169 */ 170 public DecomStaleComparator(long interval) { 171 this.staleInterval = interval; 172 } 173 174 @Override 175 public int compare(DatanodeInfo a, DatanodeInfo b) { 176 // Decommissioned nodes will still be moved to the end of the list 177 if (a.isDecommissioned()) { 178 return b.isDecommissioned() ? 0 : 1; 179 } else if (b.isDecommissioned()) { 180 return -1; 181 } 182 // Stale nodes will be moved behind the normal nodes 183 boolean aStale = a.isStale(staleInterval); 184 boolean bStale = b.isStale(staleInterval); 185 return aStale == bStale ? 0 : (aStale ? 1 : -1); 186 } 187 } 188 189 /** 190 * Address matcher for matching an address to local address 191 */ 192 static final AddressMatcher LOCAL_ADDRESS_MATCHER = new AddressMatcher() { 193 @Override 194 public boolean match(InetSocketAddress s) { 195 return NetUtils.isLocalAddress(s.getAddress()); 196 }; 197 }; 198 199 /** 200 * Whether the pathname is valid. Currently prohibits relative paths, 201 * names which contain a ":" or "//", or other non-canonical paths. 202 */ 203 public static boolean isValidName(String src) { 204 // Path must be absolute. 205 if (!src.startsWith(Path.SEPARATOR)) { 206 return false; 207 } 208 209 // Check for ".." "." ":" "/" 210 String[] components = StringUtils.split(src, '/'); 211 for (int i = 0; i < components.length; i++) { 212 String element = components[i]; 213 if (element.equals("..") || 214 element.equals(".") || 215 (element.indexOf(":") >= 0) || 216 (element.indexOf("/") >= 0)) { 217 return false; 218 } 219 220 // The string may start or end with a /, but not have 221 // "//" in the middle. 222 if (element.isEmpty() && i != components.length - 1 && 223 i != 0) { 224 return false; 225 } 226 } 227 return true; 228 } 229 230 /** 231 * Converts a byte array to a string using UTF8 encoding. 232 */ 233 public static String bytes2String(byte[] bytes) { 234 return bytes2String(bytes, 0, bytes.length); 235 } 236 237 /** 238 * Decode a specific range of bytes of the given byte array to a string 239 * using UTF8. 240 * 241 * @param bytes The bytes to be decoded into characters 242 * @param offset The index of the first byte to decode 243 * @param length The number of bytes to decode 244 * @return The decoded string 245 */ 246 public static String bytes2String(byte[] bytes, int offset, int length) { 247 try { 248 return new String(bytes, offset, length, "UTF8"); 249 } catch(UnsupportedEncodingException e) { 250 assert false : "UTF8 encoding is not supported "; 251 } 252 return null; 253 } 254 255 /** 256 * Converts a string to a byte array using UTF8 encoding. 257 */ 258 public static byte[] string2Bytes(String str) { 259 return str.getBytes(Charsets.UTF_8); 260 } 261 262 /** 263 * Given a list of path components returns a path as a UTF8 String 264 */ 265 public static String byteArray2PathString(byte[][] pathComponents) { 266 if (pathComponents.length == 0) { 267 return ""; 268 } else if (pathComponents.length == 1 269 && (pathComponents[0] == null || pathComponents[0].length == 0)) { 270 return Path.SEPARATOR; 271 } 272 StringBuilder result = new StringBuilder(); 273 for (int i = 0; i < pathComponents.length; i++) { 274 result.append(new String(pathComponents[i], Charsets.UTF_8)); 275 if (i < pathComponents.length - 1) { 276 result.append(Path.SEPARATOR_CHAR); 277 } 278 } 279 return result.toString(); 280 } 281 282 /** 283 * Given a list of path components returns a byte array 284 */ 285 public static byte[] byteArray2bytes(byte[][] pathComponents) { 286 if (pathComponents.length == 0) { 287 return EMPTY_BYTES; 288 } else if (pathComponents.length == 1 289 && (pathComponents[0] == null || pathComponents[0].length == 0)) { 290 return new byte[]{(byte) Path.SEPARATOR_CHAR}; 291 } 292 int length = 0; 293 for (int i = 0; i < pathComponents.length; i++) { 294 length += pathComponents[i].length; 295 if (i < pathComponents.length - 1) { 296 length++; // for SEPARATOR 297 } 298 } 299 byte[] path = new byte[length]; 300 int index = 0; 301 for (int i = 0; i < pathComponents.length; i++) { 302 System.arraycopy(pathComponents[i], 0, path, index, 303 pathComponents[i].length); 304 index += pathComponents[i].length; 305 if (i < pathComponents.length - 1) { 306 path[index] = (byte) Path.SEPARATOR_CHAR; 307 index++; 308 } 309 } 310 return path; 311 } 312 313 /** Convert an object representing a path to a string. */ 314 public static String path2String(final Object path) { 315 return path == null? null 316 : path instanceof String? (String)path 317 : path instanceof byte[][]? byteArray2PathString((byte[][])path) 318 : path.toString(); 319 } 320 321 /** 322 * Splits the array of bytes into array of arrays of bytes 323 * on byte separator 324 * @param bytes the array of bytes to split 325 * @param separator the delimiting byte 326 */ 327 public static byte[][] bytes2byteArray(byte[] bytes, byte separator) { 328 return bytes2byteArray(bytes, bytes.length, separator); 329 } 330 331 /** 332 * Splits first len bytes in bytes to array of arrays of bytes 333 * on byte separator 334 * @param bytes the byte array to split 335 * @param len the number of bytes to split 336 * @param separator the delimiting byte 337 */ 338 public static byte[][] bytes2byteArray(byte[] bytes, 339 int len, 340 byte separator) { 341 assert len <= bytes.length; 342 int splits = 0; 343 if (len == 0) { 344 return new byte[][]{null}; 345 } 346 // Count the splits. Omit multiple separators and the last one 347 for (int i = 0; i < len; i++) { 348 if (bytes[i] == separator) { 349 splits++; 350 } 351 } 352 int last = len - 1; 353 while (last > -1 && bytes[last--] == separator) { 354 splits--; 355 } 356 if (splits == 0 && bytes[0] == separator) { 357 return new byte[][]{null}; 358 } 359 splits++; 360 byte[][] result = new byte[splits][]; 361 int startIndex = 0; 362 int nextIndex = 0; 363 int index = 0; 364 // Build the splits 365 while (index < splits) { 366 while (nextIndex < len && bytes[nextIndex] != separator) { 367 nextIndex++; 368 } 369 result[index] = new byte[nextIndex - startIndex]; 370 System.arraycopy(bytes, startIndex, result[index], 0, nextIndex 371 - startIndex); 372 index++; 373 startIndex = nextIndex + 1; 374 nextIndex = startIndex; 375 } 376 return result; 377 } 378 379 /** 380 * Convert a LocatedBlocks to BlockLocations[] 381 * @param blocks a LocatedBlocks 382 * @return an array of BlockLocations 383 */ 384 public static BlockLocation[] locatedBlocks2Locations(LocatedBlocks blocks) { 385 if (blocks == null) { 386 return new BlockLocation[0]; 387 } 388 return locatedBlocks2Locations(blocks.getLocatedBlocks()); 389 } 390 391 /** 392 * Convert a List<LocatedBlock> to BlockLocation[] 393 * @param blocks A List<LocatedBlock> to be converted 394 * @return converted array of BlockLocation 395 */ 396 public static BlockLocation[] locatedBlocks2Locations(List<LocatedBlock> blocks) { 397 if (blocks == null) { 398 return new BlockLocation[0]; 399 } 400 int nrBlocks = blocks.size(); 401 BlockLocation[] blkLocations = new BlockLocation[nrBlocks]; 402 if (nrBlocks == 0) { 403 return blkLocations; 404 } 405 int idx = 0; 406 for (LocatedBlock blk : blocks) { 407 assert idx < nrBlocks : "Incorrect index"; 408 DatanodeInfo[] locations = blk.getLocations(); 409 String[] hosts = new String[locations.length]; 410 String[] xferAddrs = new String[locations.length]; 411 String[] racks = new String[locations.length]; 412 for (int hCnt = 0; hCnt < locations.length; hCnt++) { 413 hosts[hCnt] = locations[hCnt].getHostName(); 414 xferAddrs[hCnt] = locations[hCnt].getXferAddr(); 415 NodeBase node = new NodeBase(xferAddrs[hCnt], 416 locations[hCnt].getNetworkLocation()); 417 racks[hCnt] = node.toString(); 418 } 419 blkLocations[idx] = new BlockLocation(xferAddrs, hosts, racks, 420 blk.getStartOffset(), 421 blk.getBlockSize(), 422 blk.isCorrupt()); 423 idx++; 424 } 425 return blkLocations; 426 } 427 428 /** 429 * Returns collection of nameservice Ids from the configuration. 430 * @param conf configuration 431 * @return collection of nameservice Ids, or null if not specified 432 */ 433 public static Collection<String> getNameServiceIds(Configuration conf) { 434 return conf.getTrimmedStringCollection(DFS_NAMESERVICES); 435 } 436 437 /** 438 * @return <code>coll</code> if it is non-null and non-empty. Otherwise, 439 * returns a list with a single null value. 440 */ 441 private static Collection<String> emptyAsSingletonNull(Collection<String> coll) { 442 if (coll == null || coll.isEmpty()) { 443 return Collections.singletonList(null); 444 } else { 445 return coll; 446 } 447 } 448 449 /** 450 * Namenode HighAvailability related configuration. 451 * Returns collection of namenode Ids from the configuration. One logical id 452 * for each namenode in the in the HA setup. 453 * 454 * @param conf configuration 455 * @param nsId the nameservice ID to look at, or null for non-federated 456 * @return collection of namenode Ids 457 */ 458 public static Collection<String> getNameNodeIds(Configuration conf, String nsId) { 459 String key = addSuffix(DFS_HA_NAMENODES_KEY_PREFIX, nsId); 460 return conf.getTrimmedStringCollection(key); 461 } 462 463 /** 464 * Given a list of keys in the order of preference, returns a value 465 * for the key in the given order from the configuration. 466 * @param defaultValue default value to return, when key was not found 467 * @param keySuffix suffix to add to the key, if it is not null 468 * @param conf Configuration 469 * @param keys list of keys in the order of preference 470 * @return value of the key or default if a key was not found in configuration 471 */ 472 private static String getConfValue(String defaultValue, String keySuffix, 473 Configuration conf, String... keys) { 474 String value = null; 475 for (String key : keys) { 476 key = addSuffix(key, keySuffix); 477 value = conf.get(key); 478 if (value != null) { 479 break; 480 } 481 } 482 if (value == null) { 483 value = defaultValue; 484 } 485 return value; 486 } 487 488 /** Add non empty and non null suffix to a key */ 489 private static String addSuffix(String key, String suffix) { 490 if (suffix == null || suffix.isEmpty()) { 491 return key; 492 } 493 assert !suffix.startsWith(".") : 494 "suffix '" + suffix + "' should not already have '.' prepended."; 495 return key + "." + suffix; 496 } 497 498 /** Concatenate list of suffix strings '.' separated */ 499 private static String concatSuffixes(String... suffixes) { 500 if (suffixes == null) { 501 return null; 502 } 503 return Joiner.on(".").skipNulls().join(suffixes); 504 } 505 506 /** 507 * Return configuration key of format key.suffix1.suffix2...suffixN 508 */ 509 public static String addKeySuffixes(String key, String... suffixes) { 510 String keySuffix = concatSuffixes(suffixes); 511 return addSuffix(key, keySuffix); 512 } 513 514 /** 515 * Returns the configured address for all NameNodes in the cluster. 516 * @param conf configuration 517 * @param defaultAddress default address to return in case key is not found. 518 * @param keys Set of keys to look for in the order of preference 519 * @return a map(nameserviceId to map(namenodeId to InetSocketAddress)) 520 */ 521 private static Map<String, Map<String, InetSocketAddress>> 522 getAddresses(Configuration conf, 523 String defaultAddress, String... keys) { 524 Collection<String> nameserviceIds = getNameServiceIds(conf); 525 526 // Look for configurations of the form <key>[.<nameserviceId>][.<namenodeId>] 527 // across all of the configured nameservices and namenodes. 528 Map<String, Map<String, InetSocketAddress>> ret = Maps.newLinkedHashMap(); 529 for (String nsId : emptyAsSingletonNull(nameserviceIds)) { 530 Map<String, InetSocketAddress> isas = 531 getAddressesForNameserviceId(conf, nsId, defaultAddress, keys); 532 if (!isas.isEmpty()) { 533 ret.put(nsId, isas); 534 } 535 } 536 return ret; 537 } 538 539 private static Map<String, InetSocketAddress> getAddressesForNameserviceId( 540 Configuration conf, String nsId, String defaultValue, 541 String[] keys) { 542 Collection<String> nnIds = getNameNodeIds(conf, nsId); 543 Map<String, InetSocketAddress> ret = Maps.newHashMap(); 544 for (String nnId : emptyAsSingletonNull(nnIds)) { 545 String suffix = concatSuffixes(nsId, nnId); 546 String address = getConfValue(defaultValue, suffix, conf, keys); 547 if (address != null) { 548 InetSocketAddress isa = NetUtils.createSocketAddr(address); 549 ret.put(nnId, isa); 550 } 551 } 552 return ret; 553 } 554 555 /** 556 * @return a collection of all configured NN Kerberos principals. 557 */ 558 public static Set<String> getAllNnPrincipals(Configuration conf) throws IOException { 559 Set<String> principals = new HashSet<String>(); 560 for (String nsId : DFSUtil.getNameServiceIds(conf)) { 561 if (HAUtil.isHAEnabled(conf, nsId)) { 562 for (String nnId : DFSUtil.getNameNodeIds(conf, nsId)) { 563 Configuration confForNn = new Configuration(conf); 564 NameNode.initializeGenericKeys(confForNn, nsId, nnId); 565 String principal = SecurityUtil.getServerPrincipal(confForNn 566 .get(DFSConfigKeys.DFS_NAMENODE_USER_NAME_KEY), 567 NameNode.getAddress(confForNn).getHostName()); 568 principals.add(principal); 569 } 570 } else { 571 Configuration confForNn = new Configuration(conf); 572 NameNode.initializeGenericKeys(confForNn, nsId, null); 573 String principal = SecurityUtil.getServerPrincipal(confForNn 574 .get(DFSConfigKeys.DFS_NAMENODE_USER_NAME_KEY), 575 NameNode.getAddress(confForNn).getHostName()); 576 principals.add(principal); 577 } 578 } 579 580 return principals; 581 } 582 583 /** 584 * Returns list of InetSocketAddress corresponding to HA NN RPC addresses from 585 * the configuration. 586 * 587 * @param conf configuration 588 * @return list of InetSocketAddresses 589 */ 590 public static Map<String, Map<String, InetSocketAddress>> getHaNnRpcAddresses( 591 Configuration conf) { 592 return getAddresses(conf, null, DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY); 593 } 594 595 /** 596 * Returns list of InetSocketAddress corresponding to backup node rpc 597 * addresses from the configuration. 598 * 599 * @param conf configuration 600 * @return list of InetSocketAddresses 601 * @throws IOException on error 602 */ 603 public static Map<String, Map<String, InetSocketAddress>> getBackupNodeAddresses( 604 Configuration conf) throws IOException { 605 Map<String, Map<String, InetSocketAddress>> addressList = getAddresses(conf, 606 null, DFS_NAMENODE_BACKUP_ADDRESS_KEY); 607 if (addressList.isEmpty()) { 608 throw new IOException("Incorrect configuration: backup node address " 609 + DFS_NAMENODE_BACKUP_ADDRESS_KEY + " is not configured."); 610 } 611 return addressList; 612 } 613 614 /** 615 * Returns list of InetSocketAddresses of corresponding to secondary namenode 616 * http addresses from the configuration. 617 * 618 * @param conf configuration 619 * @return list of InetSocketAddresses 620 * @throws IOException on error 621 */ 622 public static Map<String, Map<String, InetSocketAddress>> getSecondaryNameNodeAddresses( 623 Configuration conf) throws IOException { 624 Map<String, Map<String, InetSocketAddress>> addressList = getAddresses(conf, null, 625 DFS_NAMENODE_SECONDARY_HTTP_ADDRESS_KEY); 626 if (addressList.isEmpty()) { 627 throw new IOException("Incorrect configuration: secondary namenode address " 628 + DFS_NAMENODE_SECONDARY_HTTP_ADDRESS_KEY + " is not configured."); 629 } 630 return addressList; 631 } 632 633 /** 634 * Returns list of InetSocketAddresses corresponding to namenodes from the 635 * configuration. Note this is to be used by datanodes to get the list of 636 * namenode addresses to talk to. 637 * 638 * Returns namenode address specifically configured for datanodes (using 639 * service ports), if found. If not, regular RPC address configured for other 640 * clients is returned. 641 * 642 * @param conf configuration 643 * @return list of InetSocketAddress 644 * @throws IOException on error 645 */ 646 public static Map<String, Map<String, InetSocketAddress>> getNNServiceRpcAddresses( 647 Configuration conf) throws IOException { 648 // Use default address as fall back 649 String defaultAddress; 650 try { 651 defaultAddress = NetUtils.getHostPortString(NameNode.getAddress(conf)); 652 } catch (IllegalArgumentException e) { 653 defaultAddress = null; 654 } 655 656 Map<String, Map<String, InetSocketAddress>> addressList = 657 getAddresses(conf, defaultAddress, 658 DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, DFS_NAMENODE_RPC_ADDRESS_KEY); 659 if (addressList.isEmpty()) { 660 throw new IOException("Incorrect configuration: namenode address " 661 + DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY + " or " 662 + DFS_NAMENODE_RPC_ADDRESS_KEY 663 + " is not configured."); 664 } 665 return addressList; 666 } 667 668 /** 669 * Flatten the given map, as returned by other functions in this class, 670 * into a flat list of {@link ConfiguredNNAddress} instances. 671 */ 672 public static List<ConfiguredNNAddress> flattenAddressMap( 673 Map<String, Map<String, InetSocketAddress>> map) { 674 List<ConfiguredNNAddress> ret = Lists.newArrayList(); 675 676 for (Map.Entry<String, Map<String, InetSocketAddress>> entry : 677 map.entrySet()) { 678 String nsId = entry.getKey(); 679 Map<String, InetSocketAddress> nnMap = entry.getValue(); 680 for (Map.Entry<String, InetSocketAddress> e2 : nnMap.entrySet()) { 681 String nnId = e2.getKey(); 682 InetSocketAddress addr = e2.getValue(); 683 684 ret.add(new ConfiguredNNAddress(nsId, nnId, addr)); 685 } 686 } 687 return ret; 688 } 689 690 /** 691 * Format the given map, as returned by other functions in this class, 692 * into a string suitable for debugging display. The format of this string 693 * should not be considered an interface, and is liable to change. 694 */ 695 public static String addressMapToString( 696 Map<String, Map<String, InetSocketAddress>> map) { 697 StringBuilder b = new StringBuilder(); 698 for (Map.Entry<String, Map<String, InetSocketAddress>> entry : 699 map.entrySet()) { 700 String nsId = entry.getKey(); 701 Map<String, InetSocketAddress> nnMap = entry.getValue(); 702 b.append("Nameservice <").append(nsId).append(">:").append("\n"); 703 for (Map.Entry<String, InetSocketAddress> e2 : nnMap.entrySet()) { 704 b.append(" NN ID ").append(e2.getKey()) 705 .append(" => ").append(e2.getValue()).append("\n"); 706 } 707 } 708 return b.toString(); 709 } 710 711 public static String nnAddressesAsString(Configuration conf) { 712 Map<String, Map<String, InetSocketAddress>> addresses = 713 getHaNnRpcAddresses(conf); 714 return addressMapToString(addresses); 715 } 716 717 /** 718 * Represent one of the NameNodes configured in the cluster. 719 */ 720 public static class ConfiguredNNAddress { 721 private final String nameserviceId; 722 private final String namenodeId; 723 private final InetSocketAddress addr; 724 725 private ConfiguredNNAddress(String nameserviceId, String namenodeId, 726 InetSocketAddress addr) { 727 this.nameserviceId = nameserviceId; 728 this.namenodeId = namenodeId; 729 this.addr = addr; 730 } 731 732 public String getNameserviceId() { 733 return nameserviceId; 734 } 735 736 public String getNamenodeId() { 737 return namenodeId; 738 } 739 740 public InetSocketAddress getAddress() { 741 return addr; 742 } 743 744 @Override 745 public String toString() { 746 return "ConfiguredNNAddress[nsId=" + nameserviceId + ";" + 747 "nnId=" + namenodeId + ";addr=" + addr + "]"; 748 } 749 } 750 751 /** 752 * Get a URI for each configured nameservice. If a nameservice is 753 * HA-enabled, then the logical URI of the nameservice is returned. If the 754 * nameservice is not HA-enabled, then a URI corresponding to an RPC address 755 * of the single NN for that nameservice is returned, preferring the service 756 * RPC address over the client RPC address. 757 * 758 * @param conf configuration 759 * @return a collection of all configured NN URIs, preferring service 760 * addresses 761 */ 762 public static Collection<URI> getNsServiceRpcUris(Configuration conf) { 763 return getNameServiceUris(conf, 764 DFSConfigKeys.DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, 765 DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY); 766 } 767 768 /** 769 * Get a URI for each configured nameservice. If a nameservice is 770 * HA-enabled, then the logical URI of the nameservice is returned. If the 771 * nameservice is not HA-enabled, then a URI corresponding to the address of 772 * the single NN for that nameservice is returned. 773 * 774 * @param conf configuration 775 * @param keys configuration keys to try in order to get the URI for non-HA 776 * nameservices 777 * @return a collection of all configured NN URIs 778 */ 779 public static Collection<URI> getNameServiceUris(Configuration conf, 780 String... keys) { 781 Set<URI> ret = new HashSet<URI>(); 782 783 // We're passed multiple possible configuration keys for any given NN or HA 784 // nameservice, and search the config in order of these keys. In order to 785 // make sure that a later config lookup (e.g. fs.defaultFS) doesn't add a 786 // URI for a config key for which we've already found a preferred entry, we 787 // keep track of non-preferred keys here. 788 Set<URI> nonPreferredUris = new HashSet<URI>(); 789 790 for (String nsId : getNameServiceIds(conf)) { 791 if (HAUtil.isHAEnabled(conf, nsId)) { 792 // Add the logical URI of the nameservice. 793 try { 794 ret.add(new URI(HdfsConstants.HDFS_URI_SCHEME + "://" + nsId)); 795 } catch (URISyntaxException ue) { 796 throw new IllegalArgumentException(ue); 797 } 798 } else { 799 // Add the URI corresponding to the address of the NN. 800 boolean uriFound = false; 801 for (String key : keys) { 802 String addr = conf.get(concatSuffixes(key, nsId)); 803 if (addr != null) { 804 URI uri = createUri(HdfsConstants.HDFS_URI_SCHEME, 805 NetUtils.createSocketAddr(addr)); 806 if (!uriFound) { 807 uriFound = true; 808 ret.add(uri); 809 } else { 810 nonPreferredUris.add(uri); 811 } 812 } 813 } 814 } 815 } 816 817 // Add the generic configuration keys. 818 boolean uriFound = false; 819 for (String key : keys) { 820 String addr = conf.get(key); 821 if (addr != null) { 822 URI uri = createUri("hdfs", NetUtils.createSocketAddr(addr)); 823 if (!uriFound) { 824 uriFound = true; 825 ret.add(uri); 826 } else { 827 nonPreferredUris.add(uri); 828 } 829 } 830 } 831 832 // Add the default URI if it is an HDFS URI. 833 URI defaultUri = FileSystem.getDefaultUri(conf); 834 // checks if defaultUri is ip:port format 835 // and convert it to hostname:port format 836 if (defaultUri != null && (defaultUri.getPort() != -1)) { 837 defaultUri = createUri(defaultUri.getScheme(), 838 NetUtils.createSocketAddr(defaultUri.getHost(), 839 defaultUri.getPort())); 840 } 841 if (defaultUri != null && 842 HdfsConstants.HDFS_URI_SCHEME.equals(defaultUri.getScheme()) && 843 !nonPreferredUris.contains(defaultUri)) { 844 ret.add(defaultUri); 845 } 846 847 return ret; 848 } 849 850 /** 851 * Given the InetSocketAddress this method returns the nameservice Id 852 * corresponding to the key with matching address, by doing a reverse 853 * lookup on the list of nameservices until it finds a match. 854 * 855 * Since the process of resolving URIs to Addresses is slightly expensive, 856 * this utility method should not be used in performance-critical routines. 857 * 858 * @param conf - configuration 859 * @param address - InetSocketAddress for configured communication with NN. 860 * Configured addresses are typically given as URIs, but we may have to 861 * compare against a URI typed in by a human, or the server name may be 862 * aliased, so we compare unambiguous InetSocketAddresses instead of just 863 * comparing URI substrings. 864 * @param keys - list of configured communication parameters that should 865 * be checked for matches. For example, to compare against RPC addresses, 866 * provide the list DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, 867 * DFS_NAMENODE_RPC_ADDRESS_KEY. Use the generic parameter keys, 868 * not the NameServiceId-suffixed keys. 869 * @return nameserviceId, or null if no match found 870 */ 871 public static String getNameServiceIdFromAddress(final Configuration conf, 872 final InetSocketAddress address, String... keys) { 873 // Configuration with a single namenode and no nameserviceId 874 String[] ids = getSuffixIDs(conf, address, keys); 875 return (ids != null) ? ids[0] : null; 876 } 877 878 /** 879 * return server http or https address from the configuration for a 880 * given namenode rpc address. 881 * @param conf 882 * @param namenodeAddr - namenode RPC address 883 * @param httpsAddress -If true, and if security is enabled, returns server 884 * https address. If false, returns server http address. 885 * @return server http or https address 886 * @throws IOException 887 */ 888 public static String getInfoServer(InetSocketAddress namenodeAddr, 889 Configuration conf, boolean httpsAddress) throws IOException { 890 boolean securityOn = UserGroupInformation.isSecurityEnabled(); 891 String httpAddressKey = (securityOn && httpsAddress) ? 892 DFS_NAMENODE_HTTPS_ADDRESS_KEY : DFS_NAMENODE_HTTP_ADDRESS_KEY; 893 String httpAddressDefault = (securityOn && httpsAddress) ? 894 DFS_NAMENODE_HTTPS_ADDRESS_DEFAULT : DFS_NAMENODE_HTTP_ADDRESS_DEFAULT; 895 896 String suffixes[]; 897 if (namenodeAddr != null) { 898 // if non-default namenode, try reverse look up 899 // the nameServiceID if it is available 900 suffixes = getSuffixIDs(conf, namenodeAddr, 901 DFSConfigKeys.DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, 902 DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY); 903 } else { 904 suffixes = new String[2]; 905 } 906 String configuredInfoAddr = getSuffixedConf(conf, httpAddressKey, 907 httpAddressDefault, suffixes); 908 if (namenodeAddr != null) { 909 return substituteForWildcardAddress(configuredInfoAddr, 910 namenodeAddr.getHostName()); 911 } else { 912 return configuredInfoAddr; 913 } 914 } 915 916 917 /** 918 * Substitute a default host in the case that an address has been configured 919 * with a wildcard. This is used, for example, when determining the HTTP 920 * address of the NN -- if it's configured to bind to 0.0.0.0, we want to 921 * substitute the hostname from the filesystem URI rather than trying to 922 * connect to 0.0.0.0. 923 * @param configuredAddress the address found in the configuration 924 * @param defaultHost the host to substitute with, if configuredAddress 925 * is a local/wildcard address. 926 * @return the substituted address 927 * @throws IOException if it is a wildcard address and security is enabled 928 */ 929 public static String substituteForWildcardAddress(String configuredAddress, 930 String defaultHost) throws IOException { 931 InetSocketAddress sockAddr = NetUtils.createSocketAddr(configuredAddress); 932 InetSocketAddress defaultSockAddr = NetUtils.createSocketAddr(defaultHost 933 + ":0"); 934 if (sockAddr.getAddress().isAnyLocalAddress()) { 935 if (UserGroupInformation.isSecurityEnabled() && 936 defaultSockAddr.getAddress().isAnyLocalAddress()) { 937 throw new IOException("Cannot use a wildcard address with security. " + 938 "Must explicitly set bind address for Kerberos"); 939 } 940 return defaultHost + ":" + sockAddr.getPort(); 941 } else { 942 return configuredAddress; 943 } 944 } 945 946 private static String getSuffixedConf(Configuration conf, 947 String key, String defaultVal, String[] suffixes) { 948 String ret = conf.get(DFSUtil.addKeySuffixes(key, suffixes)); 949 if (ret != null) { 950 return ret; 951 } 952 return conf.get(key, defaultVal); 953 } 954 955 /** 956 * Sets the node specific setting into generic configuration key. Looks up 957 * value of "key.nameserviceId.namenodeId" and if found sets that value into 958 * generic key in the conf. If this is not found, falls back to 959 * "key.nameserviceId" and then the unmodified key. 960 * 961 * Note that this only modifies the runtime conf. 962 * 963 * @param conf 964 * Configuration object to lookup specific key and to set the value 965 * to the key passed. Note the conf object is modified. 966 * @param nameserviceId 967 * nameservice Id to construct the node specific key. Pass null if 968 * federation is not configuration. 969 * @param nnId 970 * namenode Id to construct the node specific key. Pass null if 971 * HA is not configured. 972 * @param keys 973 * The key for which node specific value is looked up 974 */ 975 public static void setGenericConf(Configuration conf, 976 String nameserviceId, String nnId, String... keys) { 977 for (String key : keys) { 978 String value = conf.get(addKeySuffixes(key, nameserviceId, nnId)); 979 if (value != null) { 980 conf.set(key, value); 981 continue; 982 } 983 value = conf.get(addKeySuffixes(key, nameserviceId)); 984 if (value != null) { 985 conf.set(key, value); 986 } 987 } 988 } 989 990 /** Return used as percentage of capacity */ 991 public static float getPercentUsed(long used, long capacity) { 992 return capacity <= 0 ? 100 : (used * 100.0f)/capacity; 993 } 994 995 /** Return remaining as percentage of capacity */ 996 public static float getPercentRemaining(long remaining, long capacity) { 997 return capacity <= 0 ? 0 : (remaining * 100.0f)/capacity; 998 } 999 1000 /** Convert percentage to a string. */ 1001 public static String percent2String(double percentage) { 1002 return StringUtils.format("%.2f%%", percentage); 1003 } 1004 1005 /** 1006 * Round bytes to GiB (gibibyte) 1007 * @param bytes number of bytes 1008 * @return number of GiB 1009 */ 1010 public static int roundBytesToGB(long bytes) { 1011 return Math.round((float)bytes/ 1024 / 1024 / 1024); 1012 } 1013 1014 /** Create a {@link ClientDatanodeProtocol} proxy */ 1015 public static ClientDatanodeProtocol createClientDatanodeProtocolProxy( 1016 DatanodeID datanodeid, Configuration conf, int socketTimeout, 1017 boolean connectToDnViaHostname, LocatedBlock locatedBlock) throws IOException { 1018 return new ClientDatanodeProtocolTranslatorPB(datanodeid, conf, socketTimeout, 1019 connectToDnViaHostname, locatedBlock); 1020 } 1021 1022 /** Create {@link ClientDatanodeProtocol} proxy using kerberos ticket */ 1023 static ClientDatanodeProtocol createClientDatanodeProtocolProxy( 1024 DatanodeID datanodeid, Configuration conf, int socketTimeout, 1025 boolean connectToDnViaHostname) throws IOException { 1026 return new ClientDatanodeProtocolTranslatorPB( 1027 datanodeid, conf, socketTimeout, connectToDnViaHostname); 1028 } 1029 1030 /** Create a {@link ClientDatanodeProtocol} proxy */ 1031 public static ClientDatanodeProtocol createClientDatanodeProtocolProxy( 1032 InetSocketAddress addr, UserGroupInformation ticket, Configuration conf, 1033 SocketFactory factory) throws IOException { 1034 return new ClientDatanodeProtocolTranslatorPB(addr, ticket, conf, factory); 1035 } 1036 1037 /** 1038 * Get nameservice Id for the {@link NameNode} based on namenode RPC address 1039 * matching the local node address. 1040 */ 1041 public static String getNamenodeNameServiceId(Configuration conf) { 1042 return getNameServiceId(conf, DFS_NAMENODE_RPC_ADDRESS_KEY); 1043 } 1044 1045 /** 1046 * Get nameservice Id for the BackupNode based on backup node RPC address 1047 * matching the local node address. 1048 */ 1049 public static String getBackupNameServiceId(Configuration conf) { 1050 return getNameServiceId(conf, DFS_NAMENODE_BACKUP_ADDRESS_KEY); 1051 } 1052 1053 /** 1054 * Get nameservice Id for the secondary node based on secondary http address 1055 * matching the local node address. 1056 */ 1057 public static String getSecondaryNameServiceId(Configuration conf) { 1058 return getNameServiceId(conf, DFS_NAMENODE_SECONDARY_HTTP_ADDRESS_KEY); 1059 } 1060 1061 /** 1062 * Get the nameservice Id by matching the {@code addressKey} with the 1063 * the address of the local node. 1064 * 1065 * If {@link DFSConfigKeys#DFS_NAMESERVICE_ID} is not specifically 1066 * configured, and more than one nameservice Id is configured, this method 1067 * determines the nameservice Id by matching the local node's address with the 1068 * configured addresses. When a match is found, it returns the nameservice Id 1069 * from the corresponding configuration key. 1070 * 1071 * @param conf Configuration 1072 * @param addressKey configuration key to get the address. 1073 * @return nameservice Id on success, null if federation is not configured. 1074 * @throws HadoopIllegalArgumentException on error 1075 */ 1076 private static String getNameServiceId(Configuration conf, String addressKey) { 1077 String nameserviceId = conf.get(DFS_NAMESERVICE_ID); 1078 if (nameserviceId != null) { 1079 return nameserviceId; 1080 } 1081 Collection<String> nsIds = getNameServiceIds(conf); 1082 if (1 == nsIds.size()) { 1083 return nsIds.toArray(new String[1])[0]; 1084 } 1085 String nnId = conf.get(DFS_HA_NAMENODE_ID_KEY); 1086 1087 return getSuffixIDs(conf, addressKey, null, nnId, LOCAL_ADDRESS_MATCHER)[0]; 1088 } 1089 1090 /** 1091 * Returns nameservice Id and namenode Id when the local host matches the 1092 * configuration parameter {@code addressKey}.<nameservice Id>.<namenode Id> 1093 * 1094 * @param conf Configuration 1095 * @param addressKey configuration key corresponding to the address. 1096 * @param knownNsId only look at configs for the given nameservice, if not-null 1097 * @param knownNNId only look at configs for the given namenode, if not null 1098 * @param matcher matching criteria for matching the address 1099 * @return Array with nameservice Id and namenode Id on success. First element 1100 * in the array is nameservice Id and second element is namenode Id. 1101 * Null value indicates that the configuration does not have the the 1102 * Id. 1103 * @throws HadoopIllegalArgumentException on error 1104 */ 1105 static String[] getSuffixIDs(final Configuration conf, final String addressKey, 1106 String knownNsId, String knownNNId, 1107 final AddressMatcher matcher) { 1108 String nameserviceId = null; 1109 String namenodeId = null; 1110 int found = 0; 1111 1112 Collection<String> nsIds = getNameServiceIds(conf); 1113 for (String nsId : emptyAsSingletonNull(nsIds)) { 1114 if (knownNsId != null && !knownNsId.equals(nsId)) { 1115 continue; 1116 } 1117 1118 Collection<String> nnIds = getNameNodeIds(conf, nsId); 1119 for (String nnId : emptyAsSingletonNull(nnIds)) { 1120 if (LOG.isTraceEnabled()) { 1121 LOG.trace(String.format("addressKey: %s nsId: %s nnId: %s", 1122 addressKey, nsId, nnId)); 1123 } 1124 if (knownNNId != null && !knownNNId.equals(nnId)) { 1125 continue; 1126 } 1127 String key = addKeySuffixes(addressKey, nsId, nnId); 1128 String addr = conf.get(key); 1129 if (addr == null) { 1130 continue; 1131 } 1132 InetSocketAddress s = null; 1133 try { 1134 s = NetUtils.createSocketAddr(addr); 1135 } catch (Exception e) { 1136 LOG.warn("Exception in creating socket address " + addr, e); 1137 continue; 1138 } 1139 if (!s.isUnresolved() && matcher.match(s)) { 1140 nameserviceId = nsId; 1141 namenodeId = nnId; 1142 found++; 1143 } 1144 } 1145 } 1146 if (found > 1) { // Only one address must match the local address 1147 String msg = "Configuration has multiple addresses that match " 1148 + "local node's address. Please configure the system with " 1149 + DFS_NAMESERVICE_ID + " and " 1150 + DFS_HA_NAMENODE_ID_KEY; 1151 throw new HadoopIllegalArgumentException(msg); 1152 } 1153 return new String[] { nameserviceId, namenodeId }; 1154 } 1155 1156 /** 1157 * For given set of {@code keys} adds nameservice Id and or namenode Id 1158 * and returns {nameserviceId, namenodeId} when address match is found. 1159 * @see #getSuffixIDs(Configuration, String, AddressMatcher) 1160 */ 1161 static String[] getSuffixIDs(final Configuration conf, 1162 final InetSocketAddress address, final String... keys) { 1163 AddressMatcher matcher = new AddressMatcher() { 1164 @Override 1165 public boolean match(InetSocketAddress s) { 1166 return address.equals(s); 1167 } 1168 }; 1169 1170 for (String key : keys) { 1171 String[] ids = getSuffixIDs(conf, key, null, null, matcher); 1172 if (ids != null && (ids [0] != null || ids[1] != null)) { 1173 return ids; 1174 } 1175 } 1176 return null; 1177 } 1178 1179 private interface AddressMatcher { 1180 public boolean match(InetSocketAddress s); 1181 } 1182 1183 /** Create a URI from the scheme and address */ 1184 public static URI createUri(String scheme, InetSocketAddress address) { 1185 try { 1186 return new URI(scheme, null, address.getHostName(), address.getPort(), 1187 null, null, null); 1188 } catch (URISyntaxException ue) { 1189 throw new IllegalArgumentException(ue); 1190 } 1191 } 1192 1193 /** 1194 * Add protobuf based protocol to the {@link org.apache.hadoop.ipc.RPC.Server} 1195 * @param conf configuration 1196 * @param protocol Protocol interface 1197 * @param service service that implements the protocol 1198 * @param server RPC server to which the protocol & implementation is added to 1199 * @throws IOException 1200 */ 1201 public static void addPBProtocol(Configuration conf, Class<?> protocol, 1202 BlockingService service, RPC.Server server) throws IOException { 1203 RPC.setProtocolEngine(conf, protocol, ProtobufRpcEngine.class); 1204 server.addProtocol(RPC.RpcKind.RPC_PROTOCOL_BUFFER, protocol, service); 1205 } 1206 1207 /** 1208 * Map a logical namenode ID to its service address. Use the given 1209 * nameservice if specified, or the configured one if none is given. 1210 * 1211 * @param conf Configuration 1212 * @param nsId which nameservice nnId is a part of, optional 1213 * @param nnId the namenode ID to get the service addr for 1214 * @return the service addr, null if it could not be determined 1215 */ 1216 public static String getNamenodeServiceAddr(final Configuration conf, 1217 String nsId, String nnId) { 1218 1219 if (nsId == null) { 1220 nsId = getOnlyNameServiceIdOrNull(conf); 1221 } 1222 1223 String serviceAddrKey = concatSuffixes( 1224 DFSConfigKeys.DFS_NAMENODE_SERVICE_RPC_ADDRESS_KEY, nsId, nnId); 1225 1226 String addrKey = concatSuffixes( 1227 DFSConfigKeys.DFS_NAMENODE_RPC_ADDRESS_KEY, nsId, nnId); 1228 1229 String serviceRpcAddr = conf.get(serviceAddrKey); 1230 if (serviceRpcAddr == null) { 1231 serviceRpcAddr = conf.get(addrKey); 1232 } 1233 return serviceRpcAddr; 1234 } 1235 1236 /** 1237 * If the configuration refers to only a single nameservice, return the 1238 * name of that nameservice. If it refers to 0 or more than 1, return null. 1239 */ 1240 public static String getOnlyNameServiceIdOrNull(Configuration conf) { 1241 Collection<String> nsIds = getNameServiceIds(conf); 1242 if (1 == nsIds.size()) { 1243 return nsIds.toArray(new String[1])[0]; 1244 } else { 1245 // No nameservice ID was given and more than one is configured 1246 return null; 1247 } 1248 } 1249 1250 public static Options helpOptions = new Options(); 1251 public static Option helpOpt = new Option("h", "help", false, 1252 "get help information"); 1253 1254 static { 1255 helpOptions.addOption(helpOpt); 1256 } 1257 1258 /** 1259 * Parse the arguments for commands 1260 * 1261 * @param args the argument to be parsed 1262 * @param helpDescription help information to be printed out 1263 * @param out Printer 1264 * @param printGenericCommandUsage whether to print the 1265 * generic command usage defined in ToolRunner 1266 * @return true when the argument matches help option, false if not 1267 */ 1268 public static boolean parseHelpArgument(String[] args, 1269 String helpDescription, PrintStream out, boolean printGenericCommandUsage) { 1270 if (args.length == 1) { 1271 try { 1272 CommandLineParser parser = new PosixParser(); 1273 CommandLine cmdLine = parser.parse(helpOptions, args); 1274 if (cmdLine.hasOption(helpOpt.getOpt()) 1275 || cmdLine.hasOption(helpOpt.getLongOpt())) { 1276 // should print out the help information 1277 out.println(helpDescription + "\n"); 1278 if (printGenericCommandUsage) { 1279 ToolRunner.printGenericCommandUsage(out); 1280 } 1281 return true; 1282 } 1283 } catch (ParseException pe) { 1284 return false; 1285 } 1286 } 1287 return false; 1288 } 1289 1290 /** 1291 * Get DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION from configuration. 1292 * 1293 * @param conf Configuration 1294 * @return Value of DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION 1295 */ 1296 public static float getInvalidateWorkPctPerIteration(Configuration conf) { 1297 float blocksInvalidateWorkPct = conf.getFloat( 1298 DFSConfigKeys.DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION, 1299 DFSConfigKeys.DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION_DEFAULT); 1300 Preconditions.checkArgument( 1301 (blocksInvalidateWorkPct > 0 && blocksInvalidateWorkPct <= 1.0f), 1302 DFSConfigKeys.DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION + 1303 " = '" + blocksInvalidateWorkPct + "' is invalid. " + 1304 "It should be a positive, non-zero float value, not greater than 1.0f, " + 1305 "to indicate a percentage."); 1306 return blocksInvalidateWorkPct; 1307 } 1308 1309 /** 1310 * Get DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION from 1311 * configuration. 1312 * 1313 * @param conf Configuration 1314 * @return Value of DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION 1315 */ 1316 public static int getReplWorkMultiplier(Configuration conf) { 1317 int blocksReplWorkMultiplier = conf.getInt( 1318 DFSConfigKeys.DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION, 1319 DFSConfigKeys.DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION_DEFAULT); 1320 Preconditions.checkArgument( 1321 (blocksReplWorkMultiplier > 0), 1322 DFSConfigKeys.DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION + 1323 " = '" + blocksReplWorkMultiplier + "' is invalid. " + 1324 "It should be a positive, non-zero integer value."); 1325 return blocksReplWorkMultiplier; 1326 } 1327 1328 /** 1329 * Get SPNEGO keytab Key from configuration 1330 * 1331 * @param conf 1332 * Configuration 1333 * @param defaultKey 1334 * @return DFS_WEB_AUTHENTICATION_KERBEROS_KEYTAB_KEY if the key is not empty 1335 * else return defaultKey 1336 */ 1337 public static String getSpnegoKeytabKey(Configuration conf, String defaultKey) { 1338 String value = 1339 conf.get(DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_KEYTAB_KEY); 1340 return (value == null || value.isEmpty()) ? 1341 defaultKey : DFSConfigKeys.DFS_WEB_AUTHENTICATION_KERBEROS_KEYTAB_KEY; 1342 } 1343 }