package org.apache.hadoop.corona; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * Maintain parameters for sorting */ public abstract class Schedulable { final private String name; final private String type; protected int requested; protected int granted; private double share; public Schedulable(String name, String type) { this.name = name; this.type = type; } public String getName() { return name; } public String getType() { return type; } /** * Take a snapshot of requested and granted */ abstract public void snapshot(); /** * Number of current requested resource at the last snapshot */ public int getRequested() { return requested; } /** * Number of current granted resource at the last snapshot */ public int getGranted() { return granted; } /** * Change the number of granted resource since last snapshot */ public void incGranted(int diff) { granted += diff; } /** * Proportional to the number of resource this schedulable should get */ public double getWeight() { return 1.0; } /** * The minimum number of resource this schedulable should get */ public int getMinimum() { return 0; } /** * The maximum number of resource this schedulable should get */ public int getMaximum() { return Integer.MAX_VALUE; } /** * Start time of this schedulable. Can be used for FIFO sort */ public long getStartTime() { return -1L; } /** * The target number of granted resource should get in equilibrium */ public double getShare() { return share; } /** * Set the share of the schedulables based on the total */ public static void distributeShare( double total, final Collection<? extends Schedulable> schedulables, ScheduleComparator comparator) { switch (comparator) { case FIFO: Schedulable.distributeShareFifo(total, schedulables); break; case FAIR: Schedulable.distributeShareFair(total, schedulables); break; default: throw new IllegalArgumentException("Unknown comparator"); } } private static void distributeShareFifo( double total, final Collection<? extends Schedulable> schedulables) { List<Schedulable> sches = new ArrayList<Schedulable>(schedulables); Collections.sort(sches, ScheduleComparator.FIFO); for (Schedulable schedulable : sches) { int max = Math.min(schedulable.getRequested(), schedulable.getMaximum()); if (total > max) { schedulable.share = max; total -= max; } else { schedulable.share = total; return; } } } private static void distributeShareFair( double total, final Collection<? extends Schedulable> schedulables) { BinarySearcher searcher = new BinarySearcher() { @Override protected double targetFunction(double x) { return totalShareWithRatio(schedulables, x); } }; double ratio = searcher.getSolution(total); for (Schedulable schedulable : schedulables) { schedulable.share = shareWithRatio(schedulable, ratio); } } private static double totalShareWithRatio( Collection<? extends Schedulable> schedulables, double weightToShareRatio) { double totalShare = 0; for (Schedulable schedulable : schedulables) { totalShare += shareWithRatio(schedulable, weightToShareRatio); } return totalShare; } private static double shareWithRatio( Schedulable schedulable, double weightToShareRatio) { double share = schedulable.getWeight() * weightToShareRatio; int min = schedulable.getMinimum(); int max = schedulable.getMaximum(); int requested = schedulable.getRequested(); share = Math.max(min, share); share = Math.min(max, share); share = Math.min(requested, share); return share; } }