/*
* Copyright 2017 LinkedIn Corp. All rights reserved.
*
* Licensed 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.
*/
package com.github.ambry.clustermap;
import com.github.ambry.config.ClusterMapConfig;
import com.github.ambry.utils.Utils;
import java.io.File;
/**
* {@link DiskId} implementation to use within dynamic cluster managers.
*/
class AmbryDisk implements DiskId, Resource {
private final AmbryDataNode datanode;
private final String mountPath;
private final long rawCapacityBytes;
private final ResourceStatePolicy resourceStatePolicy;
/**
* Instantiate an AmbryDisk object.
* @param clusterMapConfig the {@link ClusterMapConfig} to use.
* @param datanode the {@link AmbryDataNode} on which this disk resides.
* @param mountPath the mount path at which this disk is mounted on the datanode.
* @param state the initial {@link HardwareState} of this disk.
* @param rawCapacityBytes the capacity in bytes.
* @throws Exception if there is an exception in instantiating the {@link ResourceStatePolicy}
*/
AmbryDisk(ClusterMapConfig clusterMapConfig, AmbryDataNode datanode, String mountPath, HardwareState state,
long rawCapacityBytes) throws Exception {
this.datanode = datanode;
this.mountPath = mountPath;
this.rawCapacityBytes = rawCapacityBytes;
ResourceStatePolicyFactory resourceStatePolicyFactory =
Utils.getObj(clusterMapConfig.clusterMapResourceStatePolicyFactory, this, state, clusterMapConfig);
this.resourceStatePolicy = resourceStatePolicyFactory.getResourceStatePolicy();
validate();
}
/**
* Validate the newly constructed AmbryDisk instance.
*/
private void validate() {
if (datanode == null || mountPath == null) {
throw new IllegalStateException("datanode and mount path cannot be null.");
}
if (mountPath.length() == 0) {
throw new IllegalStateException("Mount path cannot be zero-length string.");
}
File mountPathFile = new File(mountPath);
if (!mountPathFile.isAbsolute()) {
throw new IllegalStateException("Mount path has to be an absolute path.");
}
ClusterMapUtils.validateDiskCapacity(rawCapacityBytes);
}
@Override
public String getMountPath() {
return mountPath;
}
@Override
public HardwareState getState() {
return resourceStatePolicy.isDown() || datanode.getState() == HardwareState.UNAVAILABLE ? HardwareState.UNAVAILABLE
: HardwareState.AVAILABLE;
}
@Override
public long getRawCapacityInBytes() {
return rawCapacityBytes;
}
@Override
public String toString() {
return "Disk[" + datanode.getHostname() + ":" + datanode.getPort() + ":" + getMountPath() + "]";
}
/**
* @return the {@link AmbryDataNode} associated with this disk.
*/
AmbryDataNode getDataNode() {
return datanode;
}
/**
* Set the hard state of this disk dynamically.
* @param newState the updated {@link HardwareState}
*/
void setState(HardwareState newState) {
if (newState == HardwareState.AVAILABLE) {
resourceStatePolicy.onHardUp();
} else {
resourceStatePolicy.onHardDown();
}
}
/**
* Take actions, if any, when an error is received for this disk.
*/
void onDiskError() {
resourceStatePolicy.onError();
}
/**
* Take actions, if any, when this disk is back in a good state.
*/
void onDiskOk() {
resourceStatePolicy.onSuccess();
}
}