1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 package org.apache.hadoop.hdfs.protocol; 19 20 import org.apache.hadoop.classification.InterfaceAudience; 21 import org.apache.hadoop.classification.InterfaceStability; 22 import org.apache.hadoop.hdfs.DFSConfigKeys; 23 import org.apache.hadoop.hdfs.DFSUtil; 24 import org.apache.hadoop.net.NetUtils; 25 import org.apache.hadoop.net.NetworkTopology; 26 import org.apache.hadoop.net.Node; 27 import org.apache.hadoop.net.NodeBase; 28 import org.apache.hadoop.util.StringUtils; 29 import org.apache.hadoop.util.Time; 30 31 import java.util.Date; 32 import java.util.LinkedList; 33 import java.util.List; 34 35 import static org.apache.hadoop.hdfs.DFSUtil.percent2String; 36 37 /** 38 * This class extends the primary identifier of a Datanode with ephemeral 39 * state, eg usage information, current administrative state, and the 40 * network location that is communicated to clients. 41 */ 42 @InterfaceAudience.Private 43 @InterfaceStability.Evolving 44 public class DatanodeInfo extends DatanodeID implements Node { 45 private long capacity; 46 private long dfsUsed; 47 private long remaining; 48 private long blockPoolUsed; 49 private long cacheCapacity; 50 private long cacheUsed; 51 private long lastUpdate; 52 private long lastUpdateMonotonic; 53 private int xceiverCount; 54 private String location = NetworkTopology.DEFAULT_RACK; 55 private String softwareVersion; 56 private List<String> dependentHostNames = new LinkedList<String>(); 57 58 59 // Datanode administrative states 60 public enum AdminStates { 61 NORMAL("In Service"), 62 DECOMMISSION_INPROGRESS("Decommission In Progress"), 63 DECOMMISSIONED("Decommissioned"); 64 65 final String value; 66 AdminStates(final String v)67 AdminStates(final String v) { 68 this.value = v; 69 } 70 71 @Override toString()72 public String toString() { 73 return value; 74 } 75 fromValue(final String value)76 public static AdminStates fromValue(final String value) { 77 for (AdminStates as : AdminStates.values()) { 78 if (as.value.equals(value)) return as; 79 } 80 return NORMAL; 81 } 82 } 83 84 protected AdminStates adminState; 85 DatanodeInfo(DatanodeInfo from)86 public DatanodeInfo(DatanodeInfo from) { 87 super(from); 88 this.capacity = from.getCapacity(); 89 this.dfsUsed = from.getDfsUsed(); 90 this.remaining = from.getRemaining(); 91 this.blockPoolUsed = from.getBlockPoolUsed(); 92 this.cacheCapacity = from.getCacheCapacity(); 93 this.cacheUsed = from.getCacheUsed(); 94 this.lastUpdate = from.getLastUpdate(); 95 this.lastUpdateMonotonic = from.getLastUpdateMonotonic(); 96 this.xceiverCount = from.getXceiverCount(); 97 this.location = from.getNetworkLocation(); 98 this.adminState = from.getAdminState(); 99 } 100 DatanodeInfo(DatanodeID nodeID)101 public DatanodeInfo(DatanodeID nodeID) { 102 super(nodeID); 103 this.capacity = 0L; 104 this.dfsUsed = 0L; 105 this.remaining = 0L; 106 this.blockPoolUsed = 0L; 107 this.cacheCapacity = 0L; 108 this.cacheUsed = 0L; 109 this.lastUpdate = 0L; 110 this.lastUpdateMonotonic = 0L; 111 this.xceiverCount = 0; 112 this.adminState = null; 113 } 114 DatanodeInfo(DatanodeID nodeID, String location)115 public DatanodeInfo(DatanodeID nodeID, String location) { 116 this(nodeID); 117 this.location = location; 118 } 119 DatanodeInfo(DatanodeID nodeID, String location, final long capacity, final long dfsUsed, final long remaining, final long blockPoolUsed, final long cacheCapacity, final long cacheUsed, final long lastUpdate, final long lastUpdateMonotonic, final int xceiverCount, final AdminStates adminState)120 public DatanodeInfo(DatanodeID nodeID, String location, 121 final long capacity, final long dfsUsed, final long remaining, 122 final long blockPoolUsed, final long cacheCapacity, final long cacheUsed, 123 final long lastUpdate, final long lastUpdateMonotonic, 124 final int xceiverCount, final AdminStates adminState) { 125 this(nodeID.getIpAddr(), nodeID.getHostName(), nodeID.getDatanodeUuid(), 126 nodeID.getXferPort(), nodeID.getInfoPort(), nodeID.getInfoSecurePort(), 127 nodeID.getIpcPort(), capacity, dfsUsed, remaining, blockPoolUsed, 128 cacheCapacity, cacheUsed, lastUpdate, lastUpdateMonotonic, 129 xceiverCount, location, adminState); 130 } 131 132 /** Constructor */ DatanodeInfo(final String ipAddr, final String hostName, final String datanodeUuid, final int xferPort, final int infoPort, final int infoSecurePort, final int ipcPort, final long capacity, final long dfsUsed, final long remaining, final long blockPoolUsed, final long cacheCapacity, final long cacheUsed, final long lastUpdate, final long lastUpdateMonotonic, final int xceiverCount, final String networkLocation, final AdminStates adminState)133 public DatanodeInfo(final String ipAddr, final String hostName, 134 final String datanodeUuid, final int xferPort, final int infoPort, 135 final int infoSecurePort, final int ipcPort, 136 final long capacity, final long dfsUsed, final long remaining, 137 final long blockPoolUsed, final long cacheCapacity, final long cacheUsed, 138 final long lastUpdate, final long lastUpdateMonotonic, 139 final int xceiverCount, final String networkLocation, 140 final AdminStates adminState) { 141 super(ipAddr, hostName, datanodeUuid, xferPort, infoPort, 142 infoSecurePort, ipcPort); 143 this.capacity = capacity; 144 this.dfsUsed = dfsUsed; 145 this.remaining = remaining; 146 this.blockPoolUsed = blockPoolUsed; 147 this.cacheCapacity = cacheCapacity; 148 this.cacheUsed = cacheUsed; 149 this.lastUpdate = lastUpdate; 150 this.lastUpdateMonotonic = lastUpdateMonotonic; 151 this.xceiverCount = xceiverCount; 152 this.location = networkLocation; 153 this.adminState = adminState; 154 } 155 156 /** Network location name */ 157 @Override getName()158 public String getName() { 159 return getXferAddr(); 160 } 161 162 /** The raw capacity. */ getCapacity()163 public long getCapacity() { return capacity; } 164 165 /** The used space by the data node. */ getDfsUsed()166 public long getDfsUsed() { return dfsUsed; } 167 168 /** The used space by the block pool on data node. */ getBlockPoolUsed()169 public long getBlockPoolUsed() { return blockPoolUsed; } 170 171 /** The used space by the data node. */ getNonDfsUsed()172 public long getNonDfsUsed() { 173 long nonDFSUsed = capacity - dfsUsed - remaining; 174 return nonDFSUsed < 0 ? 0 : nonDFSUsed; 175 } 176 177 /** The used space by the data node as percentage of present capacity */ getDfsUsedPercent()178 public float getDfsUsedPercent() { 179 return DFSUtil.getPercentUsed(dfsUsed, capacity); 180 } 181 182 /** The raw free space. */ getRemaining()183 public long getRemaining() { return remaining; } 184 185 /** Used space by the block pool as percentage of present capacity */ getBlockPoolUsedPercent()186 public float getBlockPoolUsedPercent() { 187 return DFSUtil.getPercentUsed(blockPoolUsed, capacity); 188 } 189 190 /** The remaining space as percentage of configured capacity. */ getRemainingPercent()191 public float getRemainingPercent() { 192 return DFSUtil.getPercentRemaining(remaining, capacity); 193 } 194 195 /** 196 * @return Amount of cache capacity in bytes 197 */ getCacheCapacity()198 public long getCacheCapacity() { 199 return cacheCapacity; 200 } 201 202 /** 203 * @return Amount of cache used in bytes 204 */ getCacheUsed()205 public long getCacheUsed() { 206 return cacheUsed; 207 } 208 209 /** 210 * @return Cache used as a percentage of the datanode's total cache capacity 211 */ getCacheUsedPercent()212 public float getCacheUsedPercent() { 213 return DFSUtil.getPercentUsed(cacheUsed, cacheCapacity); 214 } 215 216 /** 217 * @return Amount of cache remaining in bytes 218 */ getCacheRemaining()219 public long getCacheRemaining() { 220 return cacheCapacity - cacheUsed; 221 } 222 223 /** 224 * @return Cache remaining as a percentage of the datanode's total cache 225 * capacity 226 */ getCacheRemainingPercent()227 public float getCacheRemainingPercent() { 228 return DFSUtil.getPercentRemaining(getCacheRemaining(), cacheCapacity); 229 } 230 231 /** 232 * Get the last update timestamp. 233 * Return value is suitable for Date conversion. 234 */ getLastUpdate()235 public long getLastUpdate() { return lastUpdate; } 236 237 /** 238 * The time when this information was accurate. <br> 239 * Ps: So return value is ideal for calculation of time differences. 240 * Should not be used to convert to Date. 241 */ getLastUpdateMonotonic()242 public long getLastUpdateMonotonic() { return lastUpdateMonotonic;} 243 244 /** 245 * Set lastUpdate monotonic time 246 */ setLastUpdateMonotonic(long lastUpdateMonotonic)247 public void setLastUpdateMonotonic(long lastUpdateMonotonic) { 248 this.lastUpdateMonotonic = lastUpdateMonotonic; 249 } 250 251 /** number of active connections */ getXceiverCount()252 public int getXceiverCount() { return xceiverCount; } 253 254 /** Sets raw capacity. */ setCapacity(long capacity)255 public void setCapacity(long capacity) { 256 this.capacity = capacity; 257 } 258 259 /** Sets the used space for the datanode. */ setDfsUsed(long dfsUsed)260 public void setDfsUsed(long dfsUsed) { 261 this.dfsUsed = dfsUsed; 262 } 263 264 /** Sets raw free space. */ setRemaining(long remaining)265 public void setRemaining(long remaining) { 266 this.remaining = remaining; 267 } 268 269 /** Sets block pool used space */ setBlockPoolUsed(long bpUsed)270 public void setBlockPoolUsed(long bpUsed) { 271 this.blockPoolUsed = bpUsed; 272 } 273 274 /** Sets cache capacity. */ setCacheCapacity(long cacheCapacity)275 public void setCacheCapacity(long cacheCapacity) { 276 this.cacheCapacity = cacheCapacity; 277 } 278 279 /** Sets cache used. */ setCacheUsed(long cacheUsed)280 public void setCacheUsed(long cacheUsed) { 281 this.cacheUsed = cacheUsed; 282 } 283 284 /** Sets time when this information was accurate. */ setLastUpdate(long lastUpdate)285 public void setLastUpdate(long lastUpdate) { 286 this.lastUpdate = lastUpdate; 287 } 288 289 /** Sets number of active connections */ setXceiverCount(int xceiverCount)290 public void setXceiverCount(int xceiverCount) { 291 this.xceiverCount = xceiverCount; 292 } 293 294 /** network location */ getNetworkLocation()295 public synchronized String getNetworkLocation() {return location;} 296 297 /** Sets the network location */ setNetworkLocation(String location)298 public synchronized void setNetworkLocation(String location) { 299 this.location = NodeBase.normalize(location); 300 } 301 302 /** Add a hostname to a list of network dependencies */ addDependentHostName(String hostname)303 public void addDependentHostName(String hostname) { 304 dependentHostNames.add(hostname); 305 } 306 307 /** List of Network dependencies */ getDependentHostNames()308 public List<String> getDependentHostNames() { 309 return dependentHostNames; 310 } 311 312 /** Sets the network dependencies */ setDependentHostNames(List<String> dependencyList)313 public void setDependentHostNames(List<String> dependencyList) { 314 dependentHostNames = dependencyList; 315 } 316 317 /** A formatted string for reporting the status of the DataNode. */ getDatanodeReport()318 public String getDatanodeReport() { 319 StringBuilder buffer = new StringBuilder(); 320 long c = getCapacity(); 321 long r = getRemaining(); 322 long u = getDfsUsed(); 323 long nonDFSUsed = getNonDfsUsed(); 324 float usedPercent = getDfsUsedPercent(); 325 float remainingPercent = getRemainingPercent(); 326 long cc = getCacheCapacity(); 327 long cr = getCacheRemaining(); 328 long cu = getCacheUsed(); 329 float cacheUsedPercent = getCacheUsedPercent(); 330 float cacheRemainingPercent = getCacheRemainingPercent(); 331 String lookupName = NetUtils.getHostNameOfIP(getName()); 332 333 buffer.append("Name: "+ getName()); 334 if (lookupName != null) { 335 buffer.append(" (" + lookupName + ")"); 336 } 337 buffer.append("\n"); 338 buffer.append("Hostname: " + getHostName() + "\n"); 339 340 if (!NetworkTopology.DEFAULT_RACK.equals(location)) { 341 buffer.append("Rack: "+location+"\n"); 342 } 343 buffer.append("Decommission Status : "); 344 if (isDecommissioned()) { 345 buffer.append("Decommissioned\n"); 346 } else if (isDecommissionInProgress()) { 347 buffer.append("Decommission in progress\n"); 348 } else { 349 buffer.append("Normal\n"); 350 } 351 buffer.append("Configured Capacity: "+c+" ("+StringUtils.byteDesc(c)+")"+"\n"); 352 buffer.append("DFS Used: "+u+" ("+StringUtils.byteDesc(u)+")"+"\n"); 353 buffer.append("Non DFS Used: "+nonDFSUsed+" ("+StringUtils.byteDesc(nonDFSUsed)+")"+"\n"); 354 buffer.append("DFS Remaining: " +r+ " ("+StringUtils.byteDesc(r)+")"+"\n"); 355 buffer.append("DFS Used%: "+percent2String(usedPercent) + "\n"); 356 buffer.append("DFS Remaining%: "+percent2String(remainingPercent) + "\n"); 357 buffer.append("Configured Cache Capacity: "+cc+" ("+StringUtils.byteDesc(cc)+")"+"\n"); 358 buffer.append("Cache Used: "+cu+" ("+StringUtils.byteDesc(cu)+")"+"\n"); 359 buffer.append("Cache Remaining: " +cr+ " ("+StringUtils.byteDesc(cr)+")"+"\n"); 360 buffer.append("Cache Used%: "+percent2String(cacheUsedPercent) + "\n"); 361 buffer.append("Cache Remaining%: "+percent2String(cacheRemainingPercent) + "\n"); 362 buffer.append("Xceivers: "+getXceiverCount()+"\n"); 363 buffer.append("Last contact: "+new Date(lastUpdate)+"\n"); 364 return buffer.toString(); 365 } 366 367 /** A formatted string for printing the status of the DataNode. */ dumpDatanode()368 public String dumpDatanode() { 369 StringBuilder buffer = new StringBuilder(); 370 long c = getCapacity(); 371 long r = getRemaining(); 372 long u = getDfsUsed(); 373 float usedPercent = getDfsUsedPercent(); 374 long cc = getCacheCapacity(); 375 long cr = getCacheRemaining(); 376 long cu = getCacheUsed(); 377 float cacheUsedPercent = getCacheUsedPercent(); 378 buffer.append(getName()); 379 if (!NetworkTopology.DEFAULT_RACK.equals(location)) { 380 buffer.append(" "+location); 381 } 382 if (isDecommissioned()) { 383 buffer.append(" DD"); 384 } else if (isDecommissionInProgress()) { 385 buffer.append(" DP"); 386 } else { 387 buffer.append(" IN"); 388 } 389 buffer.append(" " + c + "(" + StringUtils.byteDesc(c)+")"); 390 buffer.append(" " + u + "(" + StringUtils.byteDesc(u)+")"); 391 buffer.append(" " + percent2String(usedPercent)); 392 buffer.append(" " + r + "(" + StringUtils.byteDesc(r)+")"); 393 buffer.append(" " + cc + "(" + StringUtils.byteDesc(cc)+")"); 394 buffer.append(" " + cu + "(" + StringUtils.byteDesc(cu)+")"); 395 buffer.append(" " + percent2String(cacheUsedPercent)); 396 buffer.append(" " + cr + "(" + StringUtils.byteDesc(cr)+")"); 397 buffer.append(" " + new Date(lastUpdate)); 398 return buffer.toString(); 399 } 400 401 /** 402 * Start decommissioning a node. 403 * old state. 404 */ startDecommission()405 public void startDecommission() { 406 adminState = AdminStates.DECOMMISSION_INPROGRESS; 407 } 408 409 /** 410 * Stop decommissioning a node. 411 * old state. 412 */ stopDecommission()413 public void stopDecommission() { 414 adminState = null; 415 } 416 417 /** 418 * Returns true if the node is in the process of being decommissioned 419 */ isDecommissionInProgress()420 public boolean isDecommissionInProgress() { 421 return adminState == AdminStates.DECOMMISSION_INPROGRESS; 422 } 423 424 /** 425 * Returns true if the node has been decommissioned. 426 */ isDecommissioned()427 public boolean isDecommissioned() { 428 return adminState == AdminStates.DECOMMISSIONED; 429 } 430 431 /** 432 * Sets the admin state to indicate that decommission is complete. 433 */ setDecommissioned()434 public void setDecommissioned() { 435 adminState = AdminStates.DECOMMISSIONED; 436 } 437 438 /** 439 * Retrieves the admin state of this node. 440 */ getAdminState()441 public AdminStates getAdminState() { 442 if (adminState == null) { 443 return AdminStates.NORMAL; 444 } 445 return adminState; 446 } 447 448 /** 449 * Check if the datanode is in stale state. Here if 450 * the namenode has not received heartbeat msg from a 451 * datanode for more than staleInterval (default value is 452 * {@link DFSConfigKeys#DFS_NAMENODE_STALE_DATANODE_INTERVAL_DEFAULT}), 453 * the datanode will be treated as stale node. 454 * 455 * @param staleInterval 456 * the time interval for marking the node as stale. If the last 457 * update time is beyond the given time interval, the node will be 458 * marked as stale. 459 * @return true if the node is stale 460 */ isStale(long staleInterval)461 public boolean isStale(long staleInterval) { 462 return (Time.monotonicNow() - lastUpdateMonotonic) >= staleInterval; 463 } 464 465 /** 466 * Sets the admin state of this node. 467 */ setAdminState(AdminStates newState)468 protected void setAdminState(AdminStates newState) { 469 if (newState == AdminStates.NORMAL) { 470 adminState = null; 471 } 472 else { 473 adminState = newState; 474 } 475 } 476 477 private transient int level; //which level of the tree the node resides 478 private transient Node parent; //its parent 479 480 /** Return this node's parent */ 481 @Override getParent()482 public Node getParent() { return parent; } 483 @Override setParent(Node parent)484 public void setParent(Node parent) {this.parent = parent;} 485 486 /** Return this node's level in the tree. 487 * E.g. the root of a tree returns 0 and its children return 1 488 */ 489 @Override getLevel()490 public int getLevel() { return level; } 491 @Override setLevel(int level)492 public void setLevel(int level) {this.level = level;} 493 494 @Override hashCode()495 public int hashCode() { 496 // Super implementation is sufficient 497 return super.hashCode(); 498 } 499 500 @Override equals(Object obj)501 public boolean equals(Object obj) { 502 // Sufficient to use super equality as datanodes are uniquely identified 503 // by DatanodeID 504 return (this == obj) || super.equals(obj); 505 } 506 getSoftwareVersion()507 public String getSoftwareVersion() { 508 return softwareVersion; 509 } 510 setSoftwareVersion(String softwareVersion)511 public void setSoftwareVersion(String softwareVersion) { 512 this.softwareVersion = softwareVersion; 513 } 514 } 515