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.hdfs.protocol; 019 020 import java.util.Date; 021 022 import org.apache.hadoop.classification.InterfaceAudience; 023 import org.apache.hadoop.classification.InterfaceStability; 024 import org.apache.hadoop.hdfs.DFSUtil; 025 import org.apache.hadoop.net.NetUtils; 026 import org.apache.hadoop.net.NetworkTopology; 027 import org.apache.hadoop.net.Node; 028 import org.apache.hadoop.net.NodeBase; 029 import org.apache.hadoop.util.StringUtils; 030 031 /** 032 * This class extends the primary identifier of a Datanode with ephemeral 033 * state, eg usage information, current administrative state, and the 034 * network location that is communicated to clients. 035 */ 036 @InterfaceAudience.Private 037 @InterfaceStability.Evolving 038 public class DatanodeInfo extends DatanodeID implements Node { 039 protected long capacity; 040 protected long dfsUsed; 041 protected long remaining; 042 protected long blockPoolUsed; 043 protected long lastUpdate; 044 protected int xceiverCount; 045 protected String location = NetworkTopology.DEFAULT_RACK; 046 047 // Datanode administrative states 048 public enum AdminStates { 049 NORMAL("In Service"), 050 DECOMMISSION_INPROGRESS("Decommission In Progress"), 051 DECOMMISSIONED("Decommissioned"); 052 053 final String value; 054 055 AdminStates(final String v) { 056 this.value = v; 057 } 058 059 public String toString() { 060 return value; 061 } 062 063 public static AdminStates fromValue(final String value) { 064 for (AdminStates as : AdminStates.values()) { 065 if (as.value.equals(value)) return as; 066 } 067 return NORMAL; 068 } 069 } 070 071 protected AdminStates adminState; 072 073 public DatanodeInfo(DatanodeInfo from) { 074 super(from); 075 this.capacity = from.getCapacity(); 076 this.dfsUsed = from.getDfsUsed(); 077 this.remaining = from.getRemaining(); 078 this.blockPoolUsed = from.getBlockPoolUsed(); 079 this.lastUpdate = from.getLastUpdate(); 080 this.xceiverCount = from.getXceiverCount(); 081 this.location = from.getNetworkLocation(); 082 this.adminState = from.adminState; 083 this.hostName = from.hostName; 084 } 085 086 public DatanodeInfo(DatanodeID nodeID) { 087 super(nodeID); 088 this.capacity = 0L; 089 this.dfsUsed = 0L; 090 this.remaining = 0L; 091 this.blockPoolUsed = 0L; 092 this.lastUpdate = 0L; 093 this.xceiverCount = 0; 094 this.adminState = null; 095 } 096 097 public DatanodeInfo(DatanodeID nodeID, String location) { 098 this(nodeID); 099 this.location = location; 100 } 101 102 public DatanodeInfo(DatanodeID nodeID, String location, 103 final long capacity, final long dfsUsed, final long remaining, 104 final long blockPoolUsed, final long lastUpdate, final int xceiverCount, 105 final AdminStates adminState) { 106 this(nodeID.getIpAddr(), nodeID.getHostName(), nodeID.getStorageID(), nodeID.getXferPort(), 107 nodeID.getInfoPort(), nodeID.getIpcPort(), capacity, dfsUsed, remaining, 108 blockPoolUsed, lastUpdate, xceiverCount, location, adminState); 109 } 110 111 /** Constructor */ 112 public DatanodeInfo(final String ipAddr, final String hostName, 113 final String storageID, final int xferPort, final int infoPort, final int ipcPort, 114 final long capacity, final long dfsUsed, final long remaining, 115 final long blockPoolUsed, final long lastUpdate, final int xceiverCount, 116 final String networkLocation, final AdminStates adminState) { 117 super(ipAddr, hostName, storageID, xferPort, infoPort, ipcPort); 118 this.capacity = capacity; 119 this.dfsUsed = dfsUsed; 120 this.remaining = remaining; 121 this.blockPoolUsed = blockPoolUsed; 122 this.lastUpdate = lastUpdate; 123 this.xceiverCount = xceiverCount; 124 this.location = networkLocation; 125 this.adminState = adminState; 126 } 127 128 /** Network location name */ 129 public String getName() { 130 return getXferAddr(); 131 } 132 133 /** The raw capacity. */ 134 public long getCapacity() { return capacity; } 135 136 /** The used space by the data node. */ 137 public long getDfsUsed() { return dfsUsed; } 138 139 /** The used space by the block pool on data node. */ 140 public long getBlockPoolUsed() { return blockPoolUsed; } 141 142 /** The used space by the data node. */ 143 public long getNonDfsUsed() { 144 long nonDFSUsed = capacity - dfsUsed - remaining; 145 return nonDFSUsed < 0 ? 0 : nonDFSUsed; 146 } 147 148 /** The used space by the data node as percentage of present capacity */ 149 public float getDfsUsedPercent() { 150 return DFSUtil.getPercentUsed(dfsUsed, capacity); 151 } 152 153 /** The raw free space. */ 154 public long getRemaining() { return remaining; } 155 156 /** Used space by the block pool as percentage of present capacity */ 157 public float getBlockPoolUsedPercent() { 158 return DFSUtil.getPercentUsed(blockPoolUsed, capacity); 159 } 160 161 /** The remaining space as percentage of configured capacity. */ 162 public float getRemainingPercent() { 163 return DFSUtil.getPercentRemaining(remaining, capacity); 164 } 165 166 /** The time when this information was accurate. */ 167 public long getLastUpdate() { return lastUpdate; } 168 169 /** number of active connections */ 170 public int getXceiverCount() { return xceiverCount; } 171 172 /** Sets raw capacity. */ 173 public void setCapacity(long capacity) { 174 this.capacity = capacity; 175 } 176 177 /** Sets the used space for the datanode. */ 178 public void setDfsUsed(long dfsUsed) { 179 this.dfsUsed = dfsUsed; 180 } 181 182 /** Sets raw free space. */ 183 public void setRemaining(long remaining) { 184 this.remaining = remaining; 185 } 186 187 /** Sets block pool used space */ 188 public void setBlockPoolUsed(long bpUsed) { 189 this.blockPoolUsed = bpUsed; 190 } 191 192 /** Sets time when this information was accurate. */ 193 public void setLastUpdate(long lastUpdate) { 194 this.lastUpdate = lastUpdate; 195 } 196 197 /** Sets number of active connections */ 198 public void setXceiverCount(int xceiverCount) { 199 this.xceiverCount = xceiverCount; 200 } 201 202 /** rack name */ 203 public synchronized String getNetworkLocation() {return location;} 204 205 /** Sets the rack name */ 206 public synchronized void setNetworkLocation(String location) { 207 this.location = NodeBase.normalize(location); 208 } 209 210 /** A formatted string for reporting the status of the DataNode. */ 211 public String getDatanodeReport() { 212 StringBuilder buffer = new StringBuilder(); 213 long c = getCapacity(); 214 long r = getRemaining(); 215 long u = getDfsUsed(); 216 long nonDFSUsed = getNonDfsUsed(); 217 float usedPercent = getDfsUsedPercent(); 218 float remainingPercent = getRemainingPercent(); 219 String lookupName = NetUtils.getHostNameOfIP(getName()); 220 221 buffer.append("Name: "+ getName()); 222 if (lookupName != null) { 223 buffer.append(" (" + lookupName + ")"); 224 } 225 buffer.append("\n"); 226 buffer.append("Hostname: " + getHostName() + "\n"); 227 228 if (!NetworkTopology.DEFAULT_RACK.equals(location)) { 229 buffer.append("Rack: "+location+"\n"); 230 } 231 buffer.append("Decommission Status : "); 232 if (isDecommissioned()) { 233 buffer.append("Decommissioned\n"); 234 } else if (isDecommissionInProgress()) { 235 buffer.append("Decommission in progress\n"); 236 } else { 237 buffer.append("Normal\n"); 238 } 239 buffer.append("Configured Capacity: "+c+" ("+StringUtils.byteDesc(c)+")"+"\n"); 240 buffer.append("DFS Used: "+u+" ("+StringUtils.byteDesc(u)+")"+"\n"); 241 buffer.append("Non DFS Used: "+nonDFSUsed+" ("+StringUtils.byteDesc(nonDFSUsed)+")"+"\n"); 242 buffer.append("DFS Remaining: " +r+ " ("+StringUtils.byteDesc(r)+")"+"\n"); 243 buffer.append("DFS Used%: "+StringUtils.limitDecimalTo2(usedPercent)+"%\n"); 244 buffer.append("DFS Remaining%: "+StringUtils.limitDecimalTo2(remainingPercent)+"%\n"); 245 buffer.append("Last contact: "+new Date(lastUpdate)+"\n"); 246 return buffer.toString(); 247 } 248 249 /** A formatted string for printing the status of the DataNode. */ 250 public String dumpDatanode() { 251 StringBuilder buffer = new StringBuilder(); 252 long c = getCapacity(); 253 long r = getRemaining(); 254 long u = getDfsUsed(); 255 buffer.append(getName()); 256 if (!NetworkTopology.DEFAULT_RACK.equals(location)) { 257 buffer.append(" "+location); 258 } 259 if (isDecommissioned()) { 260 buffer.append(" DD"); 261 } else if (isDecommissionInProgress()) { 262 buffer.append(" DP"); 263 } else { 264 buffer.append(" IN"); 265 } 266 buffer.append(" " + c + "(" + StringUtils.byteDesc(c)+")"); 267 buffer.append(" " + u + "(" + StringUtils.byteDesc(u)+")"); 268 buffer.append(" " + StringUtils.limitDecimalTo2(((1.0*u)/c)*100)+"%"); 269 buffer.append(" " + r + "(" + StringUtils.byteDesc(r)+")"); 270 buffer.append(" " + new Date(lastUpdate)); 271 return buffer.toString(); 272 } 273 274 /** 275 * Start decommissioning a node. 276 * old state. 277 */ 278 public void startDecommission() { 279 adminState = AdminStates.DECOMMISSION_INPROGRESS; 280 } 281 282 /** 283 * Stop decommissioning a node. 284 * old state. 285 */ 286 public void stopDecommission() { 287 adminState = null; 288 } 289 290 /** 291 * Returns true if the node is in the process of being decommissioned 292 */ 293 public boolean isDecommissionInProgress() { 294 return adminState == AdminStates.DECOMMISSION_INPROGRESS; 295 } 296 297 /** 298 * Returns true if the node has been decommissioned. 299 */ 300 public boolean isDecommissioned() { 301 return adminState == AdminStates.DECOMMISSIONED; 302 } 303 304 /** 305 * Sets the admin state to indicate that decommission is complete. 306 */ 307 public void setDecommissioned() { 308 adminState = AdminStates.DECOMMISSIONED; 309 } 310 311 /** 312 * Retrieves the admin state of this node. 313 */ 314 public AdminStates getAdminState() { 315 if (adminState == null) { 316 return AdminStates.NORMAL; 317 } 318 return adminState; 319 } 320 321 /** 322 * Sets the admin state of this node. 323 */ 324 protected void setAdminState(AdminStates newState) { 325 if (newState == AdminStates.NORMAL) { 326 adminState = null; 327 } 328 else { 329 adminState = newState; 330 } 331 } 332 333 private transient int level; //which level of the tree the node resides 334 private transient Node parent; //its parent 335 336 /** Return this node's parent */ 337 public Node getParent() { return parent; } 338 public void setParent(Node parent) {this.parent = parent;} 339 340 /** Return this node's level in the tree. 341 * E.g. the root of a tree returns 0 and its children return 1 342 */ 343 public int getLevel() { return level; } 344 public void setLevel(int level) {this.level = level;} 345 346 @Override 347 public int hashCode() { 348 // Super implementation is sufficient 349 return super.hashCode(); 350 } 351 352 @Override 353 public boolean equals(Object obj) { 354 // Sufficient to use super equality as datanodes are uniquely identified 355 // by DatanodeID 356 return (this == obj) || super.equals(obj); 357 } 358 }