blob: d80f3f120f7d4123b634750c19be976c24cfdee5 [file] [log] [blame]
/**
* 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.hdds.scm.node;
import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto
.StorageContainerDatanodeProtocolProtos.LayoutVersionProto;
import org.apache.hadoop.hdds.protocol.proto
.StorageContainerDatanodeProtocolProtos.StorageReportProto;
import org.apache.hadoop.hdds.protocol.proto
.StorageContainerDatanodeProtocolProtos.MetadataStorageReportProto;
import org.apache.hadoop.util.Time;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* This class extends the primary identifier of a Datanode with ephemeral
* state, eg last reported time, usage information etc.
*/
public class DatanodeInfo extends DatanodeDetails {
private final ReadWriteLock lock;
private volatile long lastHeartbeatTime;
private long lastStatsUpdatedTime;
private List<StorageReportProto> storageReports;
private List<MetadataStorageReportProto> metadataStorageReports;
private LayoutVersionProto lastKnownLayoutVersion;
private NodeStatus nodeStatus;
/**
* Constructs DatanodeInfo from DatanodeDetails.
*
* @param datanodeDetails Details about the datanode
* @param nodeStatus Node Status
* @param layoutInfo Details about the LayoutVersionProto
*/
public DatanodeInfo(DatanodeDetails datanodeDetails, NodeStatus nodeStatus,
LayoutVersionProto layoutInfo) {
super(datanodeDetails);
this.lock = new ReentrantReadWriteLock();
this.lastHeartbeatTime = Time.monotonicNow();
lastKnownLayoutVersion =
LayoutVersionProto.newBuilder()
.setMetadataLayoutVersion(layoutInfo != null ?
layoutInfo.getMetadataLayoutVersion() : 0)
.setSoftwareLayoutVersion(layoutInfo != null ?
layoutInfo.getSoftwareLayoutVersion() : 0)
.build();
this.storageReports = Collections.emptyList();
this.nodeStatus = nodeStatus;
this.metadataStorageReports = Collections.emptyList();
}
/**
* Updates the last heartbeat time with current time.
*/
public void updateLastHeartbeatTime() {
updateLastHeartbeatTime(Time.monotonicNow());
}
/**
* Sets the last heartbeat time to a given value. Intended to be used
* only for tests.
*
* @param milliSecondsSinceEpoch - ms since Epoch to set as the heartbeat time
*/
@VisibleForTesting
public void updateLastHeartbeatTime(long milliSecondsSinceEpoch) {
try {
lock.writeLock().lock();
lastHeartbeatTime = milliSecondsSinceEpoch;
} finally {
lock.writeLock().unlock();
}
}
/**
* Updates the last LayoutVersion.
*/
public void updateLastKnownLayoutVersion(LayoutVersionProto version) {
if (version == null) {
return;
}
try {
lock.writeLock().lock();
lastKnownLayoutVersion = LayoutVersionProto.newBuilder()
.setMetadataLayoutVersion(version.getMetadataLayoutVersion())
.setSoftwareLayoutVersion(version.getSoftwareLayoutVersion())
.build();
} finally {
lock.writeLock().unlock();
}
}
/**
* Returns the last heartbeat time.
*
* @return last heartbeat time.
*/
public long getLastHeartbeatTime() {
try {
lock.readLock().lock();
return lastHeartbeatTime;
} finally {
lock.readLock().unlock();
}
}
/**
* Returns the last known Layout Version .
*
* @return last Layout Version.
*/
public LayoutVersionProto getLastKnownLayoutVersion() {
try {
lock.readLock().lock();
return lastKnownLayoutVersion;
} finally {
lock.readLock().unlock();
}
}
/**
* Updates the datanode storage reports.
*
* @param reports list of storage report
*/
public void updateStorageReports(List<StorageReportProto> reports) {
try {
lock.writeLock().lock();
lastStatsUpdatedTime = Time.monotonicNow();
storageReports = reports;
} finally {
lock.writeLock().unlock();
}
}
/**
* Updates the datanode metadata storage reports.
*
* @param reports list of metadata storage report
*/
public void updateMetaDataStorageReports(
List<MetadataStorageReportProto> reports) {
try {
lock.writeLock().lock();
lastStatsUpdatedTime = Time.monotonicNow();
metadataStorageReports = reports;
} finally {
lock.writeLock().unlock();
}
}
/**
* Returns the storage reports associated with this datanode.
*
* @return list of storage report
*/
public List<StorageReportProto> getStorageReports() {
try {
lock.readLock().lock();
return storageReports;
} finally {
lock.readLock().unlock();
}
}
/**
* Returns count of healthy volumes reported from datanode.
* @return count of healthy volumes
*/
public int getHealthyVolumeCount() {
try {
lock.readLock().lock();
return storageReports.size() - getFailedVolumeCount();
} finally {
lock.readLock().unlock();
}
}
/**
* Returns count of healthy metadata volumes reported from datanode.
* @return count of healthy metdata log volumes
*/
public int getMetaDataVolumeCount() {
try {
lock.readLock().lock();
return metadataStorageReports.size();
} finally {
lock.readLock().unlock();
}
}
/**
* Returns count of failed volumes reported from datanode.
* @return count of failed volumes
*/
private int getFailedVolumeCount() {
return (int) storageReports.stream().
filter(e -> e.hasFailed() ? e.getFailed() : false).count();
}
/**
* Returns the last updated time of datanode info.
* @return the last updated time of datanode info.
*/
public long getLastStatsUpdatedTime() {
return lastStatsUpdatedTime;
}
/**
* Return the current NodeStatus for the datanode.
*
* @return NodeStatus - the current nodeStatus
*/
public NodeStatus getNodeStatus() {
try {
lock.readLock().lock();
return nodeStatus;
} finally {
lock.readLock().unlock();
}
}
/**
* Update the NodeStatus for this datanode. When using this method
* be ware of the potential for lost updates if two threads read the
* current status, update one field and then write it back without
* locking enforced outside of this class.
*
* @param newNodeStatus - the new NodeStatus object
*/
public void setNodeStatus(NodeStatus newNodeStatus) {
try {
lock.writeLock().lock();
this.nodeStatus = newNodeStatus;
} finally {
lock.writeLock().unlock();
}
}
@Override
public int hashCode() {
return super.hashCode();
}
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
}