/*
* 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.flink.runtime.clusterframework.types;
import javax.annotation.Nonnull;
import java.io.Serializable;
/**
* Describe the resource profile of the slot, either when requiring or offering it. The profile can be
* checked whether it can match another profile's requirement, and furthermore we may calculate a matching
* score to decide which profile we should choose when we have lots of candidate slots.
*
* <p>Resource Profiles have a total ordering, defined by comparing these fields in sequence:
* <ol>
* <li>Memory Size</li>
* <li>CPU cores</li>
* </ol>
*/
public class ResourceProfile implements Serializable, Comparable<ResourceProfile> {
private static final long serialVersionUID = 1L;
public static final ResourceProfile UNKNOWN = new ResourceProfile(-1.0, -1);
// ------------------------------------------------------------------------
/** How many cpu cores are needed, use double so we can specify cpu like 0.1 */
private final double cpuCores;
/** How many heap memory in mb are needed */
private final int heapMemoryInMB;
/** How many direct memory in mb are needed */
private final int directMemoryInMB;
/** How many native memory in mb are needed */
private final int nativeMemoryInMB;
// ------------------------------------------------------------------------
/**
* Creates a new ResourceProfile.
*
* @param cpuCores The number of CPU cores (possibly fractional, i.e., 0.2 cores)
* @param heapMemoryInMB The size of the heap memory, in megabytes.
* @param directMemoryInMB The size of the direct memory, in megabytes.
* @param nativeMemoryInMB The size of the native memory, in megabytes.
*/
public ResourceProfile(
double cpuCores,
int heapMemoryInMB,
int directMemoryInMB,
int nativeMemoryInMB) {
this.cpuCores = cpuCores;
this.heapMemoryInMB = heapMemoryInMB;
this.directMemoryInMB = directMemoryInMB;
this.nativeMemoryInMB = nativeMemoryInMB;
}
/**
* Creates a new simple ResourceProfile used for testing.
*
* @param cpuCores The number of CPU cores (possibly fractional, i.e., 0.2 cores)
* @param heapMemoryInMB The size of the heap memory, in megabytes.
*/
public ResourceProfile(double cpuCores, int heapMemoryInMB) {
this.cpuCores = cpuCores;
this.heapMemoryInMB = heapMemoryInMB;
this.directMemoryInMB = 0;
this.nativeMemoryInMB = 0;
}
/**
* Creates a copy of the given ResourceProfile.
*
* @param other The ResourceProfile to copy.
*/
public ResourceProfile(ResourceProfile other) {
this.cpuCores = other.cpuCores;
this.heapMemoryInMB = other.heapMemoryInMB;
this.directMemoryInMB = other.directMemoryInMB;
this.nativeMemoryInMB = other.nativeMemoryInMB;
}
// ------------------------------------------------------------------------
/**
* Get the cpu cores needed
* @return The cpu cores, 1.0 means a full cpu thread
*/
public double getCpuCores() {
return cpuCores;
}
/**
* Get the heap memory needed in MB
* @return The heap memory in MB
*/
public long getHeapMemoryInMB() {
return heapMemoryInMB;
}
/**
* Get the direct memory needed in MB
* @return The direct memory in MB
*/
public int getDirectMemoryInMB() {
return directMemoryInMB;
}
/**
* Get the native memory needed in MB
* @return The native memory in MB
*/
public int getNativeMemoryInMB() {
return nativeMemoryInMB;
}
/**
* Get the total memory needed in MB
* @return The total memory in MB
*/
public int getMemoryInMB() {
return heapMemoryInMB + directMemoryInMB + nativeMemoryInMB;
}
/**
* Check whether required resource profile can be matched
*
* @param required the required resource profile
* @return true if the requirement is matched, otherwise false
*/
public boolean isMatching(ResourceProfile required) {
return cpuCores >= required.getCpuCores() &&
heapMemoryInMB >= required.getHeapMemoryInMB() &&
directMemoryInMB >= required.getDirectMemoryInMB() &&
nativeMemoryInMB >= required.getNativeMemoryInMB();
}
@Override
public int compareTo(@Nonnull ResourceProfile other) {
int cmp1 = Integer.compare(this.getMemoryInMB(), other.getMemoryInMB());
int cmp2 = Double.compare(this.cpuCores, other.cpuCores);
return (cmp1 != 0) ? cmp1 : cmp2;
}
// ------------------------------------------------------------------------
@Override
public int hashCode() {
final long cpuBits = Double.doubleToLongBits(cpuCores);
int result = (int) (cpuBits ^ (cpuBits >>> 32));
result = 31 * result + heapMemoryInMB;
result = 31 * result + directMemoryInMB;
result = 31 * result + nativeMemoryInMB;
return result;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
else if (obj != null && obj.getClass() == ResourceProfile.class) {
ResourceProfile that = (ResourceProfile) obj;
return this.cpuCores == that.cpuCores &&
this.heapMemoryInMB == that.heapMemoryInMB &&
this.directMemoryInMB == that.directMemoryInMB;
}
else {
return false;
}
}
@Override
public String toString() {
return "ResourceProfile{" +
"cpuCores=" + cpuCores +
", heapMemoryInMB=" + heapMemoryInMB +
", directMemoryInMB=" + directMemoryInMB +
", nativeMemoryInMB=" + nativeMemoryInMB +
'}';
}
}