/** * 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; import java.io.UnsupportedEncodingException; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.Comparator; import java.util.StringTokenizer; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.BlockLocation; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.protocol.DatanodeInfo; import org.apache.hadoop.hdfs.protocol.LocatedBlock; import org.apache.hadoop.hdfs.protocol.LocatedBlocks; import org.apache.hadoop.net.NodeBase; public class DFSUtil { /** * Whether the pathname is valid. Currently prohibits relative paths, * and names which contain a ":" or "/" */ public static boolean isValidName(String src) { // Path must be absolute. if (!src.startsWith(Path.SEPARATOR)) { return false; } // Check for ".." "." ":" "/" StringTokenizer tokens = new StringTokenizer(src, Path.SEPARATOR); while(tokens.hasMoreTokens()) { String element = tokens.nextToken(); if (element.equals("..") || element.equals(".") || (element.indexOf(":") >= 0) || (element.indexOf("/") >= 0)) { return false; } } return true; } /** * Converts a byte array to a string using UTF8 encoding. */ public static String bytes2String(byte[] bytes) { try { return new String(bytes, "UTF8"); } catch(UnsupportedEncodingException e) { assert false : "UTF8 encoding is not supported "; } return null; } /** * Converts a string to a byte array using UTF8 encoding. */ public static byte[] string2Bytes(String str) { try { return str.getBytes("UTF8"); } catch(UnsupportedEncodingException e) { assert false : "UTF8 encoding is not supported "; } return null; } /** * Convert a LocatedBlocks to BlockLocations[] * @param blocks a LocatedBlocks * @return an array of BlockLocations */ public static BlockLocation[] locatedBlocks2Locations(LocatedBlocks blocks) { if (blocks == null) { return new BlockLocation[0]; } int nrBlocks = blocks.locatedBlockCount(); BlockLocation[] blkLocations = new BlockLocation[nrBlocks]; int idx = 0; for (LocatedBlock blk : blocks.getLocatedBlocks()) { assert idx < nrBlocks : "Incorrect index"; DatanodeInfo[] locations = blk.getLocations(); String[] hosts = new String[locations.length]; String[] names = new String[locations.length]; String[] racks = new String[locations.length]; for (int hCnt = 0; hCnt < locations.length; hCnt++) { hosts[hCnt] = locations[hCnt].getHostName(); names[hCnt] = locations[hCnt].getName(); NodeBase node = new NodeBase(names[hCnt], locations[hCnt].getNetworkLocation()); racks[hCnt] = node.toString(); } blkLocations[idx] = new BlockLocation(names, hosts, racks, blk.getStartOffset(), blk.getBlockSize()); idx++; } return blkLocations; } /** Create a URI from the scheme and address */ public static URI createUri(String scheme, InetSocketAddress address) { try { return new URI(scheme, null, address.getHostName(), address.getPort(), null, null, null); } catch (URISyntaxException ue) { throw new IllegalArgumentException(ue); } } /** * Get DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION from configuration. * * @param conf Configuration * @return Value of DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION * @throws IllegalArgumentException If the value is not positive */ public static float getInvalidateWorkPctPerIteration(Configuration conf) { float blocksInvalidateWorkPct = conf.getFloat( DFSConfigKeys.DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION, DFSConfigKeys.DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION_DEFAULT); if (blocksInvalidateWorkPct <= 0.0f || blocksInvalidateWorkPct > 1.0f) { throw new IllegalArgumentException( DFSConfigKeys.DFS_NAMENODE_INVALIDATE_WORK_PCT_PER_ITERATION + " = '" + blocksInvalidateWorkPct + "' is invalid. " + "It should be a positive, non-zero float value " + "indicating a percentage."); } return blocksInvalidateWorkPct; } /** * Get DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION * from configuration. * * @param conf Configuration * @return Value of DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION * @throws IllegalArgumentException If the value is not positive */ public static int getReplWorkMultiplier(Configuration conf) { int blocksReplWorkMultiplier = conf.getInt( DFSConfigKeys.DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION, DFSConfigKeys. DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION_DEFAULT); if (blocksReplWorkMultiplier <= 0) { throw new IllegalArgumentException( DFSConfigKeys.DFS_NAMENODE_REPLICATION_WORK_MULTIPLIER_PER_ITERATION + " = '" + blocksReplWorkMultiplier + "' is invalid. " + "It should be a positive, non-zero integer value."); } return blocksReplWorkMultiplier; } /** * Comparator for sorting DataNodeInfo[] based on stale states. Stale nodes * are moved to the end of the array on sorting with this comparator. */ public static class StaleComparator implements Comparator<DatanodeInfo> { private long staleInterval; /** * Constructor of StaleComparator * * @param interval * The time interval for marking datanodes as stale is passed from * outside, since the interval may be changed dynamically */ public StaleComparator(long interval) { this.staleInterval = interval; } @Override public int compare(DatanodeInfo a, DatanodeInfo b) { // Stale nodes will be moved behind the normal nodes boolean aStale = a.isStale(staleInterval); boolean bStale = b.isStale(staleInterval); return aStale == bStale ? 0 : (aStale ? 1 : -1); } } }