3

There is a LinkedList with the name busyList that keeps track of all the machines that are busy.A machine may be busy or available.The id of the machine is removed from the list when it gets free.

Following is the method that gets fired whenever the machine gets free/busy

@Override
public void cloudSimEventFired(CloudSimEvent e) {
    if(e.getId() == CloudSimEvents.EVENT_CLOUDLET_ALLOCATED_TO_VM) {
        int vmId = (Integer) e.getParameter(Constants.PARAM_VM_ID);
        busyList.add(vmId);
    }else if(e.getId() == CloudSimEvents.EVENT_VM_FINISHED_CLOUDLET) {
        int vmId = (Integer) e.getParameter(Constants.PARAM_VM_ID);
        busyList.remove(new Integer(vmId));
    }
}

A map named allMap (for allocation map) has id of the machine as its key and an object of class VmAllocation as its value.The attributes of VmAllocation are :

maxAlloc (which tells the maximum times a machine can be returned)
currAlloc (which tells the current count)

/*
   allMap.put(id, new VmAllocation(o.getMemory()/512, 0));

   o.getMemory()/512 => maxAlloc
   0 => currAlloc

   This map has been initialized earlier.Like for 3 machines id will be 0,1,2
   As the machine will be returned currAlloc will be incremented by 1
   but it cannot exceed maxAlloc.  
*/

I have to return the machines in a round robin fashion while keeping in view, that I do not return the machine that is busy at the moment.If busyList.contains(id) returns true, it means the machine is busy and the next available machine (in the allMap) is returned also keeping in view that it doesn't get more than maxAlloc set for it. For example if 1 comes busy, then 2 will be returned if 2 is not busy and currAlloc has not exceeded maxAlloc

Following is the method that has to return the machine and is called multiple times from outside the enclosing class.

@Override
    public int getNextAvailableVm() {
                  // return the id
    }   

This is the general way algorithm shall work :

Let the id of the machines inside the allMap be :
     0,1,2,3,4
     0 has maxAlloc of 4
     1 has maxAlloc of 4
     2,3 has maxAlloc of 2
     4 has maxAlloc of 1

    The ideal order of returning will be :
    0000 1111 22 33 4 0000 1111 22 33 4 00....

But this happens only when none of the machine is ever busy. But if machines get busy the order could be like :

0 0 1 2 0 1 0 1 ....

Note that the number of times a machine is returned cannot exceed maxAlloc and if machine is found busy next machine that will be returned, is the one that could be just next to the machine that is currently busy and that itself is not busy (Also currAlloc should not exceed maxAlloc)

If maxAlloc = 5, currAlloc limit is 4. Because its count starts from 0

I am unable to implement this logic. Help me do this.

saplingPro
  • 20,769
  • 53
  • 137
  • 195

2 Answers2

1

The function that should fit in your code is the following:

public Integer getNextAvailable() {
    Integer machineId = null;
    VMallocation allocation;

    // busyListIsFull is a volatile variable that has to be shared between the 2 classes:
    // the one that contains getNext... and the one that modifies busyList
    //this should be added to the code that modifies busyList
    /*
    if(busyList.containsAll(mapAll.keySet())) {
    busyListIsFull = true;
    notifyAll();
    }
     */

    // all machines are busy
    while(busyListIsFull) {
        try {
            wait();
        } catch (InterruptedException e) {

        }
    }
    busyListIsFull = false;
    notifyAll();

    for(Map.Entry<Integer, VMallocation> entry: mapAll.entrySet()) {
        machineId = (Integer)(entry.getKey());
        allocation = (VMallocation)(entry.getValue());
        // allocate the next machineId if it is not busy and has available allocations
        if(!busyList.contains(machineId) &&
                allocation.getCurrentAlloc() < allocation.getMaxAlloc()) {
            System.out.println("allocating machineId:" + machineId);
            allocation.setCurrentAlloc(allocation.getCurrentAlloc() + 1);
            if(machineId != null) {
                return machineId;
            }
        }
    }
    // no machineId was returned if code execution gets here, so no
    //resource was available; now free them all
    for(Map.Entry<Integer, VMallocation> entry: mapAll.entrySet()) {
        allocation = (VMallocation)(entry.getValue());
        allocation.setCurrentAlloc(0);
    }
    // return first available machine
    return getNextAvailable();
}
aUserHimself
  • 1,589
  • 2
  • 17
  • 26
1

I was interested in your problem, so i came up with this solution, that might be working for you. There are no sanity checks in that code, it's just a proof of concept.

Event:

public class CloudSimEvent {

    private final int id;
    private final boolean allocated;

    public CloudSimEvent(int id, boolean allocated) {
        super();
        this.id = id;
        this.allocated = allocated;
    }

    public int getID() {
        return id;
    }

    public boolean allocated() {
        return allocated;
    }

    public boolean finished() {
        return !allocated;
    }

}

Event interface

public interface CloudSimEventListener {

    public void cloudSimEventFired(CloudSimEvent e);

}

VMAllocation object

public final class VMAllocation implements Comparable<VMAllocation> {

    private final int id;
    private final int maxAlloc;
    private final int currAlloc;

    public VMAllocation(int id, int maxAlloc, int currAlloc) {
        super();
        this.id = id;
        this.maxAlloc = maxAlloc;
        this.currAlloc = currAlloc;
    }

    public VMAllocation allocate() {
        return new VMAllocation(id, maxAlloc, currAlloc + 1);
    }

    public VMAllocation finish() {
        return new VMAllocation(id, maxAlloc, currAlloc - 1);
    }

    public boolean isBusy() {
        return currAlloc >= maxAlloc;
    }

    public int getId() {
        return id;
    }

    @Override
    public int compareTo(VMAllocation o) {
        if (isBusy() && !o.isBusy()) {
            return 1;
        } else if (!isBusy() && o.isBusy()) {
            return -1;
        } else {
            return Integer.compare(id, o.id);
        }
    }

    @Override
    public String toString() {
        return "id: " + id + " currAlloc: " + currAlloc + " maxAlloc: "
                + maxAlloc + " is-busy: " + isBusy();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + currAlloc;
        result = prime * result + id;
        result = prime * result + maxAlloc;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        VMAllocation other = (VMAllocation) obj;
        if (currAlloc != other.currAlloc)
            return false;
        if (id != other.id)
            return false;
        if (maxAlloc != other.maxAlloc)
            return false;
        return true;
    }

}

RRScheduler

import java.util.Arrays;
import java.util.Iterator;
import java.util.PriorityQueue;

public class RRSheduler implements CloudSimEventListener {

    private final PriorityQueue<VMAllocation> queue = new PriorityQueue<>();

    public void addVMAllocation(VMAllocation allocation) {
        synchronized (queue) {
            queue.add(allocation);
        }
    }

    @Override
    public void cloudSimEventFired(CloudSimEvent e) {
        VMChanged(e.getID(), e.allocated());
    }

    private void VMChanged(int id, boolean allocation) {
        synchronized (queue) {
            Iterator<VMAllocation> it = queue.iterator();
            VMAllocation newAllocation = null;
            while (it.hasNext()) {
                VMAllocation vmAllocation = it.next();
                if (vmAllocation.getId() == id) {
                    if (allocation)
                        newAllocation = vmAllocation.allocate();
                    else
                        newAllocation = vmAllocation.finish();
                    it.remove();
                    break;
                }
            }

            if (newAllocation != null)
                queue.add(newAllocation);
        }
    }

    public VMAllocation getNextFreeVMAllocation() {
        synchronized (queue) {
            VMAllocation allocation = queue.element();
            return allocation.isBusy() ? null : allocation;
        }
    }

    @Override
    public String toString() {
        synchronized (queue) {
            VMAllocation[] arr = queue.toArray(new VMAllocation[] {});
            Arrays.sort(arr);
            return Arrays.toString(arr);
        }
    }
}

Simple test program

public class TestRR {

    public static void main(String[] args) {
        RRSheduler rrSheduler = new RRSheduler();
        rrSheduler.addVMAllocation(new VMAllocation(0, 4, 0));
        rrSheduler.addVMAllocation(new VMAllocation(1, 4, 0));
        rrSheduler.addVMAllocation(new VMAllocation(2, 2, 0));
        rrSheduler.addVMAllocation(new VMAllocation(3, 2, 0));
        rrSheduler.addVMAllocation(new VMAllocation(4, 1, 0));

        VMAllocation nextAllocation = null;
        while ((nextAllocation = rrSheduler.getNextFreeVMAllocation()) != null) {
            System.out.println(nextAllocation);
            rrSheduler.cloudSimEventFired(new CloudSimEvent(nextAllocation
                    .getId(), true));
        }

    }
}

I am not using a map like you do, but you might get an idea how to solve your problem.

Ortwin Angermeier
  • 5,957
  • 2
  • 34
  • 34