import java.util.Vector;

import org.simgrid.msg.Msg;
import org.simgrid.msg.Host;
import org.simgrid.msg.Process;
import org.simgrid.msg.HostFailureException;
import org.simgrid.msg.HostNotFoundException;

public class VIPServer extends Process {
	private static DefaultLFC defaultLFC = null;
	private static Vector<LFC> lfcList = new Vector<LFC>();
	private static DefaultSE defaultSE = null;
	private static Vector<SE> seList = new Vector<SE>();

	// Worker node management for registration and termination 
	private Vector<Gate> gateWorkers = new Vector<Gate>();
	private Vector<Merge> mergeWorkers = new Vector<Merge>();
	private int endedGateWorkers = 0;
	private int runningMergeWorkers = 0;

	public static LFC getDefaultLFC() {
		return defaultLFC;
	}

	public static void setDefaultLFC(DefaultLFC lfc) {
		if (defaultLFC != null){
			Msg.warn("The default LFC has already been identified. Please " +
					"check there is only one 'DefaultLFC' process in the " +
					"deployement file.");
		} else {
			defaultLFC = lfc;
		}
	}

	public static Vector<LFC> getLFCList() {
		return lfcList;
	}

	public static SE getDefaultSE() {
		return defaultSE;
	}

	public static void setDefaultSE(DefaultSE se) {
		if (defaultSE != null){
			Msg.warn("The default SE has already been identified. Please " +
					"check there is only one 'DefaultSE' process in the " +
					"deployement file.");
		} else {
			defaultSE = se;
			Msg.info("Default SE is '"+ defaultSE.getName() + "'");
		}
	}

	public static Vector<SE> getSEList() {
		return seList;
	}

	public static SE getSEbyName(String seName){
		for (SE se : seList) 
			if (se.getName().matches(seName))
				return se;
		// Some worker may define a close SE that was never used, hence that 
		// exists neither in the platform nor the deployment files. In that case
		// we fall back on the default SE. 
		Msg.warn("Cannot find an SE named '" + seName +"'. Return Default SE");
		return VIPServer.getDefaultSE();
	}

	public VIPServer(Host host, String name, String[]args) {
		super(host,name,args);
	}

	public void main(String[] args) throws HostFailureException,
	HostNotFoundException {
		Msg.info("A new simulation starts!");
		boolean stop=false, timer = false;
		long totalParticleNumber = 0;
		Msg.info("Init log file with JOBID,DOWNTIME,UPTIME,EXECUTIONTIME,TOTALTIME");
                System.out.println("JOBID,DOWNTIME,UPTIME,EXECUTIONTIME,TOTALTIME");
		while(!stop){
			// Use of some simulation magic here, every worker knows the 
			// mailbox of the VIP server
			GateMessage message = (GateMessage) Message.getFrom("VIPServer");
			Job job = (Job) message.getSender();

			switch (message.getType()){
			case "GATE_CONNECT":
				gateWorkers.add((Gate) job);

				Msg.debug(gateWorkers.size() + " GATE worker(s) registered " +
						"out of " + VIPSimulator.numberOfGateJobs);

				job.begin();
				break;

			case "GATE_PROGRESS":
				totalParticleNumber += message.getParticleNumber();
				Msg.info (totalParticleNumber + 
						" particles have been computed. "+
						VIPSimulator.totalParticleNumber + " are expected.");
				if (totalParticleNumber < VIPSimulator.totalParticleNumber){
					//  WARNING TEMPORARY HACK FOR FIRST TEST
					job.end();
					// SHOULD BE REPLACED BY
					//job.carryOn();
				} else {
					if (!timer){
						Msg.info("The expected number of particles has been "+
								"reached. Start a timer!");
						new Process(this.getHost(),"Timer"){
							public void main(String[] args) throws 
							HostFailureException {
								Process.sleep(VIPSimulator.sosTime);
								if (runningMergeWorkers < 
										VIPSimulator.numberOfMergeJobs){
									Msg.info("Timeout has expired. Wake up " + 
											mergeWorkers.size() + 
											" Merge worker(s)");

									mergeWorkers.firstElement().begin();
									runningMergeWorkers++;
								} else {
									Msg.info("No need for Merge workers on " +
											" timeout expiration");
								}
							}
						}.start();
						timer = true;
					}
					job.end();
				}
				break;

			case "GATE_DISCONNECT":
				// a GATE job is now complete, send it a kill signal.
				job.kill();

				endedGateWorkers++;
				if (endedGateWorkers == VIPSimulator.numberOfGateJobs){
					//Add a safety guard in case the deployment has no Merge
					if (VIPSimulator.numberOfMergeJobs == 0)
						stop = true;
					if (runningMergeWorkers < VIPSimulator.numberOfMergeJobs){
						Msg.info("All GATE workers sent a 'GATE_END' message" +
								"Wake up " + mergeWorkers.size() + 
								" Merge worker(s)");
						runningMergeWorkers++;
						mergeWorkers.firstElement().begin();
					} 
				}
				break;

			case "MERGE_CONNECT":
				mergeWorkers.add((Merge) job);
				Msg.debug(mergeWorkers.size() + " MERGE worker(s) registered "+
						"out of " + VIPSimulator.numberOfMergeJobs);
				break;

			case "MERGE_DISCONNECT":
				// a MERGE job is now complete, send it a kill signal.
				job.kill();
				// then stop
				stop=true;
				break;
			default:
				break;

			}
		}

		// sleep sosTime so that tasks have the time to finish before shutting 
		// down the LFCs and SEs
		Process.sleep(VIPSimulator.sosTime);

		Msg.info("Server waited for " + VIPSimulator.sosTime/1000 +" seconds." +
				" It's time to shutdown the system.");

		// Shutting down all the LFCs
		for (LFC lfc : getLFCList())
			lfc.kill();

		// Shutting down all the SEs
		for (SE se : getSEList())
			se.kill();
	}
}

@@ -2253,20 +2253,20 @@
 ;%0A%09%09Msg.
-info
+verb
 (%22Init l
@@ -2283,137 +2283,132 @@
 th J
-OBID,DOWNTIME,UPTIME,EXECUTIONTIME,TOTALTIME%22);%0A                System.out.println(%22JOBID,DOWNTIME,UPTIME,EXECUTIONTIME,TOTALTIME
+obId,DownTime,UpTime,ExecutionTime,%22 +%0A%09%09%09%09%22TotalTime%22);%0A%09%09System.out.println(%22JobId,DownTime,UpTime,ExecutionTime,Totaltime
 %22);%0A

Update header of timings file to match the behavior of the new scripts