/**
* 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.dfs;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Date;
import org.apache.hadoop.fs.FsShell;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableFactories;
import org.apache.hadoop.io.WritableFactory;
import org.apache.hadoop.io.WritableUtils;
import org.apache.hadoop.net.NetworkTopology;
import org.apache.hadoop.net.Node;
import org.apache.hadoop.net.NodeBase;
/**
* DatanodeInfo represents the status of a DataNode.
* This object is used for communication in the
* Datanode Protocol and the Client Protocol.
*/
public class DatanodeInfo extends DatanodeID implements Node {
protected long capacity;
protected long dfsUsed;
protected long remaining;
protected long lastUpdate;
protected int xceiverCount;
protected String location = NetworkTopology.UNRESOLVED;
/** HostName as suplied by the datanode during registration as its
* name. Namenode uses datanode IP address as the name.
*/
protected String hostName = null;
// administrative states of a datanode
public enum AdminStates {NORMAL, DECOMMISSION_INPROGRESS, DECOMMISSIONED; }
protected AdminStates adminState;
DatanodeInfo() {
super();
adminState = null;
}
DatanodeInfo(DatanodeInfo from) {
super(from);
this.capacity = from.getCapacity();
this.dfsUsed = from.getDfsUsed();
this.remaining = from.getRemaining();
this.lastUpdate = from.getLastUpdate();
this.xceiverCount = from.getXceiverCount();
this.location = from.getNetworkLocation();
this.adminState = from.adminState;
this.hostName = from.hostName;
}
DatanodeInfo(DatanodeID nodeID) {
super(nodeID);
this.capacity = 0L;
this.dfsUsed = 0L;
this.remaining = 0L;
this.lastUpdate = 0L;
this.xceiverCount = 0;
this.adminState = null;
}
DatanodeInfo(DatanodeID nodeID, String location, String hostName) {
this(nodeID);
this.location = location;
this.hostName = hostName;
}
/** The raw capacity. */
public long getCapacity() { return capacity; }
/** The used space by the data node. */
public long getDfsUsed() { return dfsUsed; }
/** The raw free space. */
public long getRemaining() { return remaining; }
/** The time when this information was accurate. */
public long getLastUpdate() { return lastUpdate; }
/** number of active connections */
public int getXceiverCount() { return xceiverCount; }
/** Sets raw capacity. */
void setCapacity(long capacity) {
this.capacity = capacity;
}
/** Sets raw free space. */
void setRemaining(long remaining) {
this.remaining = remaining;
}
/** Sets time when this information was accurate. */
void setLastUpdate(long lastUpdate) {
this.lastUpdate = lastUpdate;
}
/** Sets number of active connections */
void setXceiverCount(int xceiverCount) {
this.xceiverCount = xceiverCount;
}
/** rack name **/
public synchronized String getNetworkLocation() {return location;}
/** Sets the rack name */
public synchronized void setNetworkLocation(String location) {
this.location = NodeBase.normalize(location);
}
public String getHostName() {
return (hostName == null || hostName.length()==0) ? getHost() : hostName;
}
public void setHostName(String host) {
hostName = host;
}
/** A formatted string for reporting the status of the DataNode. */
public String getDatanodeReport() {
StringBuffer buffer = new StringBuffer();
long c = getCapacity();
long r = getRemaining();
long u = getDfsUsed();
buffer.append("Name: "+name+"\n");
if (!NetworkTopology.UNRESOLVED.equals(location) &&
!NetworkTopology.DEFAULT_RACK.equals(location)) {
buffer.append("Rack: "+location+"\n");
}
if (isDecommissioned()) {
buffer.append("State : Decommissioned\n");
} else if (isDecommissionInProgress()) {
buffer.append("State : Decommission in progress\n");
} else {
buffer.append("State : In Service\n");
}
buffer.append("Total raw bytes: "+c+" ("+FsShell.byteDesc(c)+")"+"\n");
buffer.append("Remaining raw bytes: " +r+ "("+FsShell.byteDesc(r)+")"+"\n");
buffer.append("Used raw bytes: "+u+" ("+FsShell.byteDesc(u)+")"+"\n");
buffer.append("% used: "+FsShell.limitDecimalTo2(((1.0*u)/c)*100)+"%"+"\n");
buffer.append("Last contact: "+new Date(lastUpdate)+"\n");
return buffer.toString();
}
/** A formatted string for printing the status of the DataNode. */
String dumpDatanode() {
StringBuffer buffer = new StringBuffer();
long c = getCapacity();
long r = getRemaining();
long u = getDfsUsed();
buffer.append(name);
if (!NetworkTopology.UNRESOLVED.equals(location) &&
!NetworkTopology.DEFAULT_RACK.equals(location)) {
buffer.append(" "+location);
}
if (isDecommissioned()) {
buffer.append(" DD");
} else if (isDecommissionInProgress()) {
buffer.append(" DP");
} else {
buffer.append(" IN");
}
buffer.append(" " + c + "(" + FsShell.byteDesc(c)+")");
buffer.append(" " + u + "(" + FsShell.byteDesc(u)+")");
buffer.append(" " + FsShell.limitDecimalTo2(((1.0*u)/c)*100)+"%");
buffer.append(" " + r + "(" + FsShell.byteDesc(r)+")");
buffer.append(" " + new Date(lastUpdate));
return buffer.toString();
}
/**
* Start decommissioning a node.
* old state.
*/
void startDecommission() {
adminState = AdminStates.DECOMMISSION_INPROGRESS;
}
/**
* Stop decommissioning a node.
* old state.
*/
void stopDecommission() {
adminState = null;
}
/**
* Returns true if the node is in the process of being decommissioned
*/
boolean isDecommissionInProgress() {
if (adminState == AdminStates.DECOMMISSION_INPROGRESS) {
return true;
}
return false;
}
/**
* Returns true if the node has been decommissioned.
*/
boolean isDecommissioned() {
if (adminState == AdminStates.DECOMMISSIONED) {
return true;
}
return false;
}
/**
* Sets the admin state to indicate that decommision is complete.
*/
void setDecommissioned() {
adminState = AdminStates.DECOMMISSIONED;
}
/**
* Retrieves the admin state of this node.
*/
AdminStates getAdminState() {
if (adminState == null) {
return AdminStates.NORMAL;
}
return adminState;
}
/**
* Sets the admin state of this node.
*/
void setAdminState(AdminStates newState) {
if (newState == AdminStates.NORMAL) {
adminState = null;
}
else {
adminState = newState;
}
}
private int level; //which level of the tree the node resides
private Node parent; //its parent
/** Return this node's parent */
public Node getParent() { return parent; }
public void setParent(Node parent) {this.parent = parent;}
/** Return this node's level in the tree.
* E.g. the root of a tree returns 0 and its children return 1
*/
public int getLevel() { return level; }
public void setLevel(int level) {this.level = level;}
/////////////////////////////////////////////////
// Writable
/////////////////////////////////////////////////
static { // register a ctor
WritableFactories.setFactory
(DatanodeInfo.class,
new WritableFactory() {
public Writable newInstance() { return new DatanodeInfo(); }
});
}
/** {@inheritDoc} */
public void write(DataOutput out) throws IOException {
super.write(out);
//TODO: move it to DatanodeID once DatanodeID is not stored in FSImage
out.writeShort(ipcPort);
out.writeLong(capacity);
out.writeLong(dfsUsed);
out.writeLong(remaining);
out.writeLong(lastUpdate);
out.writeInt(xceiverCount);
Text.writeString(out, location);
Text.writeString(out, hostName == null? "": hostName);
WritableUtils.writeEnum(out, getAdminState());
}
/** {@inheritDoc} */
public void readFields(DataInput in) throws IOException {
super.readFields(in);
//TODO: move it to DatanodeID once DatanodeID is not stored in FSImage
this.ipcPort = in.readShort() & 0x0000ffff;
this.capacity = in.readLong();
this.dfsUsed = in.readLong();
this.remaining = in.readLong();
this.lastUpdate = in.readLong();
this.xceiverCount = in.readInt();
this.location = Text.readString(in);
this.hostName = Text.readString(in);
setAdminState(WritableUtils.readEnum(in, AdminStates.class));
}
}