package org.cloudbus.cloudsim.container.schedulers;
import org.cloudbus.cloudsim.container.containerProvisioners.ContainerPe;
import org.cloudbus.cloudsim.container.lists.ContainerPeList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by sareh on 22/07/15.
*/
public class ContainerSchedulerTimeSharedOverSubscription extends ContainerSchedulerTimeShared {
/**
* Instantiates a new container scheduler time shared.
*
* @param pelist the pelist
*/
public ContainerSchedulerTimeSharedOverSubscription(List<? extends ContainerPe> pelist) {
super(pelist);
}
@Override
public boolean allocatePesForContainer(String containerUid, List<Double> mipsShareRequested) {
double totalRequestedMips = 0;
// if the requested mips is bigger than the capacity of a single PE, we cap
// the request to the PE's capacity
List<Double> mipsShareRequestedCapped = new ArrayList<Double>();
double peMips = getPeCapacity();
for (Double mips : mipsShareRequested) {
if (mips > peMips) {
mipsShareRequestedCapped.add(peMips);
totalRequestedMips += peMips;
} else {
mipsShareRequestedCapped.add(mips);
totalRequestedMips += mips;
}
}
if (getContainersMigratingIn().contains(containerUid)) {
// the destination host only experience 10% of the migrating VM's MIPS
totalRequestedMips = 0.0;
}else {
getMipsMapRequested().put(containerUid, mipsShareRequested);
setPesInUse(getPesInUse() + mipsShareRequested.size());
}
if (getAvailableMips() >= totalRequestedMips) {
List<Double> mipsShareAllocated = new ArrayList<Double>();
for (Double mipsRequested : mipsShareRequestedCapped) {
// if (getContainersMigratingOut().contains(containerUid)) {
// // performance degradation due to migration = 10% MIPS
// mipsRequested *= 0.9;
// } else
if (!getContainersMigratingIn().contains(containerUid)) {
// the destination host only experience 10% of the migrating VM's MIPS
mipsShareAllocated.add(mipsRequested);
}
}
getMipsMap().put(containerUid, mipsShareAllocated);
// getMipsMap().put(containerUid, mipsShareRequestedCapped);
setAvailableMips(getAvailableMips() - totalRequestedMips);
} else {
redistributeMipsDueToOverSubscription();
}
return true;
}
/**
* This method recalculates distribution of MIPs among VMs considering eventual shortage of MIPS
* compared to the amount requested by VMs.
*/
protected void redistributeMipsDueToOverSubscription() {
// First, we calculate the scaling factor - the MIPS allocation for all VMs will be scaled
// proportionally
double totalRequiredMipsByAllVms = 0;
Map<String, List<Double>> mipsMapCapped = new HashMap<String, List<Double>>();
for (Map.Entry<String, List<Double>> entry : getMipsMapRequested().entrySet()) {
double requiredMipsByThisContainer = 0.0;
String vmId = entry.getKey();
List<Double> mipsShareRequested = entry.getValue();
List<Double> mipsShareRequestedCapped = new ArrayList<Double>();
double peMips = getPeCapacity();
for (Double mips : mipsShareRequested) {
if (mips > peMips) {
mipsShareRequestedCapped.add(peMips);
requiredMipsByThisContainer += peMips;
} else {
mipsShareRequestedCapped.add(mips);
requiredMipsByThisContainer += mips;
}
}
mipsMapCapped.put(vmId, mipsShareRequestedCapped);
// if (getContainersMigratingIn().contains(entry.getKey())) {
// // the destination host only experience 10% of the migrating VM's MIPS
// requiredMipsByThisContainer *= 0.1;
// }
totalRequiredMipsByAllVms += requiredMipsByThisContainer;
}
double totalAvailableMips = ContainerPeList.getTotalMips(getPeList());
double scalingFactor = totalAvailableMips / totalRequiredMipsByAllVms;
// Clear the old MIPS allocation
getMipsMap().clear();
// Update the actual MIPS allocated to the VMs
for (Map.Entry<String, List<Double>> entry : mipsMapCapped.entrySet()) {
String vmUid = entry.getKey();
List<Double> requestedMips = entry.getValue();
List<Double> updatedMipsAllocation = new ArrayList<Double>();
for (Double mips : requestedMips) {
// if (getContainersMigratingOut().contains(vmUid)) {
// the original amount is scaled
// mips *= scalingFactor;
// performance degradation due to migration = 10% MIPS
// mips *= 0.9;
// } else
if (!getContainersMigratingIn().contains(vmUid)) {
// the destination host only experiences 10% of the migrating VM's MIPS
mips *= scalingFactor;
updatedMipsAllocation.add(Math.floor(mips));
// the final 10% of the requested MIPS are scaled
// mips *= scalingFactor;
}
}
requestedMips.clear();
// add in the new map
getMipsMap().put(vmUid, updatedMipsAllocation);
}
mipsMapCapped.clear();
// As the host is oversubscribed, there no more available MIPS
setAvailableMips(0);
}
}