Commits

Cristian Viorel Pasat  committed d90d737 Draft

added the project for practice stage

  • Participants
  • Parent commits bb0b384

Comments (0)

Files changed (56)

File .settings/org.eclipse.jdt.core.prefs

+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
+		... use this piece of software?
+		
+		
+Pretty simple: the TestClass in package main holds the main method.
+Using it you can do wonderful things! (more or less related to this programs' scope.
+
+
+This program is used to read the data from a json file, 
+populate it's related beans accordingly and provide methods 
+for calculating resource load and relocation cost.
+
+The content of the packages otherClasses and allTasksVariablesComputator
+contain the main classes while the packages Beans and fileIO
+represent the dependencies.
+
+
+PopulateBean is used to read the the json file 
+located in the docs folder verify it's content and populate the class
+GigaBean.
+At the creation of a PopulateBean object, the content of the json is 
+compared to the data found in the files all_tasks_variables.txt and 
+single_task_variables.txt found in the docs folder. 
+
+GigaBean is made of 2 other beans: FromMachineBean and ToMachineBean,
+which contain information regarding the load state of a machine.
+
+
+AllTasksVariablesComputator is used to compute different resource 
+loads or relocation costs and implements iAllTasksVariablesComputator.
+At instantiation, the constructor receives a Vector containing all 
+the nodes created so far.
+The objects returned in a MinMaxResource bean containing the ID of 
+a node and the respective load/cost.
+
+
+MakeJson is used to create a json object from a bean. (this is done pretty straight forward)
+
+
+interpret groovy====>>>>> description in the class
+

File methods to be implemented for single_task_variables - condition.txt

+resource_load (CPU, memory, disk): exists for both Node and Partition, so which one to use?
+
+monetary_cost ( $ ), 
+transport_cost (throughput in s), 
+resource_execution_cost ( s ): DO NOT EXIST =>
+=> need to be implemented. 

File src/mosaic/scheduler/platform/Scaler.java

+package mosaic.scheduler.platform;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.List;
+import java.util.Vector;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.log4j.Logger;
+
+import mosaic.scheduler.platform.com.json.beans.ComponentWorkflowBean;
+import mosaic.scheduler.platform.com.json.beans.ComponentsBean;
+import mosaic.scheduler.platform.com.json.beans.NodeListBean;
+import mosaic.scheduler.platform.com.json.beans.QueueListBean;
+import mosaic.scheduler.simulator.util.Runner;
+
+
+public class Scaler {
+	private static Logger logger = Logger.getLogger(Runner.class.getPackage().getName());
+
+	public int[] scale(Vector<ComponentWorkflowBean> componentData, Vector<QueueListBean> queueData,  Vector<NodeListBean> nodes) {
+		int[] totalNoComponents = new int[componentData.size()];
+		int[] finalNoComponents = new int[componentData.size()];
+		int[][] connection = new int[componentData.size()][componentData.size()];
+		int[][] readRate = new int[componentData.size()][componentData.size()];
+		int[][] writeRate = new int[componentData.size()][componentData.size()];
+		int[][] initialMessage = new int[componentData.size()][componentData.size()];
+		int[][] currentMessage = new int[componentData.size()][componentData.size()];
+		int[][] previousMessage = new int[componentData.size()][componentData.size()];
+		
+		
+		//build the component connection table & the read rate table
+		for (ComponentWorkflowBean cwb : componentData) {
+			String[] links = cwb.getLinked_to_Component();
+			String[] reads = cwb.getRead_rate();
+			String[] writes = cwb.getWrite_rate();
+			for (int i=0; i< links.length; i++) {
+				if (links[i].trim().length() > 0 && reads[i].trim().length() > 0)
+					connection[cwb.getComponent_type()][Integer.parseInt(links[i])] = 1;
+					//cwb is read by its links
+					readRate[cwb.getComponent_type()][Integer.parseInt(links[i])] = Integer.parseInt(reads[i]);
+					//cwb writes to its links
+					writeRate[cwb.getComponent_type()][Integer.parseInt(links[i])] = Integer.parseInt(writes[i]);
+			}
+		}
+				
+		//compute total number of components available in the platform
+		for (NodeListBean ncb : nodes) {
+			for (ComponentsBean cb : ncb.getComponents()) {
+				totalNoComponents[cb.getComponent_type()] += cb.getComponent_number();
+				//finalNoComponents[cb.getComponent_type()] = totalNoComponents[cb.getComponent_type()];
+			}			
+		}
+		
+		Scaler.logger.debug("Total number of components per type");		
+		for (int i=0; i<totalNoComponents.length; i++)
+			Scaler.logger.debug(i + "\t" + totalNoComponents[i]);		
+		
+		Scaler.logger.debug("Connection table");		
+		for (int i=0; i<componentData.size(); i++) {
+			String s = "";
+			for (int j=0; j<componentData.size(); j++)
+				s += connection[i][j] + "\t";
+			Scaler.logger.debug(s);
+		}
+		
+		Scaler.logger.debug("Read/write table");		
+		for (int i=0; i<componentData.size(); i++) {
+			String s = "";
+			for (int j=0; j<componentData.size(); j++)
+				s += readRate[i][j] + "/" + writeRate[i][j] + "\t";
+			Scaler.logger.debug(s);
+		}
+		
+		//compute the initialMessage table, i.e., [i][j] contains the number of messages initially existing in the queue from i to j
+		for (QueueListBean qlb : queueData) {
+			String[] endpoints = qlb.getQueue_id().split("-");
+			initialMessage[Integer.parseInt(endpoints[0])][Integer.parseInt(endpoints[1])] = Integer.parseInt(qlb.getNo_messages()[0]);
+		}
+
+		//this method was just a test to see whether we would be able to use a free web based NLP to compute the optimal number of components 
+		//this.computeNonLinearMinimizationEquation(connection, initialMessage, readRate);
+		
+		int readCapacity = 0;
+		boolean identical = true;
+		do {
+			
+			for (int i=0; i< componentData.size(); i++)
+				for (int j=0; j< componentData.size(); j++)
+					previousMessage[i][j] = currentMessage[i][j];
+			
+			//for every component type i
+			for (int i=0; i<componentData.size(); i++) {
+				int tmpComponentNo = 0;
+				//get the components j linking to it
+				for (int j=0; j<componentData.size(); j++) {					
+					//check link from j to i
+					if (i!=j && connection[j][i] == 1) {
+						currentMessage[j][i] = initialMessage[j][i] + finalNoComponents[j] * writeRate[j][i];						
+						//compute the current read capacity of the component type i 
+						readCapacity = finalNoComponents[i] * readRate[i][j];
+						Scaler.logger.debug(j+ "->" + i + "\t" + initialMessage[j][i] + " " + finalNoComponents[j] + "*" + writeRate[j][i] + "\t" + readCapacity + " " + currentMessage[j][i]);
+						//if this capacity is lower than the existing message queue size update the number of component accordingly
+						if (readCapacity < currentMessage[j][i]) {
+							//maximum between the number of components of type i we have so far and the needed at this link
+							tmpComponentNo = Math.max(tmpComponentNo, Math.round((currentMessage[j][i] - readCapacity) / (float)readRate[i][j])); 
+						}
+					}
+				}
+				//the final number of components is the maximum between what we computed at this step and the existing ones
+				finalNoComponents[i] = Math.max(tmpComponentNo, finalNoComponents[i]);
+				Scaler.logger.debug(i + " " + finalNoComponents[i]);
+			}
+			
+			//compute the stopping criterion, i.e., stop when the message matrix has not changed
+			identical = true;
+			for (int i=0; i<componentData.size(); i++) {
+				for (int j=0; j<componentData.size(); j++) {
+					if (i!=j && connection[j][i] == 1) {
+						readCapacity = finalNoComponents[i] * readRate[i][j];						
+						if (readCapacity < currentMessage[j][i]) {
+							identical = false;
+						}
+					}
+				}
+			}
+			
+			Scaler.logger.debug("Read capacity vs current message table:");
+			for (int i=0; i< componentData.size(); i++) {
+				String s = "";
+				for (int j=0; j< componentData.size(); j++) {
+					s += (finalNoComponents[j] * readRate[j][i]) + "/" + currentMessage[i][j] + "\t";
+				}
+				Scaler.logger.debug(s);
+			}
+
+		} while (identical == false);
+		
+		Scaler.logger.debug("Required number of components:");
+		for (int i=0; i<finalNoComponents.length; i++) {
+			finalNoComponents[i] = finalNoComponents[i] - totalNoComponents[i];
+			Scaler.logger.debug(i + "\t" + finalNoComponents[i]);
+		}
+		
+		return finalNoComponents;
+	}
+	
+	public void storeNumberOfComponents(Vector<NodeListBean> components) {
+		//TODO
+	}
+	
+	/**
+	 * @deprecated
+	 * @param connection
+	 * @param initialMessage
+	 * @param readRate
+	 * @return
+	 */
+	@SuppressWarnings("unused")
+	private int[] computeNonLinearMinimizationEquation(int[][] connection, int[][] initialMessage, int[][] readRate) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("Model 3d");
+		sb.append("\n");
+		sb.append("Variables");
+		sb.append("\n");
+		
+		String s = "";
+		for (int i=0; i<readRate.length; i++) {
+			sb.append("x"+(i+1));
+			sb.append("\n");
+			if (i<readRate.length-1)
+				s += "x" + (i+1) + "+";
+			else
+				s += "x" + (i+1);
+		}
+		
+		sb.append("End Variables");
+		sb.append("\n");
+		
+		sb.append("Equations");
+		sb.append("\n");
+		sb.append(s + " = 100");
+		sb.append("\n");		
+		for (int i=0; i<readRate.length; i++) {
+			sb.append("x"+(i+1) + " > 1");
+			sb.append("\n");
+		}
+		
+		s = "minimize ";
+		for (int i=0; i<connection[0].length; i++) {
+			for (int j=0; j<connection[0].length; j++) {
+				if (i!=j && connection[j][i] == 1) {
+					s += Math.pow(initialMessage[j][i],2) + "-2*" + readRate[i][j] + "*x" + (i+1) + "+" + readRate[i][j] + "^2*x" + (i+1) + "^2" + "+";   
+				}
+			}
+		}
+		
+		s = s.substring(0, s.length() - 1);
+		
+		sb.append(s);
+		sb.append("\n");
+		sb.append("End Equations");
+		sb.append("\n");
+		sb.append("End Model");
+		
+	//	Scaler.logger.debug("Sending NLP: " + sb.toString());
+		
+		HTTP_NLP http = new HTTP_NLP();
+		
+		String id = http.getAPMonitorPOSTID("http://www.apmonitor.com/online/view_pass.php");
+		Scaler.logger.debug("Found NLP APMonitor ID: " + id);
+			
+		try {
+			String result = http.submitNLP(sb.toString(), "http://www.apmonitor.com/online/save.php", id);
+			//Scaler.logger.debug("Response HTTP for NLP request : " + result);			
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		
+		String result = http.getNLPResult("http://www.apmonitor.com/online/"+ id + "/" + id + "_var.htm");
+
+		Scaler.logger.debug("Response HTTP for NLP ("+ "http://www.apmonitor.com/online/"+ id + "/" + id + "_var.htm) : " + result);
+		
+		return null;
+	}
+		
+	/**
+	 * @deprecated
+	 * @author ieat
+	 *
+	 */
+	class HTTP_NLP {
+		
+		public String getNLPResult(String urlString) {
+			return this.call(null, urlString);
+		}
+		
+		public String submitNLP(String nlp, String urlString, String id) throws UnsupportedEncodingException {
+			
+			String data = URLEncoder.encode("content", "UTF-8") + "=" + URLEncoder.encode(nlp, "UTF-8");
+     	    data += "&" + URLEncoder.encode("d", "UTF-8") + "=" + URLEncoder.encode(id, "UTF-8");
+     	    data += "&" + URLEncoder.encode("f", "UTF-8") + "=" + URLEncoder.encode(id + ".apm", "UTF-8");
+     	    data += "&" + URLEncoder.encode("code", "UTF-8") + "=" + URLEncoder.encode("17201206", "UTF-8");
+		
+     	    return this.call(data, urlString);
+     	     
+		}
+		
+		public String getAPMonitorPOSTID(String urlString) {
+			String id = null;
+			
+			String response = this.call(null, urlString);
+			
+			System.out.println(response);
+			
+			Pattern p = Pattern.compile("<title>(.*?)</title>");
+	        Matcher m = p.matcher(response);
+	        if (m.find()) {
+	        	id = m.group(1);
+	        	id = id.substring(id.indexOf('-') + 1, id.lastIndexOf('.')).trim();
+	        }
+			
+			return id;
+		}
+		
+		private String call(String data, String urlString) {
+			StringBuilder sb = new StringBuilder();
+			try{
+				URL url = new URL(urlString);
+	    	    
+	    	    URLConnection conn = url.openConnection();
+	    	    conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.2.2) Gecko/20100316 Firefox/3.6.2");
+	    	    conn.setRequestProperty("Accept-Charset", "UTF-8");
+	    	    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
+	    	    conn.setDoOutput(true);
+	    	   
+	    	    for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
+	    	        System.out.println(header.getKey() + "=" + header.getValue());
+	    	    }
+
+	    	    
+	    	    OutputStreamWriter wr = null;
+	    	    if (data != null) {	    	    	
+		    	    wr = new OutputStreamWriter(conn.getOutputStream());
+		    	    wr.write(data);
+		    	    wr.flush();
+	    	    }
+	    	    // Get the response
+	    	    BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+	    	    String line;
+	    	    while ((line = rd.readLine()) != null) {
+	    	    	sb.append(line);
+	    	    	sb.append("\n");
+	    	    }
+	    	    if (data != null)
+	    	    	wr.close();
+	    	    rd.close();
+	    	} catch (Exception e) {}
+			return sb.toString();
+		}
+	}
+}

File src/mosaic/scheduler/platform/Scheduler.java

+package mosaic.scheduler.platform;
+
+import java.util.Vector;
+
+import org.apache.log4j.Logger;
+
+import mosaic.scheduler.platform.algorithms.IAlgorithm;
+import mosaic.scheduler.platform.algorithms.util.AlgorithmUtil;
+import mosaic.scheduler.platform.com.json.beans.ComponentLoadListBean;
+import mosaic.scheduler.platform.com.json.beans.ComponentWorkflowBean;
+import mosaic.scheduler.platform.com.json.beans.NodesBean;
+import mosaic.scheduler.platform.resources.Component;
+import mosaic.scheduler.platform.resources.ComponentRequirementsList;
+import mosaic.scheduler.platform.resources.Node;
+import mosaic.scheduler.platform.resources.Partition;
+import mosaic.scheduler.platform.settings.SystemSettings;
+import mosaic.scheduler.simulator.util.Runner;
+
+
+
+public class Scheduler {
+	private static Logger logger = Logger.getLogger(Runner.class.getPackage().getName());
+
+	Vector<ComponentWorkflowBean> componentWorkflow = null;
+	Vector<NodesBean> crtNodes;
+	Vector<ComponentLoadListBean> crtComponents;
+	Runner.AlgorithmContainer container = null;
+	
+	public Scheduler(IAlgorithm algorithm) {
+		this.container = new Runner(). new AlgorithmContainer(algorithm, new Vector<Node>());
+		
+		//dummy data - remove in production
+		this.putDummyData();
+		
+		//TODO get component workflow
+	}
+ 	
+	public void run() {
+		Component component = null;
+		Partition partition = null;
+		Node node = null;
+		
+		//do {
+		
+		//TODO scale components based on traffic at each of the component
+		
+		this.container.nodes.clear();
+		//TODO query node list
+		
+		for (NodesBean nb : this.crtNodes) {
+			//TODO query node for components
+			
+			//compute the average load of every component type based on input data
+			int[] averageComponentLoad = new int[SystemSettings.getSystemSettings().getNo_component_types()];
+			int[] noComponentsPerType =  new int[SystemSettings.getSystemSettings().getNo_component_types()];
+			for (ComponentLoadListBean c : this.crtComponents) {
+				averageComponentLoad[c.getComponent_type()] += Integer.parseInt(c.getComponent_load().split(",")[0]);
+				noComponentsPerType[c.getComponent_type()]++;
+			}
+			
+			ComponentRequirementsList crl  = ComponentRequirementsList.getComponentsRequirement();
+			for (int i=0; i<averageComponentLoad.length; i++) {
+				averageComponentLoad[i] = (noComponentsPerType[i] != 0) ? averageComponentLoad[i]/noComponentsPerType[i] : 0;
+				crl.getComponentRequirements(i).setCpuUsage(0, averageComponentLoad[i]);
+			}
+			
+			//add node and components attached to it
+			node = new Node(nb.getNode_id(), nb.getNode_datacenter_id(), nb.getNode_cloud_id());	
+			for (ComponentLoadListBean ncb : crtComponents) {
+				component = new Component(false, ncb.getComponent_type());
+				partition = Partition.provide(node.getID());
+				partition.addComponent(component);
+				node.addPartition(partition);					
+			}
+			
+			this.container.nodes.add(node);
+		}
+
+		//add connections to components based on the input data
+		for (Component c : AlgorithmUtil.gatherComponents(this.container.nodes)) {		
+			for (ComponentWorkflowBean cwb : this.componentWorkflow) {
+				if (cwb.getComponent_type() == c.getType()) {
+					for (String id : cwb.getLinked_to_Component()) {
+						if (id.trim().length() > 0)
+							c.addConnection(AlgorithmUtil.getRandomComponent(Integer.parseInt(id), this.container.nodes));									
+					}					
+				}
+			}
+		}
+
+		//run the algorithm
+		this.container.nodes = this.container.algorithm.executeOnce(this.container.nodes, new int[]{1,7,19},0);/*use this if scaling is enabled*/
+		//this.container.nodes = this.container.algorithm.executeOnce(this.container.nodes,0);/*use this if scaling is disabled*/
+		
+		//compute the number of nodes to be added or removed
+		int countAdd = 0, countRemove = 0;
+		for (Node n : this.container.nodes) {
+			if (n.status == Node.NODE_STATUS.NEW)
+				countAdd++;
+			if (n.status == Node.NODE_STATUS.TO_BE_REMOVED)
+				countRemove++;
+		}
+			
+		Scheduler.logger.debug("Nodes to be added : " + countAdd);
+		Scheduler.logger.debug("Nodes to be removed : " + countRemove);
+		
+		//TODO send message for scaling up/down	and for adding/removing nodes	
+		
+//		try {
+//			Thread.sleep(60000);
+//		} catch (InterruptedException e) { }
+		//} while (true);
+	}
+
+	//TODO unsure whether the following methods are really needed
+	
+	public synchronized void storeNodes(Vector<NodesBean> nodes) {
+		this.crtNodes = nodes;
+	}
+	
+	public synchronized void storeComponentsPerNode(Vector<ComponentLoadListBean> components) {
+		this.crtComponents = components;
+	}
+
+	public synchronized void storeComponentWorkflow(Vector<ComponentWorkflowBean> workflow) {
+		this.componentWorkflow = workflow;
+	}
+	
+	private void putDummyData() {
+		//component workflow
+		this.componentWorkflow = new Vector<ComponentWorkflowBean>();
+		this.componentWorkflow.add(new ComponentWorkflowBean(0, "1", "10", "20"));
+		this.componentWorkflow.add(new ComponentWorkflowBean(1, "2", "10", "20"));
+		this.componentWorkflow.add(new ComponentWorkflowBean(2, "", "10", "20"));
+				
+		//node list
+		this.crtNodes = new Vector<NodesBean>();
+		//add 1st node
+		this.crtNodes.add(new NodesBean("1", "1", "1", "45"));
+		
+		//component list
+		this.crtComponents = new Vector<ComponentLoadListBean>();
+		//create queue list for 1st component
+		//Vector<QueueListBean> queue = new Vector<QueueListBean>();
+		//queue.add(new QueueListBean("1", "100"));
+		//add 1st component
+		this.crtComponents.add(new ComponentLoadListBean(0, "10,12,9"));
+		
+		//create queue list for 2nd component
+		//queue = new Vector<QueueListBean>();
+		//queue.add(new QueueListBean("2", "50"));
+		//add 2nd component
+		this.crtComponents.add(new ComponentLoadListBean(0, "15,13,10"));
+		
+		//create queue list for 3rd component
+		//queue = new Vector<QueueListBean>();
+		//queue.add(new QueueListBean("3", "50"));
+		//add 3rd component
+		this.crtComponents.add(new ComponentLoadListBean(1, "20,13,24"));
+		
+//		//create queue list for 4th component
+//		queue = new Vector<NoMessagesInQueueBean>();
+//		queue.add(new NoMessagesInQueueBean("3", "50"));
+//		//add 3rd component
+//		this.crtComponents.add(new ComponentLoadListBean(2, "20,13,24", queue));
+
+	}
+}

File src/mosaic/scheduler/platform/algorithms/IAlgorithm.java

+package mosaic.scheduler.platform.algorithms;
+
+import java.util.Vector;
+
+import mosaic.scheduler.platform.resources.Node;
+
+
+/**
+ * Interface for the scheduling algorithm. It offers methods for executing the heuristics only once.
+ * The algorithm should be executed only when the number of components or the characteristics of
+ * the system/application's have changed (Reactive and not proactive method). It is not meant for 
+ * periodic executing for reasons of efficiency.  
+ * @author Marc Frincu
+ * @since 2012
+ */
+public interface IAlgorithm {
+	
+	/**
+	 * Method that reschedules the components on the given node vector and returns a COPY of the new node list.
+	 * The algorithm reschedules components if certain thresholds are broken (e.g., node load) 
+	 * @param nodes the list of nodes needing rescheduling
+	 * @param componentsToBeGenerated the number of components to be generated on the existing nodes
+	 * @param time the moment in time this schedule corresponds to
+	 * @return the list with the (new) nodes and their assigned components after rescheduling
+	 */
+	public Vector<Node> executeOnce(Vector<Node> nodes, int[] componentsToBeGenerated, int time);
+		
+	/**
+	 * Method that reschedules the components on the given node vector and returns a COPY of the new node list.
+	 * In this method the new components are not placed by the algorithm but are already present. The algorithm
+	 * only reschedules if certain thresholds (e.g., node load) are broken by the placement
+	 * @param nodes the list of nodes needing rescheduling
+	 * @param time the moment in time this schedule corresponds to
+	 * @return the list with the (new) nodes and their assigned components after rescheduling
+	 */
+	public Vector<Node> executeOnce(Vector<Node> nodes,  int time);
+}

File src/mosaic/scheduler/platform/algorithms/OurOnetoOne.java

+package mosaic.scheduler.platform.algorithms;
+
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import mosaic.scheduler.platform.algorithms.util.AlgorithmUtil;
+import mosaic.scheduler.platform.resources.Component;
+import mosaic.scheduler.platform.resources.Node;
+import mosaic.scheduler.platform.resources.Partition;
+import mosaic.scheduler.platform.settings.SystemSettings;
+import mosaic.scheduler.simulator.algorithms.OurManyToOne;
+import mosaic.scheduler.simulator.util.Runner;
+import mosaic.scheduler.test.Test;
+
+import org.apache.log4j.Logger;
+
+
+
+public class OurOnetoOne implements IAlgorithm {
+	private static Logger logger = Logger.getLogger(Runner.class.getPackage().getName());
+
+	@Override
+	public Vector<Node> executeOnce(Vector<Node> nodes,	int[] componentsToBeGenerated, int time) {
+		Node n;
+		Partition p;
+		String s = "";
+		for (int i=0; i<componentsToBeGenerated.length; i++) {
+			s = s + componentsToBeGenerated[i] + " ";
+		}
+		OurOnetoOne.logger.debug("componentsToBeGenerated : " + s);
+		//add components & possibly nodes
+		for (int i=0; i<componentsToBeGenerated.length; i++) {
+			for (int j=0; j< componentsToBeGenerated[i]; j++) {
+				n = nodes.get((int)(Math.random() * (nodes.size() - 1)));
+				p = Partition.provide(n.getID());
+				p.addComponent(new Component(false, i));
+				n.addPartition(p);
+			}
+		}
+		
+		nodes = this.scale(nodes, time);
+		
+		//try to remove nodes
+		Collections.sort(nodes, new NodeComparator());
+		int k = 0;
+		Vector<Partition> partitions = null;
+		boolean found, found2;
+		do {
+			found = false;
+			found2 = false;
+			for (int i=0; i<componentsToBeGenerated.length; i++) {
+				if (componentsToBeGenerated[i] < 0 && Math.abs(componentsToBeGenerated[i]) < AlgorithmUtil.getNumberComponents(nodes.get(k), i)) {
+					found = true; 
+				}
+				if (componentsToBeGenerated[i] > 0)
+					found2 = true;
+
+			}
+			if (!found && !found2) {
+				nodes.get(k).status = Node.NODE_STATUS.TO_BE_REMOVED;
+				for (int i=0; i<componentsToBeGenerated.length; i++) {
+					componentsToBeGenerated[i] = componentsToBeGenerated[i] +  AlgorithmUtil.getNumberComponents(nodes.get(k), i);
+				}
+			}
+			else {
+				for (int i=0; i<componentsToBeGenerated.length; i++) {
+					partitions = nodes.get(k).getAssignedPartitions();
+					int j=0;
+					do {
+						Component c = partitions.get(j).getAssignedComponents().size() == 1 ? partitions.get(j).getAssignedComponents().get(0) : null;
+						if (c != null && c.getType() == i && AlgorithmUtil.getNumberComponents(nodes.get(k), i) > 1 && Math.abs(componentsToBeGenerated[i]) > 0) {
+							partitions.remove(j);
+							componentsToBeGenerated[i]++;
+						}
+						else
+							j++;
+					} while (j < partitions.size());
+				}
+			}
+			
+			found = false;
+			for (int i=0; i<componentsToBeGenerated.length; i++) {
+				if (componentsToBeGenerated[i] < 0)
+					found = true;
+			}
+			k++;
+		} while (k<nodes.size() && found);
+		
+		return nodes;
+	}
+
+	@Override
+	public Vector<Node> executeOnce(Vector<Node> nodes, int time) {
+		//scale if necessary
+		return this.scale(nodes, time);
+	}
+
+	private Vector<Node> scale(Vector<Node> nodes, int time) {		
+		// apply GA for each element in population. move random number of partitions from overloaded node to other nodes.
+		// after movement pick one in which all nodes are under-loaded & has all component types & cost is minimized
+		// if such case is inexistent create node and move random one partition from every component type
+		// keep the one which minimizes cost
+		Hashtable<Integer,Vector<Node>> mutatedNodes = new Hashtable<Integer, Vector<Node>>();
+		for (int i=0; i<OurManyToOne.POPULATION_SIZE; i++) {
+			try {
+				mutatedNodes.put(i, this.mutate(Test.cloneNodes(nodes), time));
+			} catch (Exception e) {
+				e.printStackTrace();
+			}
+		}
+		
+		// get the solution with the least cost and that has all nodes under-loaded
+		int minIndex = 0;
+		float minCost = Float.MAX_VALUE;
+		boolean ok = true;
+		int k=0;
+		for (int i=0; i<OurManyToOne.POPULATION_SIZE; i++) {
+			if (AlgorithmUtil.computePlatformCost(mutatedNodes.get(i)) < minCost) {
+				ok = true;
+				k = 0;
+				for (Node n : mutatedNodes.get(i)) {
+					if (n.computeLoad(time, k++) > SystemSettings.getSystemSettings().getMax_node_load_threshold()) {
+						ok = false;
+					}
+				}
+				if (ok == true) {
+					minCost = AlgorithmUtil.computePlatformCost(mutatedNodes.get(i));
+					minIndex = i;
+				}
+			}
+		}
+
+		return mutatedNodes.get(minIndex);
+	}
+
+
+	private Vector<Node> mutate(Vector<Node> nodes, int time) {
+		Partition partition = null;
+		int repeats = 0, repeats2 = 0;
+		int maxRepeats = 0;
+		Node n2 = null, newNode = null;
+		Node n;
+		int m;
+		
+		for (int k=0; k<nodes.size(); k++) {
+			if (nodes.get(k).status == Node.NODE_STATUS.NEW)
+				nodes.get(k).status = Node.NODE_STATUS.EXISTING;
+		}
+		//synchronized(nodes) {
+			for (int k=0; k<nodes.size(); k++) {
+				n = nodes.get(k);				 
+				OurOnetoOne.logger.debug("Load on node " + n.getID() + " : " + n.computeLoad(time, k));
+				repeats = 0;
+				maxRepeats = 30;
+				while (n.computeLoad(time, k) > SystemSettings.getSystemSettings().getMax_node_load_threshold() && maxRepeats > repeats++) {
+					OurOnetoOne.logger.debug("Node " + n.getID() + " overloaded. Trying to reasign partitions");
+					repeats2 = 0;
+					//pick random node which is under-loaded
+					do {		
+						m = 0 + (int)(Math.random() * ((nodes.size() - 1 - 0) + 1));
+						//OurOnetoOne.logger.debug("Attempting to move from node " + n.getID() + " to node " + nodes.get(m).getID());
+						if (repeats2 < maxRepeats) {
+							n2 = nodes.get(m);
+							//pick random partition
+							partition = n.getAssignedPartitions().get(0 + (int)(Math.random() * ((n.getAssignedPartitions().size() - 1 - 0) + 1)));
+							String[] pTypes = AlgorithmUtil.computeNumberServiceTypes(n).split("#");
+							if (Integer.parseInt(pTypes[partition.getAssignedComponents().get(0).getType()]) - 1 >= 1) {
+								if (n2.getID().compareToIgnoreCase(n.getID()) != 0)
+									if (n2.computeLoad(time, m) + partition.computeLoad(time) < SystemSettings.getSystemSettings().getMax_node_load_threshold()) {
+										n.getAssignedPartitions().remove(partition);
+										//reassign it
+										n2.addPartition(partition);
+										partition.assignToNode(n2.getID());
+									}
+							}
+						}
+					} while (maxRepeats > repeats2++);									
+					
+					// we were not able to decrease load so create new node
+					if (repeats2 >= maxRepeats) {	
+						if (nodes.size() < SystemSettings.getSystemSettings().getMax_number_nodes() + AlgorithmUtil.computeNoFailedNodes(nodes)) {
+							newNode = AlgorithmUtil.addNewRandomNode();
+							nodes.add(newNode);
+							Vector<Integer> types = new Vector<Integer>();
+							OurOnetoOne.logger.debug("Could not releave load. Load :" + n.computeLoad(time, k) + " Creating new node " + newNode.getID());
+							//decrease load of node by moving random partitions
+							int reps = 0;
+							while (n.computeLoad(time, k) > SystemSettings.getSystemSettings().getMax_node_load_threshold() && reps++ < 1000) {
+								//pick random a partition from overloaded node
+								partition = n.getAssignedPartitions().get(0 + (int)(Math.random() * ((n.getAssignedPartitions().size() - 1 - 0) + 1)));
+								String[] pTypes = AlgorithmUtil.computeNumberServiceTypes(n).split("#");
+								if (Integer.parseInt(pTypes[partition.getAssignedComponents().get(0).getType()]) - 1 >= 1) {						
+									if (newNode.computeLoad(time, nodes.size()-1) + partition.computeLoad(time) < SystemSettings.getSystemSettings().getMax_node_load_threshold()
+											&& !types.contains(partition.getAssignedComponents().get(0).getType())) {
+										//reassign it
+										n.getAssignedPartitions().remove(partition);
+										newNode.addPartition(partition);
+										partition.assignToNode(newNode.getID());
+										types.add(partition.getAssignedComponents().get(0).getType());
+										//OurOnetoOne.logger.debug("Moved partition of type " + partition.getAssignedComponents().get(0).getType() + " from node " + n.getID() + " to new node " + newNode.getID() + ". Loads : " + n.computeLoad(time, k) + "/" + newNode.computeLoad(time, k));
+									}
+								}
+							}
+							//reassign a partition of each type to new node						
+							int count = 0;
+							//for all component types
+							OurOnetoOne.logger.debug("Trying to achieve HA on new node");
+							for (int kk=0;kk<SystemSettings.getSystemSettings().getNo_component_types();kk++) {
+								//check if this type is not already present
+								if (!types.contains(kk)) {
+									reps = 0;
+									do {											
+										n2 = nodes.get(0 + (int)(Math.random() * ((nodes.size() - 1))));
+										//OurOnetoOne.logger.debug("Selected node " + n2.getID() + " for moving partition from it to new node " + newNode.getID());
+										count = 0;
+										if (n2.getID() != newNode.getID()) {															
+											for (Partition pp : n2.getAssignedPartitions()) {
+												if (pp.getAssignedComponents().get(0).getType() == kk)
+													count++;
+											}
+											if (count > 1)
+												for (Partition pp : n2.getAssignedPartitions())
+													if (pp.getAssignedComponents().get(0).getType() == kk)
+														partition = pp;											
+											//OurOnetoOne.logger.debug("Count on partition of type " + kk + " : " + count);
+											//if succeeded in moving partition
+											if (count > 1 && newNode.computeLoad(time, nodes.size()-1) + partition.computeLoad(time) < SystemSettings.getSystemSettings().getMax_node_load_threshold()) {
+												partition = n2.removePartition(partition);
+												newNode.addPartition(partition);
+												partition.assignToNode(newNode.getID());
+												types.add(partition.getAssignedComponents().get(0).getType());
+												//OurOnetoOne.logger.debug("Moved partition of type " + partition.getAssignedComponents().get(0).getType() + " from node " + n2.getID() + " to new node " + newNode.getID() + ". Loads : " + n.computeLoad(time, k) + "/" + newNode.computeLoad(time, k));										
+											}
+										}
+									} while (count <= 1 && reps++ < 1000);
+								}
+							}
+						}
+					}
+				}
+				OurOnetoOne.logger.debug("Load after attempt :" + n.computeLoad(time, k));
+			}
+			//}		
+		OurOnetoOne.logger.debug("Component types after scheduling :");
+		for (int ii=0; ii<nodes.size(); ii++) {
+			Node nn = nodes.get(ii);
+			OurOnetoOne.logger.debug(nn.getID() + " : " + AlgorithmUtil.computeNumberServiceTypes(nn) + " " + nn.computeLoad(0, ii));
+		}
+		
+		return nodes;
+	}	
+	
+	class NodeComparator implements java.util.Comparator<Node> {
+	    public int compare(Node node1, Node node2) {
+	        return AlgorithmUtil.gatherComponents(node2).size() - AlgorithmUtil.gatherComponents(node1).size();
+	    }
+	}
+}

File src/mosaic/scheduler/platform/algorithms/util/AlgorithmUtil.java

+package mosaic.scheduler.platform.algorithms.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
+import mosaic.scheduler.platform.resources.Component;
+import mosaic.scheduler.platform.resources.Node;
+import mosaic.scheduler.platform.resources.Partition;
+import mosaic.scheduler.platform.settings.SystemSettings;
+import mosaic.scheduler.test.TestRunner;
+
+import org.apache.log4j.Logger;
+
+
+public class AlgorithmUtil {
+
+	public static Logger logger = Logger.getLogger(TestRunner.class.getPackage().getName());
+
+	/**
+	 * Use the Pooled class instead for speed
+	 * @param list
+	 * @return
+	 * @throws Exception
+	 */
+	@SuppressWarnings("unchecked")
+	@Deprecated
+	public static Vector<Node> deepCopyNodes(
+			Vector<Node> list) throws Exception {
+
+		// serialize Vector into byte array
+		ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
+		ObjectOutputStream oos = new ObjectOutputStream(baos);
+		oos.writeObject(list);
+		byte buf[] = baos.toByteArray();
+		oos.close();
+
+		// deserialize byte array into Vector
+		ByteArrayInputStream bais = new ByteArrayInputStream(buf);
+		ObjectInputStream ois = new ObjectInputStream(bais);
+		Vector<Node> newlist = (Vector<Node>) ois.readObject();
+		ois.close();
+
+		return newlist;
+	}
+	
+	/**
+	 * Computes the cost for a given component
+	 * @param nodes
+	 * @param component
+	 * @param assignedNode the node the component is assigned to
+	 * @return
+	 */
+	public static float computeCostForComponent (Vector<Node> nodes, Component component, Node assignedNode) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return Float.NEGATIVE_INFINITY;
+		}
+		if (component == null) {
+			AlgorithmUtil.logger.debug("component null");
+			return Float.NEGATIVE_INFINITY;
+		}
+		
+		Vector<Component> components = null;
+		Vector<String> dependencies = component.getConnections();
+		if (assignedNode == null)
+			assignedNode = AlgorithmUtil.findNode(nodes, component);
+		
+		float c1 = 1 /*same DC*/, c2 = 2 /*same C*/, c3 = 4 /*different C*/;
+		float cost = 0;
+		
+		for (String d : dependencies) {
+			if (d == null)
+				continue;
+			
+			for (Node node : nodes) {
+				components = AlgorithmUtil.gatherComponents(node);
+				if (components == null)
+					continue;
+				
+				for (Component c : components) {
+					if (d.compareToIgnoreCase(c.getID()) == 0) {
+						if (assignedNode.getCloudID().compareToIgnoreCase(node.getCloudID()) != 0) {
+							cost += c3;
+						}
+						else {
+							if (assignedNode.getDataCenterID().compareToIgnoreCase(node.getDataCenterID()) == 0) {
+								cost += c1;
+							}
+							else {
+								cost += c2;
+							}
+						}
+					}
+				}
+			}
+		}
+		return cost;
+	}
+
+	/**
+	 * Retrieves the vector of existing partitions.
+	 * The returned list is a reference and not a DEEP COPY 
+	 * @param nodes
+	 * @return
+	 */
+	public static Vector<Partition> gatherPartitions(Vector<Node> nodes) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		Vector<Partition> partitions = new Vector<Partition>();		
+		for (Node node : nodes) {
+			partitions.addAll(node.getAssignedPartitions());
+		}
+		
+		return partitions;
+	}
+
+	/**
+	 * Retrieves the list of components assigned to the given node
+	 * The returned list is a reference and not a DEEP COPY
+	 * @param node
+	 * @return
+	 */
+	public static Vector<Component> gatherComponents(Node node) {
+		if (node == null) {
+			AlgorithmUtil.logger.debug("node null");
+			return null;
+		}
+		Vector<Component> components = new Vector<Component>();
+		Vector<Partition> partitions = node.getAssignedPartitions();
+		for (Partition partition : partitions) {
+			components.addAll(partition.getAssignedComponents());
+		}
+		return components;
+	}
+
+	/**
+	 * Returns the number of components of a specified type found on a given node
+	 * @param node
+	 * @param type
+	 * @return
+	 */
+	public static int getNumberComponents(Node node, int type) {
+		if (node == null) {
+			AlgorithmUtil.logger.debug("node null");
+			return (int)Float.NEGATIVE_INFINITY;
+		}
+		if (type >= SystemSettings.getSystemSettings().getNo_component_types()) {
+			AlgorithmUtil.logger.debug("type greater than largest allowed type value");
+			return (int)Float.NEGATIVE_INFINITY;		
+		}
+		Vector<Component> c = gatherComponents(node);
+		int count =0;
+		for (Component com : c) {
+			if (com.getType() == type) {
+				count++;
+			}
+		}
+		return count;
+	}
+
+	/**
+	 * Retrieves the list of existing components. 
+	 * The list contains references and not DEEP COPIES 
+	 * @param nodes
+	 * @return
+	 */
+	public static Vector<Component> gatherComponents(Vector<Node> nodes) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		Vector<Partition> partitions = gatherPartitions(nodes);
+		Vector<Component> components = new Vector<Component>();
+		
+		for (Partition partition : partitions) {
+			components.addAll(partition.getAssignedComponents());
+		}
+		
+		return components;
+	}
+
+	/**
+	 * Retrieves the list of existing components that have a specified type.
+	 * The list contains references and not DEEP COPIES
+	 * @param nodes
+	 * @param type
+	 * @return
+	 */
+	public static Vector<Component> gatherComponents(Vector<Node> nodes, int type) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		if (type >= SystemSettings.getSystemSettings().getNo_component_types()) {
+			AlgorithmUtil.logger.debug("type greater than largest allowed type value");
+			return null;
+		}
+		Vector<Component> c = gatherComponents(nodes);
+		Vector<Component> list = new Vector<Component>();
+		for (Component com : c) {
+			if (com.getType() == type) {
+				list.add(com);
+			}
+		}
+		return list;
+	}
+	
+	public static String computeNumberServiceTypes(Node node) {
+		String format = "";
+		for (int i=0;i<SystemSettings.getSystemSettings().getNo_component_types(); i++)
+			format += AlgorithmUtil.getNumberComponents(node, i) + "#";
+		
+		return format;
+	}
+
+	/**
+	 * Computes the cost of the platform
+	 * @param nodes
+	 * @return
+	 */
+	public static float computePlatformCost(Vector<Node> nodes) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return Float.NEGATIVE_INFINITY;
+		}
+		Vector<Component> components = gatherComponents(nodes);
+		//TODO: when computing costs ignore already considered nodes. Eg. if A linked to B and A has been considered, ignore it when processing B's cost 
+		//	Hashtable<String, Integer> alreadySeen = new Hashtable<String, Integer>();	 
+		float cost = 0;
+		
+		for (Component component : components) {
+			cost += AlgorithmUtil.computeCostForComponent(nodes, component, null);
+		}
+		return cost;
+	}
+
+	/**
+	 * Creates a random node attached to an arbitrary cloud and data center
+	 * @return the newly created node
+	 */
+	public static Node addNewRandomNode() {
+		int dci = 0 + (int)(Math.random() * SystemSettings.getSystemSettings().getNumber_clouds());
+		int ci = 0 + (int)(Math.random() * SystemSettings.getSystemSettings().getNumber_datacenters_per_cloud());
+		
+		return new Node("DC" + dci, "C" + ci);
+	}
+	
+	/**
+	 * Retrieves the partition with the biggest load
+	 * @param partitions
+	 * @return
+	 */
+	public static Partition getLargestPartition(Vector<Partition> partitions, Node node, int time){
+		if (node == null) {
+			AlgorithmUtil.logger.debug("node null");
+			return null;
+		}
+		if (partitions == null) {
+			AlgorithmUtil.logger.debug("partition null");
+			return null;
+		}
+		
+		Partition maxPartition = partitions.get(0);
+		float cost = node.computeLoad(time, maxPartition), cost2;
+		for (Partition partition : partitions) {
+			cost2 = node.computeLoad(time, partition);
+			if (cost2 > cost) {
+				cost = cost2;
+				maxPartition = partition;
+			}
+		}
+		return maxPartition;
+	}
+	
+	/**
+	 * Retrieves the node with the given ID.
+	 * The node is a reference and not a DEEP COPY
+	 * @param nodes
+	 * @param ID
+	 * @return
+	 */
+	protected static Node getNodeFromList(Vector<Node> nodes, String ID) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		for (Node node: nodes) {
+			if (node.getID().compareToIgnoreCase(ID) == 0) {
+				return node;
+			}
+		}
+		return null;
+	}
+	
+	/**
+	 * Retrieves the component types that are assigned on the given node
+	 * @param node
+	 * @return a string containing the component types in integer format: "0123" -> 4 types 0, 1, 2, 3
+	 */
+	protected static String getComponentTypes(Node node) {
+		int[] types = new int[SystemSettings.getSystemSettings().getNo_component_types()];
+		for (Partition p : node.getAssignedPartitions()) 
+			for (Component c : p.getAssignedComponents())
+				types[c.getType()] = c.getType();
+		
+		StringBuilder s = new StringBuilder();
+		for (int i=0; i<types.length; i++) {
+			if (types[i] != 0) 
+				s.append(types[i]);  
+		}
+		return s.toString();
+	}
+	
+	/**
+	 * Retrieves the number of component types existing on a given node
+	 * @param node
+	 * @return
+	 */
+	public static int getNoComponentTypes(Node node) {
+		int[] types = new int[SystemSettings.getSystemSettings().getNo_component_types()];
+		for (Partition p : node.getAssignedPartitions()) 
+			for (Component c : p.getAssignedComponents())
+				types[c.getType()] = c.getType()+1;
+		
+		int count = 0;
+		for (int i=0; i<types.length; i++) {
+			if (types[i] != 0)
+				++count;
+		}
+		return count;
+	}	
+	
+	/**
+	 * Retrieves a random component of a certain type given the list of nodes
+	 * @param type
+	 * @param nodes
+	 * @return
+	 */
+	public static String getRandomComponent(int type, Vector<Node> nodes) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		if (type >= SystemSettings.getSystemSettings().getNo_component_types()) {
+			AlgorithmUtil.logger.debug("type greater than largest allowed type value");
+			return null;		
+		}
+		Vector<Component> components = AlgorithmUtil.gatherComponents(nodes);
+		int i = 0;
+		while (i < components.size()) {
+			if (components.get(i).getType() != type)
+				components.remove(i);
+			else
+				i++;
+		}
+		if (components.size() > 0) 
+			return components.get(0 + (int)(Math.random() * ((components.size() -1 - 0) + 1))).getID();
+		return null;
+	}
+		
+	public static float computeNodeCost(Node node, Vector<Node> nodes) {
+		if (node == null) {
+			AlgorithmUtil.logger.debug("node null");
+			return (int)Float.NEGATIVE_INFINITY;
+		}
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return (int)Float.NEGATIVE_INFINITY;
+		}
+		Vector<Component> components = AlgorithmUtil.gatherComponents(node);		
+		float cost = 0;
+		
+		for (Component component : components) {
+			cost += AlgorithmUtil.computeCostForComponent(nodes, component, null);	
+		}
+		return cost;
+	}
+		
+	/**
+	 * Simulates a failure in one or more nodes
+	 * @param nodes
+	 * @return the list of components from the failed nodes
+	 */
+	protected static Vector<Component> simulateFailure(Vector<Node> nodes, int noNodesToFail) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		if (noNodesToFail <= 0) {
+			AlgorithmUtil.logger.debug("noNodesToFail not a positive value");
+			return null;		
+		}		Vector<Component> components = new Vector<Component>();
+		
+		int j = 0, selected = 0;
+		if (nodes.size() == 1)
+			return null;
+
+		for (int i=0; i< noNodesToFail; i++) {
+				do {
+					selected = 0 + (int)(Math.random() * ((nodes.size() -1  - 0) + 1));
+				} while (nodes.get(selected).isStopped);
+				
+				nodes.get(selected).isStopped = true;
+				components.addAll(new Vector<Component>(AlgorithmUtil.gatherComponents(nodes.get(selected))));
+
+				// Reassign in a round robin manner node partitions to the rest of the nodes
+				j=0;				
+				while (nodes.get(selected).getAssignedPartitions().size() > 0){
+					if (j == selected || nodes.get(j).isStopped)
+						j++;
+					
+					if (j >= nodes.size())
+						j=0;
+					
+					Partition p = nodes.get(selected).getAssignedPartitions().remove(0);
+					nodes.get(j).addPartition(p);
+					p.assignToNode(nodes.get(j).getID());
+					p.removeAssignedComponents();
+					
+					j++;
+					if (j >= nodes.size())
+						j=0;
+				}
+		}
+		return components;
+	}
+	
+	/**
+	 * Returns the number of overloaded nodes
+	 * @param nodes
+	 * @param time
+	 * @return
+	 */
+	public static int computeNumberOverloadedNodes(Vector<Node> nodes, int time) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return (int)Float.NEGATIVE_INFINITY;
+		}
+		int count = 0;
+		int k=0;
+		for (Node node: nodes) {
+			if (node.computeLoad(time,k++) > SystemSettings.getSystemSettings().getMax_node_load_threshold())
+				count++;
+		}
+		return count;
+	}
+
+	/**
+	 * Computes the costs of relocating a partition on every available nodes. The partition must always have a positive no of components
+	 * @param partition
+	 * @param nodes
+	 * @return a vector sorted ascending after relocation costs
+	 */
+	@SuppressWarnings("unchecked")
+	public static Vector<CostData> computePartitionRelocationCost(Partition partition, Vector<Node> nodes) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		if (partition == null) {
+			AlgorithmUtil.logger.debug("partition null");
+			return null;
+		}
+		if (partition.getAssignedComponents().size() == 0)
+			return null;
+		
+		float cost = 0f;
+		Vector<CostData> costs = new Vector<CostData>();
+		for (Node n : nodes) {
+			cost = 0f;
+			for (Component c : partition.getAssignedComponents()) {	
+				if (n.getID().compareToIgnoreCase(partition.getAssignedNodeID()) != 0 && !n.isStopped) {
+					cost += AlgorithmUtil.computeCostForComponent(nodes, c, n);
+				}
+			}
+			costs.add(new AlgorithmUtil(). new CostData(partition, n, cost, partition.getAssignedComponents().get(0).getType()));
+		}	
+		Collections.sort(costs, new AlgorithmUtil(). new ItemComparatorAsc());		
+		return costs;
+	}
+
+	/**
+	 * Returns the number of failed nodes
+	 * @param nodes
+	 * @return
+	 */
+	public static int computeNoFailedNodes(Vector<Node> nodes) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return (int)Float.NEGATIVE_INFINITY;
+		}		int no = 0;
+		for (Node node : nodes) {
+			if (node.isStopped)
+				no++;
+		}
+		return no;
+	}
+
+	/**
+	 * Returns the node the given component belongs to
+	 * @param nodes
+	 * @param component
+	 * @return
+	 */
+	private static Node findNode(Vector<Node> nodes, Component component) {
+		if (nodes == null) {
+			AlgorithmUtil.logger.debug("nodes null");
+			return null;
+		}
+		if (component == null) {
+			AlgorithmUtil.logger.debug("component null");
+			return null;
+		}		
+		Vector<Partition> partitions;
+		Vector<Component> components;
+		for (Node node : nodes) {
+			partitions = node.getAssignedPartitions();
+			for (Partition partition : partitions) {
+				components = partition.getAssignedComponents();
+				for (Component c : components) {					 
+					if (component.getID().compareToIgnoreCase(c.getID()) == 0) {
+						return node;
+					}
+				}
+			}
+		}
+		
+		return null;
+	}
+	
+	protected class ItemComparatorAsc implements Comparator {
+		public final int compare(Object a, Object b) {
+			if (((CostData) a).getCost() >= ((CostData) b).getCost())
+				return -1;
+			return 1;
+		}
+	}
+	
+	public final class CostData {
+		public float cost;
+		public Partition partition;
+		public Node node;
+		public int partitionType;
+		
+		public CostData(Partition partition, Node node, float cost, int partitionType) {
+			this.partition = partition;
+			this.node = node;
+			this.cost = cost;
+			this.partitionType = partitionType;
+		}
+
+		public float getCost() {
+			return this.cost;
+		}
+
+		public Partition getPartition() {
+			return this.partition;
+		}
+
+		public Node getNode() {
+			return this.node;
+		}
+
+		public int getPartitionType() {
+			return this.partitionType;
+		}
+	}
+}

File src/mosaic/scheduler/platform/com/json/beans/ComponentLoadListBean.java

+package mosaic.scheduler.platform.com.json.beans;
+
+public class ComponentLoadListBean {
+	private int component_type;
+	private String component_load;
+//	private Vector<QueueListBean> queue_list;
+	
+	public ComponentLoadListBean(int componentType, String componentLoad) {
+		this.component_load = componentLoad;
+		this.component_type = componentType;
+//		this.queue_list = queueList;
+	}
+
+	public int getComponent_type() {
+		return component_type;
+	}
+
+	public String getComponent_load() {
+		return component_load;
+	}
+
+//	public Vector<QueueListBean> getQueueList() {
+//		return queue_list;
+//	}
+	
+}

File src/mosaic/scheduler/platform/com/json/beans/ComponentWorkflowBean.java

+package mosaic.scheduler.platform.com.json.beans;
+
+public class ComponentWorkflowBean {
+	private int component_type;
+	private String read_rate, write_rate;
+	private String linked_to_component;
+	
+	public ComponentWorkflowBean(int componentID, String linkedToComponent, String writeRate, String readRate) {
+		this.component_type = componentID;
+		this.linked_to_component = linkedToComponent;
+		this.read_rate = readRate;
+		this.write_rate = writeRate;
+	}
+
+	public int getComponent_type() {
+		return component_type;
+	}
+
+	public String[] getLinked_to_Component() {
+		return linked_to_component.split(",");
+	}
+	
+	public String[] getRead_rate() {
+		return read_rate.split(",");
+	}
+
+	public String[] getWrite_rate() {
+		return write_rate.split(",");
+	}
+	
+	
+}

File src/mosaic/scheduler/platform/com/json/beans/ComponentsBean.java

+package mosaic.scheduler.platform.com.json.beans;
+
+public class ComponentsBean {
+	private int component_type;
+	private int component_number;
+	
+	public ComponentsBean (int componentType, int componentNumber) {
+		this.component_number = componentNumber;
+		this.component_type = componentType;
+	}
+
+	public int getComponent_type() {
+		return component_type;
+	}
+
+	public int getComponent_number() {
+		return component_number;
+	}
+	
+	
+}

File src/mosaic/scheduler/platform/com/json/beans/NodeListBean.java

+package mosaic.scheduler.platform.com.json.beans;
+
+import java.util.Vector;
+
+public class NodeListBean {
+	private String node_id;
+	private Vector<ComponentsBean> components;
+	
+	public NodeListBean(String nodeID, Vector<ComponentsBean> components) {
+		this.node_id = nodeID;
+		this.components = components;
+	}
+
+	public String getNode_id() {
+		return node_id;
+	}
+
+	public Vector<ComponentsBean> getComponents() {
+		return components;
+	}
+}

File src/mosaic/scheduler/platform/com/json/beans/NodesBean.java

+package mosaic.scheduler.platform.com.json.beans;
+
+public class NodesBean {
+	private String node_id, node_load, node_datacenter_id, node_cloud_id;
+	
+	public NodesBean (String nodeID, String nodeDatacenterID, String nodeCloudID, String nodeLoad) {
+		this.node_id = nodeID;
+		this.node_load = nodeLoad;
+		this.node_datacenter_id = nodeDatacenterID;
+		this.node_cloud_id = nodeCloudID;
+	}
+
+	public String getNode_id() {
+		return node_id;
+	}
+
+	public String getNode_load() {
+		return node_load;
+	}
+
+	public String getNode_datacenter_id() {
+		return node_datacenter_id;
+	}
+
+	public String getNode_cloud_id() {
+		return node_cloud_id;
+	}	
+}

File src/mosaic/scheduler/platform/com/json/beans/QueueListBean.java

+package mosaic.scheduler.platform.com.json.beans;
+
+public class QueueListBean {
+	private String queue_id, no_messages;
+	
+	public QueueListBean(String queueID, String noMessages) {
+		this.queue_id = queueID;
+		this.no_messages = noMessages;	
+	}
+
+	public String getQueue_id() {
+		return queue_id;
+	}
+
+	public String[] getNo_messages() {
+		return no_messages.split(",");
+	}
+}

File src/mosaic/scheduler/platform/resources/AComponentRequirements.java

+package mosaic.scheduler.platform.resources;
+
+import org.apache.log4j.Logger;
+
+import mosaic.scheduler.platform.settings.SystemSettings;
+import mosaic.scheduler.test.TestRunner;
+
+public abstract class AComponentRequirements {
+	public static Logger logger = Logger.getLogger(TestRunner.class.getPackage().getName());
+
+	protected double[] cpuUsage = new double[SystemSettings.getSystemSettings().getTime_span()==Integer.MAX_VALUE ? 24 : SystemSettings.getSystemSettings().getTime_span()]; 
+	protected double[] memoryUsage = new double[SystemSettings.getSystemSettings().getTime_span()==Integer.MAX_VALUE ? 24 : SystemSettings.getSystemSettings().getTime_span()];
+	protected double[] networkUsage = new double[SystemSettings.getSystemSettings().getTime_span()==Integer.MAX_VALUE ? 24 : SystemSettings.getSystemSettings().getTime_span()];
+
+	public AComponentRequirements() {	
+		this.generateCpuUsage();
+		this.generateMemoryUsage();
+		this.generateNetworkUsage();
+	}
+	
+	public final double getCpuUsage(int time) {
+		if ((time >= 0) && (time < SystemSettings.getSystemSettings().getTime_span())) 
+			return this.cpuUsage[time]; 
+		else
+			return -1;
+	}
+	
+	public final double getMemoryUsage(int time) {
+		if ((time >= 0) && (time < SystemSettings.getSystemSettings().getTime_span())) 
+			return this.memoryUsage[time]; 
+		else
+			return -1;		
+	}
+	
+	public final double getNetworkUsage(int time) {
+		if ((time >= 0) && (time < SystemSettings.getSystemSettings().getTime_span())) 
+			return this.networkUsage[time]; 
+		else
+			return -1;
+	}
+	
+	public abstract void generateCpuUsage();
+	public abstract void generateMemoryUsage();
+	public abstract void generateNetworkUsage();
+	
+	public abstract void setCpuUsage(int time, double usage);
+	public abstract void setMemoryUsage(int time, double usage);
+	public abstract void setNetworkUsage(int time, double usage);
+}

File src/mosaic/scheduler/platform/resources/Component.java

+package mosaic.scheduler.platform.resources;
+
+import java.util.UUID;
+import java.util.Vector;
+
+/**
+ * Class for holding information about an application component
+ * @author Marc Frincu
+ *
+ */
+public final class Component  {
+	/**
+	 * Unique component ID
+	 */
+	private String ID = null;
+	/**
+	 * Vector indicating the IDs of other components this one links to
+	 */
+	private Vector<String> linkedTo = null; 
+	/**
+	 * The type of the component in case more than one types exist
+	 */
+	private int type = 0;
+	/**
+	 * Variable indicating whether the component can be collocated or not
+	 */
+	private boolean collocated = false;
+	
+	/**
+	 * Creates a new component
+	 * @param isCollocated true if it should be collocated or false otherwise
+	 * @param type the type of the component
+	 */
+	public Component(boolean isCollocated, int type) {
+		this.collocated = isCollocated;
+		this.type = type;
+		this.linkedTo = new Vector<String>();
+		this.ID = UUID.randomUUID().toString();
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	public Component clone() {
+		Component c = new Component(this.collocated, this.type);
+		c.linkedTo = (Vector<String>)c.linkedTo.clone();
+		return c;
+	}
+	
+	public void addConnection(String ID) {
+		this.linkedTo.add(ID);
+	}
+	
+	public Vector<String> getConnections() {
+		return this.linkedTo;
+	}
+	
+	public int getType(){
+		return this.type;
+	}
+	
+	public String getID() {
+		return this.ID;
+	}
+	
+	public boolean getIsCollocated() {
+		return this.collocated;
+	}
+}

File src/mosaic/scheduler/platform/resources/ComponentRequirementsList.java

+package mosaic.scheduler.platform.resources;
+
+import java.util.Hashtable;
+
+
+public class ComponentRequirementsList {
+	Hashtable<Integer, AComponentRequirements> reqs = null;
+	
+	private static ComponentRequirementsList cr = null;
+	
+	private ComponentRequirementsList() {
+		this.reqs = new Hashtable<Integer, AComponentRequirements>();
+	}
+	
+	public static ComponentRequirementsList getComponentsRequirement() {
+		if (cr == null) {
+			cr = new ComponentRequirementsList();
+		}
+		return cr;
+	}
+	
+	public void addComponentRequirement(int componentType, AComponentRequirements cr) {
+		this.reqs.put(componentType,  cr);
+	}
+	
+	
+	public AComponentRequirements getComponentRequirements(int componentType) {
+		return this.reqs.get(componentType);
+	}
+	
+}

File src/mosaic/scheduler/platform/resources/ComponentRequirementsPlatform.java

+package mosaic.scheduler.platform.resources;
+
+import mosaic.scheduler.platform.settings.SystemSettings;
+
+public class ComponentRequirementsPlatform extends AComponentRequirements {
+
+	@Override
+	public void generateCpuUsage() {
+		for (int i=0; i<SystemSettings.getSystemSettings().getTime_span(); i++) {
+			this.cpuUsage[i] = 30;
+		}
+	}
+
+	@Override
+	public void generateMemoryUsage() {
+		for (int i=0; i<SystemSettings.getSystemSettings().getTime_span(); i++) {
+			this.memoryUsage[i] = 30;
+		}		
+	}
+
+	@Override
+	public void generateNetworkUsage() {
+		for (int i=0; i<SystemSettings.getSystemSettings().getTime_span(); i++) {
+			this.networkUsage[i] = 30;
+		}
+	}
+
+	@Override
+	public void setCpuUsage(int time, double usage) {
+		if (time < 0 && time >= SystemSettings.getSystemSettings().getTime_span()) {
+			ComponentRequirementsPlatform.logger.fatal("time should be inside the specified time span");
+			return;
+		}
+		this.cpuUsage[time] = usage;		
+	}