/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.ow2.choreos.ee.nodes.selector;
import java.util.ArrayList;
import java.util.List;
import org.ow2.choreos.ee.config.QoSManagementConfiguration;
import org.ow2.choreos.nodes.datamodel.CloudNode;
import org.ow2.choreos.nodes.datamodel.MemoryType;
import org.ow2.choreos.nodes.datamodel.ResourceImpact;
import org.ow2.choreos.selectors.ObjectFilter;
import org.ow2.choreos.services.datamodel.DeployableServiceSpec;
/**
* Filter nodes that match requirements. The filter policy is extracted from
* MAPPER_POLICY configuration. The default behavior if the ANY_FIT policy.
*
* @author leonardo
*
*/
class NodeFilter implements ObjectFilter<CloudNode, DeployableServiceSpec> {
private enum MapperPolicy {
ANY_FIT, EXACT_FIT
};
private static final String MAPPER_POLICY_PROPERTY = "MAPPER_POLICY";
private static final MapperPolicy DEFAULT_MAPPER_POLICY = MapperPolicy.ANY_FIT;
private static final String[] NODE_TYPES = QoSManagementConfiguration
.getMultiple(QoSManagementConfiguration.NODE_TYPES);
private MapperPolicy policy;
public NodeFilter() {
this.policy = this.retrieveMapperPolicy();
}
private MapperPolicy retrieveMapperPolicy() {
MapperPolicy mapperPolicy = DEFAULT_MAPPER_POLICY;
String policyStr = QoSManagementConfiguration.get(QoSManagementConfiguration.MAPPER_POLICY);
try {
mapperPolicy = MapperPolicy.valueOf(policyStr);
} catch (Exception e) {
mapperPolicy = DEFAULT_MAPPER_POLICY;
}
return mapperPolicy;
}
public static String[] types() {
return NODE_TYPES;
}
@Override
public List<CloudNode> filter(List<CloudNode> nodes, DeployableServiceSpec spec) {
List<CloudNode> filtered = new ArrayList<CloudNode>();
for (CloudNode node : nodes) {
if (isAcceptable(spec.getResourceImpact(), node)) {
filtered.add(node);
}
}
return filtered;
}
private boolean near(int a, int b) {
if (Math.abs(a - b) < 0.1 * (double) a)
return true;
return false;
}
private int getBaseMemoryFromType(MemoryType memory) {
switch (memory) {
case SMALL:
return 256;
case MEDIUM:
return 512;
case LARGE:
return 768;
default:
return 256;
}
}
private boolean isAcceptable(ResourceImpact resourceImpact, CloudNode selected) {
if (noMemoryRequirements(resourceImpact)) {
return true;
}
switch (this.policy) {
case ANY_FIT:
return getBaseMemoryFromType(resourceImpact.getMemory()) <= selected.getRam();
case EXACT_FIT:
return near(getBaseMemoryFromType(resourceImpact.getMemory()), selected.getRam());
default:
return false;
}
}
private boolean noMemoryRequirements(ResourceImpact resourceImpact) {
return resourceImpact == null || resourceImpact.getMemory() == null;
}
}