/* * Copyright (c) 2005-2006 Erik Tigerholm * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ namespace OpenTraffic.Network { using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Threading; using System.Xml.Serialization; using OpenTraffic.Model.Result; using OpenTraffic.Model.Route; using OpenTraffic.Model.StopCriteria; public enum SERVER_STATES { NOT_STARTED, INITIALIZE, PARTITION, TRANSFERING_DATA, SIMULATION, RESTARTING_ITERATION, FETCHING_RESULT, NO_CLIENTS_RUNNING }; public class TrafficServer { public ResultData ResultToCompare { get; set; } public float smoothing { get; set; } public Model.SimulatorFactory.AbstractSimulatorFactory SimulatorFactory { get; set; } public bool GenerateRoutes { get; set; } public int NumberOfIteration { get; set; } public List Clients { get; private set; } private OpenTraffic.Model.TrafficModel model; private List connected; private List profiles; private OpenTraffic.TrafficProfile prof; public TrafficServer(Model.TrafficModel m) { GenerateRoutes = true; NumberOfIteration = 30; smoothing = float.NaN; model = m; Clients = new List(); profiles = new List(); LoadConfig(); } private void CompareResult(ResultData r2) { if (ResultToCompare != null) { Dictionary stops; stops = new Dictionary(); stops.Add("flow", delegate(ResultData res, float i, Model.TrafficModelLink l) { return res.GetLinkResultFromTime(i, l).FlowIn * 60 * 60; }); stops.Add("tt", delegate(ResultData res, float i, Model.TrafficModelLink l) { return res.GetQueuingTime(i, l) + ((res.GetTravelTime(i, l) == 0) ? l.CalculateFreeFlowTravelTime() : res.GetTravelTime(i, l)); }); string str = "AAD:\t"; foreach (KeyValuePair kv in stops) { float value = new Model.StopCriteria.AverageAbsoluteDifference(kv.Value).Compare(ResultToCompare, r2, model); str += " | " + kv.Key + ": " + value.ToString("f"); } Console.WriteLine(str); Console.WriteLine(); } } public List Profiles { get { return profiles; } } public bool AddClient(string ip, int port, float scale) { Clients.Add(new ClientDescription(ip, port, scale)); return true; } public void SaveConfig() { using (System.IO.StreamWriter file = new System.IO.StreamWriter("opentraffic_network.xml")) { System.Xml.Serialization.XmlSerializer writer = new System.Xml.Serialization.XmlSerializer(Clients.GetType()); writer.Serialize(file, Clients); } } public bool LoadConfig() { try { using (TextReader reader = new StreamReader("opentraffic_network.xml")) { XmlSerializer serializer = new XmlSerializer(Clients.GetType()); Clients = (List)serializer.Deserialize(reader); // reader.Close(); } return true; } catch (Exception) { return false; } } public void WaitToFinish() { bool ended = true; while (ended != false) { ended = false; foreach (ClientDescription cd in connected) { if (!cd.IterationFinished()) { ended = true; } } Thread.Sleep(0); Thread.Sleep(500); } } public void StartSimulation(BackgroundWorker worker) { if (worker != null) { profiles.Clear(); profiles.Add(prof); if (worker.WorkerReportsProgress) worker.ReportProgress(0, SERVER_STATES.INITIALIZE); int i = 0; int sessionId = 1; connected = new List(); foreach (ClientDescription cd in Clients) { if (cd.StartSimulation(sessionId)) { i++; cd.id = i; connected.Add(cd); } } if (connected.Count == 0) return; Console.WriteLine("Running simulation with " + connected.Count + " clients"); float[] weights = new float[connected.Count]; i = 0; foreach (ClientDescription cd in connected) { weights[i] = cd.Scale; i++; } if (worker.WorkerReportsProgress) worker.ReportProgress(0, SERVER_STATES.PARTITION); model.Partion(weights); if (worker.WorkerReportsProgress) worker.ReportProgress(0, SERVER_STATES.TRANSFERING_DATA); if (SimulatorFactory == null) SimulatorFactory = new Model.SimulatorFactory.QueueFactory(-1, 30, new Model.Simulator.RouteAssigner.ShortestPath()); prof.Start("transferring model"); foreach (ClientDescription cd in connected) { cd.TransferModel(model, connected, null, cd.id , this.SimulatorFactory); } prof.Stop("transferring model"); prof.Start("PreCalculation"); foreach (ClientDescription cd in connected) { cd.StartPreCalculation(); } WaitToFinish(); prof.Stop("PreCalculation"); if (worker.WorkerReportsProgress) worker.ReportProgress(0, SERVER_STATES.SIMULATION); } } public void MoreRoutes() { List routes = new List(); foreach (ClientDescription cd in connected) { cd.StartGenerateNewRoutes(); } WaitToFinish(); prof.Start("transferring routes"); foreach (ClientDescription cd in connected) { routes.AddRange(cd.GetRoutes(model)); } model.Routes.AddRange(routes); foreach (ClientDescription cd in connected) { cd.AddRoutes(routes, model.Partition); } prof.Stop("transferring routes"); } public void Work(object sender, DoWorkEventArgs e) { prof = new TrafficProfile(); prof.Start("simulation"); if (sender != null && e != null) { BackgroundWorker worker = sender as BackgroundWorker; bool success = initSimulation(worker); if (success) { prof.Start("iterations"); ResultData prevRes = null; for (int i = 0; i < NumberOfIteration; i++) { xferHistoricalResult(prevRes); generateMoreRoutes(); restartIteration(); if (runSimulation(e, worker, prevRes)) { break; } if (worker.WorkerReportsProgress) { worker.ReportProgress(100, SERVER_STATES.FETCHING_RESULT); } prevRes = fetchResult(worker, prevRes); } prof.Stop("iterations"); foreach (ClientDescription cd in connected) { profiles.Add(cd.GetProfile()); } e.Result = prevRes; Abort(); } } prof.Stop("simulation"); return; } private bool initSimulation(BackgroundWorker worker) { prof.Start("init"); bool success = true; StartSimulation(worker); if (connected.Count == 0) { if (worker.WorkerReportsProgress) { worker.ReportProgress(0, SERVER_STATES.NO_CLIENTS_RUNNING); } success = false; } else { model.ResultFactory.CreateResult(); } prof.Stop("init"); return success; } private ResultData fetchResult(BackgroundWorker worker, ResultData prevRes) { prof.Start("Fetching result"); ResultData res = model.ResultFactory.CreateResult(); foreach (ClientDescription cd in connected) { ResultData tres = cd.FetchResult(); res.AddResult(tres); } CompareResult(res); if (worker.WorkerReportsProgress) { worker.ReportProgress(0, SERVER_STATES.RESTARTING_ITERATION); } if (float.IsNaN(smoothing) || prevRes == null) { prevRes = res; } else { prevRes.MergeResult(res, smoothing, model.TrafficModelLinks); } prof.Stop("Fetching result"); return prevRes; } private bool runSimulation(DoWorkEventArgs e, BackgroundWorker worker, ResultData prevRes) { prof.Start("simulation"); foreach (ClientDescription cd in connected) { cd.StartIteration(); } bool aborted = waitForFinishedIterations(e, worker, prevRes); prof.Stop("simulation"); return aborted; } private void restartIteration() { prof.Start("restart iteration"); foreach (ClientDescription cd in connected) { cd.StartRestartIteration(); } WaitToFinish(); prof.Stop("restart iteration"); } private void generateMoreRoutes() { prof.Start("route generation"); if (GenerateRoutes) { MoreRoutes(); } prof.Stop("route generation"); } private void xferHistoricalResult(ResultData prevRes) { prof.Start("Historical result transfer"); if (prevRes != null) { foreach (ClientDescription cd in connected) { cd.SetHistoricalResult(prevRes); } } prof.Stop("Historical result transfer"); } private bool waitForFinishedIterations(DoWorkEventArgs e, BackgroundWorker worker, ResultData prevRes) { bool iterationFinished = false; bool aborted = false; while (!iterationFinished) { iterationFinished = true; int minPercent = 0; foreach (ClientDescription cd in connected) { if (!cd.IterationFinished()) { minPercent = Math.Min(minPercent, cd.GetProcentFinished()); iterationFinished = false; } } if (worker.WorkerReportsProgress) worker.ReportProgress(minPercent, SERVER_STATES.SIMULATION); if (worker.CancellationPending) { e.Result = prevRes; Abort(); aborted = true; break; } Thread.Sleep(500); } return aborted; } public void Abort() { foreach (ClientDescription cd in connected) { cd.Abort(); } } } }