/* * Accepts a new job from the data center. Returns true if the job was accepted, * false if it was not. */ public Boolean AcceptJob(bool SimStart) { Boolean jobAccepted = false; if (!SimStart && (GV.VMStatus)GV.GlobalComms.Rows[SpaceNumber]["Status"] == GV.VMStatus.justArrived) { if (DataCenter.CheckForExistingJob(SpaceNumber)) { TransType = GV.TransmissionType.recReturnVM; return(true); } else { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.idle; } } if ((int)GV.GlobalComms.Rows[SpaceNumber]["Time"] <= GV.tooClose) { if (SimStart || (GV.VMStatus)GV.GlobalComms.Rows[SpaceNumber]["Status"] == GV.VMStatus.idle) { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.unavailable; } } else if (((GV.VMStatus)GV.GlobalComms.Rows[SpaceNumber]["Status"] == GV.VMStatus.idle) || SimStart) { if ((GV.VMStatus)GV.GlobalComms.Rows[SpaceNumber]["Status"] == GV.VMStatus.idle) { if (DataCenter.FindBackupLocations(SpaceNumber)) { GV.GlobalComms.Rows[SpaceNumber]["Primary"] = SpaceNumber; Job NewJob = new Job(); CurrentJob = NewJob; DataCenter.AssignJobtoBackups(CurrentJob, SpaceNumber); if (SimStart) { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.processing; BackupsNeeded = GV.BackupsNeeded.none; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; } else { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.receiving; TransType = GV.TransmissionType.recInputData; BackupsNeeded = GV.BackupsNeeded.BothBackups; DownloadDataSize = CurrentJob.inputDataSize; RemainingDatatoTransmit = CurrentJob.inputDataSize; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = GV.DCAddress; // To do, set backup locations currentjobs to new job } // Estimate of how long it will take to offload final data TimeToTransferFinalData = (int)Math.Round(CurrentJob.outputDataSize / (54.0 / 20), 0); TimeToTransferVM = TimeToTransferFinalData + (int)Math.Round(4000 / (54.0 / 20), 0); jobAccepted = true; } // find backup locations successful else { //MessageBox.Show("W:" + SpaceNumber + "No backup found"); GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.idle; GV.GlobalComms.Rows[SpaceNumber]["Primary"] = -1; } } // if available else // not available { //do nothing } } return(jobAccepted); } // AcceptJob
static void Main(string[] args) { Simulation sim = new Simulation("SomeSimulation", @"C:\CSSL"); Settings.WriteOutput = false; Settings.NotifyObservers = true; // Parameters... double dispatchTime = 1E-3; double lambda = 100; int numberServerpools = 10; int numberServerpoolsToChooseFrom = 10; // The experiment part... sim.MyExperiment.NumberOfReplications = 3; sim.MyExperiment.LengthOfReplication = 10; sim.MyExperiment.LengthOfWarmUp = 2; // The model part... DataCenter dataCenter = new DataCenter(sim.MyModel, "DataCenter"); for (int i = 0; i < numberServerpools; i++) { dataCenter.AddServerpool(new ServerPool(dataCenter, $"Serverpool_{i}")); } Dispatcher dispatcher = new Dispatcher(dataCenter, "Dispatcher", new ExponentialDistribution(1), double.PositiveInfinity, dataCenter.ServerPools, dispatchTime, numberServerpoolsToChooseFrom); dataCenter.SetDispatcher(dispatcher); JobGenerator jobGenerator = new JobGenerator(dataCenter, "JobGenerator", new ExponentialDistribution(lambda), dispatcher); dataCenter.SetJobGenerator(jobGenerator); // The observer part... DispatcherObserver dispatcherObserver = new DispatcherObserver(sim); dispatcher.Subscribe(dispatcherObserver); DataCenterObserver dataCenterObserver = new DataCenterObserver(sim); dataCenter.Subscribe(dataCenterObserver); foreach (ServerPool serverpool in dataCenter.ServerPools) { ServerPoolObserver serverpoolObserver = new ServerPoolObserver(sim); serverpool.Subscribe(serverpoolObserver); } // Run... sim.Run(); // The reporting part... SimulationReporter reporter = sim.MakeSimulationReporter(); reporter.PrintSummaryToFile(); reporter.PrintSummaryToConsole(); }
} // Transmit // The receive cycle is at the end of the time loop. It checks the status of each car and takes appropriate // action based on the status and the transmission type, if any. public void Receive() { // Decrement the time left in the shift for th ecurrent car. GV.GlobalComms.Rows[SpaceNumber]["Time"] = (int)GV.GlobalComms.Rows[SpaceNumber]["Time"] - 1; // Check the car's status switch ((GV.VMStatus)GV.GlobalComms.Rows[SpaceNumber]["Status"]) { // If the car was processing, then call to run the current job. case GV.VMStatus.processing: // If the current job is complete, set the status to transmitting, and the transmission // type to final data. if (CurrentJob.Run()) // returns true if job is complete { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.transmitting; TransType = GV.TransmissionType.transFinalData; RemainingDatatoTransmit = CurrentJob.outputDataSize; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = GV.DCAddress; } // If the job didn't complete, then check to see if we are leaving soon and need to start // migrating our VM. If so, we always migrate to the car holding our random backup. That // car will send the job back to the new car occupying this same spot. else if ((int)GV.GlobalComms.Rows[SpaceNumber]["Time"] <= StartMigration) { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.transmitting; TransType = GV.TransmissionType.transVM; int randomBackup = Convert.ToInt32(GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"]); if (randomBackup != -1) { GV.GlobalComms.Rows[SpaceNumber]["Partner"] = randomBackup; RemainingDatatoTransmit = GV.VMSize + CurrentJob.outputDataSize; DataCenter.NotifyPartnerofTransfer((int)GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"], RemainingDatatoTransmit, GV.TransmissionType.recVM, CurrentJob); } } break; //If we are holding, we first check to see if we need to offload the backup. //We do that if we have less than an hour in our shift. case GV.VMStatus.holding: int newBackupLoc = -1; if ((int)GV.GlobalComms.Rows[SpaceNumber]["Time"] <= GV.tooClose) { Boolean bBackupFound = false; int PrimaryCar = (int)GV.GlobalComms.Rows[SpaceNumber]["Primary"]; if (Convert.ToInt32(GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"]) == SpaceNumber && Convert.ToInt32(GV.GlobalComms.Rows[PrimaryCar]["LocalBackup"]) != -1) { bBackupFound = DataCenter.FindRandomBackupLocation(PrimaryCar); if (bBackupFound) { newBackupLoc = (int)GV.GlobalComms.Rows[PrimaryCar]["RandomBackup"]; // Update the two backup locations so that they know about each other. int localBackup = (int)GV.GlobalComms.Rows[PrimaryCar]["LocalBackup"]; GV.GlobalComms.Rows[newBackupLoc]["LocalBackup"] = localBackup; GV.GlobalComms.Rows[localBackup]["RandomBackup"] = newBackupLoc; } } else { if (Convert.ToInt32(GV.GlobalComms.Rows[SpaceNumber]["LocalBackup"]) == SpaceNumber && Convert.ToInt32(GV.GlobalComms.Rows[PrimaryCar]["RandomBackup"]) != -1) { bBackupFound = DataCenter.FindLocalBackupLocation(PrimaryCar); } if (bBackupFound) { newBackupLoc = (int)GV.GlobalComms.Rows[PrimaryCar]["LocalBackup"]; // Update the two backup locations so that they know about each other. int randomBackup = (int)GV.GlobalComms.Rows[PrimaryCar]["RandomBackup"]; GV.GlobalComms.Rows[newBackupLoc]["RandomBackup"] = randomBackup; GV.GlobalComms.Rows[randomBackup]["LocalBackup"] = newBackupLoc; } } if (bBackupFound) { int DataSize = CurrentJob.inputDataSize; DataCenter.NotifyPartnerofTransfer(newBackupLoc, CurrentJob.inputDataSize, GV.TransmissionType.recBackupData, CurrentJob); // Let the new backup vehicle know what's up. DataCenter.AssignJobtoVehicle(CurrentJob, newBackupLoc, PrimaryCar, DataSize); GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.transmitting; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = newBackupLoc; GV.GlobalComms.Rows[newBackupLoc]["Partner"] = SpaceNumber; TransType = GV.TransmissionType.transBackupCopy; RemainingDatatoTransmit = DataSize; } } break; // Holding for return is a special status meaning that the primary car running our job has decided to // leave and has passed us their VM and intermediate data. We have to hold onto the job until the new // car arrives at the start of the next shift. When that happens, we change our status to transmitting // and notify the new car that it will be getting the VM back so that it can resume the job our predecessor // began. case GV.VMStatus.holdingForReturn: // Wait until the top of the next hour to send the VM back to the new car if (GV.intElapsedTime % GV.oneHour == 0) { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.transmitting; TransType = GV.TransmissionType.transReturnVM; RemainingDatatoTransmit = GV.VMSize + CurrentJob.outputDataSize; DataCenter.NotifyPartnerofTransfer(Convert.ToInt32(GV.GlobalComms.Rows[SpaceNumber]["Primary"]), RemainingDatatoTransmit, GV.TransmissionType.recReturnVM, CurrentJob); } break; // If we are idle or unavailable, we do nothing. The unavailable status will be changed when a new car // arrives in the spot. The idle status will change when we accept a job or a backup. case GV.VMStatus.idle: case GV.VMStatus.unavailable: break; // There are many transmission types, and each has diffent actions associated with it. default: // transmitting or receiving // decrement the remaining data count by the effective speed of transmission. RemainingDatatoTransmit -= Convert.ToDouble(GV.GlobalComms.Rows[SpaceNumber]["Speed"]); // If we have finished transmitting: if (RemainingDatatoTransmit <= 0) { switch (TransType) { //Done receiving input data, need to make 2 backups. case GV.TransmissionType.recInputData: GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.transmitting; TransType = GV.TransmissionType.transBackups; BackupsNeeded = GV.BackupsNeeded.BothBackups; RemainingDatatoTransmit = GV.inputDataSize; if ((int)GV.GlobalComms.Rows[SpaceNumber]["LocalBackup"] == -1) { MessageBox.Show("Primary Backup Vehicle invalid", "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { GV.GlobalComms.Rows[SpaceNumber]["Partner"] = GV.GlobalComms.Rows[SpaceNumber]["LocalBackup"]; GV.GlobalComms.Rows[(int)GV.GlobalComms.Rows[SpaceNumber]["LocalBackup"]]["Partner"] = SpaceNumber; } DataCenter.NotifyPartnerofTransfer((int)GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"], RemainingDatatoTransmit, GV.TransmissionType.recBackupData, CurrentJob); break; // Check to see if both backups are complete. If not, start the second backup. case GV.TransmissionType.transBackups: if (BackupsNeeded == GV.BackupsNeeded.BothBackups) { BackupsNeeded = GV.BackupsNeeded.RandomBackup; RemainingDatatoTransmit = GV.inputDataSize; if ((int)GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"] == -1) { MessageBox.Show("Secondary Backup Vehicle invalid", "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } else { GV.GlobalComms.Rows[SpaceNumber]["Partner"] = Convert.ToInt32(GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"]); GV.GlobalComms.Rows[(int)GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"]]["Partner"] = SpaceNumber; } DataCenter.NotifyPartnerofTransfer((int)GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"], RemainingDatatoTransmit, GV.TransmissionType.recBackupData, CurrentJob); } else if (BackupsNeeded == GV.BackupsNeeded.LocalBackup || BackupsNeeded == GV.BackupsNeeded.RandomBackup) { if ((int)GV.GlobalComms.Rows[SpaceNumber]["Time"] > TimeToTransferFinalData + CurrentJob.jobLength) { StartMigration = 0; } else { StartMigration = TimeToTransferVM; } GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.processing; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; TransType = GV.TransmissionType.none; BackupsNeeded = GV.BackupsNeeded.none; } else // (BackupsNeeded == GV.BackupsNeeded.none { MessageBox.Show("Transmitting backups when none needed.", "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } break; // Ive offloaded my backup to another vehicle, and am waiting to leave. Set my // status to unavailable. case GV.TransmissionType.transBackupCopy: GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.unavailable; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; break; // I'm done receiving backup data, set my status to holding case GV.TransmissionType.recBackupData: GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.holding; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; TransType = GV.TransmissionType.none; break; // I received the backup from a departing vehicle, now I have to hold it until // the new vehicle arrives. case GV.TransmissionType.recVM: if (Convert.ToInt32(GV.GlobalComms.Rows[SpaceNumber]["Primary"]) == -1) { //MessageBox.Show("Can't receive VM. Primary is -1"); } else { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.holdingForReturn; TransType = GV.TransmissionType.none; RemainingDatatoTransmit = GV.VMSize + CurrentJob.outputDataSize; } GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; break; // I am the new car and have received a VM from a backup car. I start // running the program. case GV.TransmissionType.recReturnVM: GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.processing; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; break; // I am a departing car and have finished transmitting my VM. I become unavailable. case GV.TransmissionType.transVM: GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.unavailable; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; break; // I completed my job! If it's too close to time to leave, I become unavailable. // Otherwise I set myself idle so that I can be assigned a new job or can become // a backup for another car. case GV.TransmissionType.transFinalData: if ((int)GV.GlobalComms.Rows[SpaceNumber]["Time"] <= GV.tooClose) { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.unavailable; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; } else { GV.GlobalComms.Rows[SpaceNumber]["Status"] = GV.VMStatus.idle; GV.GlobalComms.Rows[SpaceNumber]["Partner"] = SpaceNumber; } // After the job is complete, write out the data to the .csv file. The // actual write to file takes place in the data center once per seond for // all cars. This is to help the speed of the simulation. string OutputString = CurrentJob.jobNumber + "," + CurrentJob.StartTime.ToString() + "," + GV.currentTime.ToString() + "," + CurrentJob.GetJobLength().ToString() + "," + (GV.currentTime - CurrentJob.StartTime).TotalSeconds + "," + SpaceNumber; GV.csv.AppendLine(OutputString); DataCenter.DeleteBackup((int)GV.GlobalComms.Rows[SpaceNumber]["LocalBackup"], (int)GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"]); GV.GlobalComms.Rows[SpaceNumber]["LocalBackup"] = -1; GV.GlobalComms.Rows[SpaceNumber]["RandomBackup"] = -1; GV.GlobalComms.Rows[SpaceNumber]["Primary"] = -1; // set stop time break; default: break; } break; } // switch on transmission type. break; } // switch on VM status } // Receive