summaryrefslogtreecommitdiff
path: root/Simulator/include/Simulator.h
blob: d0828dcd90ffbb3f62585d81e4772d536be6258d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once
#include "simulation/Section.h"
#include "database/Database.h"

#include <iostream>
#include <unordered_map>

namespace Simulation
{
	/*
		The Simulator class controls (the creation of) all experiments, and providing access to the database.
	*/
	class Simulator
	{
	public:
		/*
			Initializes the simulator with an empty list of experiments, and with a reference to the database.
		*/
		explicit Simulator(char* databaseName) : database(databaseName) {}

		/*
			Adds a simulation to the list of experiments from the database, removing it from the queue
			of experiments in the database.
		*/
		void load(int experimentId)
		{
			Experiment experiment = database.createExperiment(experimentId);
			experiments.insert(std::make_pair(experimentId, experiment));
			database.dequeueExperiment(experimentId);
		}

		/*
			Polls the database for new jobs and simulates every queued simulation it finds.
		*/
		void pollAndLoadAll()
		{
			int rc = pollAndLoad();
			if (rc != -1)
				pollAndLoadAll();
		}

		/*
			Polls the database for new jobs and simulates the first it finds.
		*/
		int pollAndLoad()
		{
			int id = database.pollQueuedExperiments();
			if (id != -1)
			{
				std::cout << "Loaded simulation section " << id << std::endl;
				load(id);
			}
			return id;
		}

		/*
			Writes the state of all experiments if their history is size 3000 or larger.
		*/
		void writeHistoryAll()
		{
			if (experiments.size() == 0)
				return;

			auto it = experiments.begin();
			while(it != experiments.end())
			{
				auto& history = (*it).second.getHistory();
				if (history.historySize() > 3000 || (*it).second.isFinished())
					write((*it).first);

				if ((*it).second.isFinished())
				{
					std::cout << "Finished simulation." << std::endl;
					database.finishExperiment((*it).first);
					it = experiments.erase(it);
				}
				else
				{
					++it;
				}
			}
		}

		/*
			Writes the state of the given simulation to the database.
		*/
		void write(int id)
		{
			std::cout << "Writing batch." << std::endl;
			database.startTransaction();
			database.writeExperimentHistory(experiments.at(id));
			database.endTransaction();
			auto history = experiments.at(id).getHistory();
			history.clearHistory();
			std::cout << "Finished writing batch." << std::endl;
		}
		
		/*
			Ticks each simulation once.
		*/
		void tickAll()
		{
			for (std::pair<const int, Experiment>& s : experiments)
				s.second.tick();
		}

		/*
			Ticks the given simulation once.
		*/
		void tick(int simulationId)
		{
			experiments.at(simulationId).tick();
		}

		/*
			Returns true if all experiments are finished.
		*/
		bool hasSimulations() const
		{
			return experiments.size() != 0;
		}

		/*
			Saves the state of all workloads to the history.
		*/
		void saveStateAll()
		{
			for (auto& pair : experiments)
				pair.second.saveState();
		}

	private:
		// The database to write results to.
		Database::Database database;

		// The list of experiments.
		std::unordered_map<int, Experiment> experiments;
	};
}