-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackupMain.h
More file actions
378 lines (342 loc) · 16 KB
/
backupMain.h
File metadata and controls
378 lines (342 loc) · 16 KB
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
/*
Adam Nelson-Archer (2140122)
COSC 3336
Programming Assignment 1
to compile this code:
use
*/
// enable this to get detailed output logs like the output files:
bool verboseLog = false;
//
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
#include <map>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
struct Process {
int PID; // Process ID number
float TimeCompletion; // Time completion or arrival time
string Instruction; // Type of instruction
int NumLogReads = 0; // Number of logical reads
int NumPhyWrites = 0; // Number of physical writes
int NumPhyReads = 0; // Number of physical reads
int BufferSize = 0; // Buffer size, initially 0
};
struct Input {
string command;
float time;
};
struct ProcessEntry {
int PID;
int StartLine = 0; // Also starting at 0
int EndLine = -1; // Initialized to -1 to adjust for 0-based indexing
int CurrentLine = -1;
int State = 0; // 0 = null, 1 = running, 2 = ready, 3 = blocked
};
// Comparator for the priority queue (min heap based on TimeCompletion)
struct ProcessCompare {
bool operator()(const Process& a, const Process& b) {
return a.TimeCompletion > b.TimeCompletion;
}
};
// global variables & queues
int BSIZE = 0;
priority_queue<Process, vector<Process>, ProcessCompare> MainQueue; // Priority Queue of Processes
queue<Process> SQ; // SSD
queue<Process> RQ; // CPU Queue
bool CpuIsEmpty = true;
bool SSDisEmpty = true;
float ClockTime = 0;
int handleBuffer(int bytesNeeded, int curBSIZE);
void Arrival(const Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable);
void CoreRequest(Process& process, vector<ProcessEntry>& pTable, const vector<Input>& inputTable);
void SSDRequest(Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable);
void CoreCompletion(Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable);
void SSDCompletion(Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable);
vector<Input> processInputFileToTable(const string& fileName, vector<ProcessEntry>& processTable) {
ifstream file(fileName);
string line;
int starts = 0;
vector<Input> inputTable;
int lineCounter = 0;
bool newProcess = false;
ProcessEntry currentProcess;
while (getline(file, line)) {
istringstream iss(line);
Input input;
iss >> input.command >> input.time;
inputTable.push_back(input); // Populate the input table
if(input.command == "BSIZE")
BSIZE = input.time;
if (input.command == "START") {
if (newProcess) { // If already in a process, finalize it
currentProcess.EndLine = lineCounter - 1;
processTable.push_back(currentProcess);
}
newProcess = true;
currentProcess = ProcessEntry(); // Start a new process entry
currentProcess.PID = starts; // Increment PID for new process
starts ++;
currentProcess.StartLine = lineCounter;
}
currentProcess.EndLine = lineCounter; // Update as we go
lineCounter++; // Increment lineCounter after processing the line
}
// Add the last process if it exists
if (newProcess) {
processTable.push_back(currentProcess);
}
return inputTable;
}
void printInputTable(const vector<Input>& table) {
cout << "Index Com. Time/Value" << endl;
for (size_t i = 0; i < table.size(); i++) {
cout << i << " " << table[i].command << " " << table[i].time << endl;
}
}
void printProcessTable(const vector<ProcessEntry>& table) {
cout << "PID; Start Line; End Line; Current Line; State;" << endl;
for (const auto& entry : table) {
cout << entry.PID << "; " << entry.StartLine << "; " << entry.EndLine << "; "
<< entry.CurrentLine << "; " << entry.State << ";" << endl;
}
}
void printMainQueue() {
cout << "Main Queue Contents:" << endl;
while (!MainQueue.empty()) {
Process process = MainQueue.top();
MainQueue.pop();
cout << "Process " << process.PID << ":" << endl;
cout << " Time Completion: " << process.TimeCompletion << endl;
cout << " Instruction: " << process.Instruction << endl;
cout << " NumLogReads: " << process.NumLogReads << endl;
cout << " NumPhyWrites: " << process.NumPhyWrites << endl;
cout << " NumPhyReads: " << process.NumPhyReads << endl;
cout << " BufferSize: " << process.BufferSize << endl;
}
}
int main() {
const string fileName = "input10.txt";
vector<ProcessEntry> processTable;
vector<Input> inputTable = processInputFileToTable(fileName, processTable);
if(verboseLog){
cout << "Input Table:" << endl;
printInputTable(inputTable);
cout << "\nProcess Table:" << endl;
printProcessTable(processTable);
cout << "\n";
}
for (const auto& entry : processTable) {
// Retrieve the start line index of the process entry
int startLineIndex = entry.StartLine;
string command = inputTable[startLineIndex].command;
float time = inputTable[startLineIndex].time;
Process process;
process.PID = entry.PID;
process.TimeCompletion = time;
process.Instruction = command;
MainQueue.push(process);
}
// Main simulation loop
while (!MainQueue.empty()) {
if(verboseLog) cout << "main queue entered, looking at top process. It is: ";
Process currentProcess = MainQueue.top();
MainQueue.pop();
if(verboseLog) cout << currentProcess.PID << " " << currentProcess.Instruction << endl;
if (currentProcess.TimeCompletion > ClockTime) {
ClockTime = currentProcess.TimeCompletion;
}
if (currentProcess.Instruction == "START") {
Arrival(currentProcess, processTable, inputTable);
} else if (currentProcess.Instruction == "CORE") {
CoreCompletion(currentProcess, processTable, inputTable);
} else {
SSDCompletion(currentProcess, processTable, inputTable);
}
}
return 0;
}
int handleBuffer(int bytesNeeded, int curBSIZE) {
if(verboseLog) cout << "\nhandle buffer called. Bytes needed: " << bytesNeeded << " Current Buffer Size: " << curBSIZE << endl;
int finalBufferSize;
if (bytesNeeded <= curBSIZE) {
finalBufferSize = curBSIZE - bytesNeeded;
} else {
int bytesMissing = bytesNeeded - curBSIZE;
int bytesBrought;
if (bytesMissing % BSIZE == 0) {
bytesBrought = bytesMissing;
} else {
bytesBrought = ((bytesMissing / BSIZE) + 1) * BSIZE;
}
finalBufferSize = curBSIZE + bytesBrought - bytesNeeded;
}
if(verboseLog) cout << "Final buffer size: " << finalBufferSize << endl << endl;
return finalBufferSize;
}
void Arrival(const Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable) {
// Update the current line of the process entry in the process table
processTable[process.PID].CurrentLine = processTable[process.PID].StartLine + 1;
string command = inputTable[processTable[process.PID].CurrentLine].command;
float time = inputTable[processTable[process.PID].CurrentLine].time;
if(verboseLog) cout << "arrival command/time : " << command << " " << time << endl;
// Update the process with the new command and time
Process updatedProcess = process;
updatedProcess.Instruction = command;
updatedProcess.TimeCompletion = time;
// Call the Core Request function with the updated process and process table
CoreRequest(updatedProcess, processTable, inputTable);
}
void CoreRequest(Process& process, vector<ProcessEntry>& pTable, const vector<Input>& inputTable) {
if(verboseLog) cout << "CoreRequest called with " << process.PID << " " << process.Instruction << endl;
// process.PID is used to find the corresponding entry in pTable
int pidIndex = -1;
for (size_t i = 0; i < pTable.size(); ++i) {
if (pTable[i].PID == process.PID) {
pidIndex = static_cast<int>(i);
break;
}
}
// [A] If the CORE is empty
if (CpuIsEmpty) {
if(verboseLog) cout << "CPU empty, process " << process.PID << " is moved to the CPU(main) queue" << endl;
CpuIsEmpty = false; // Set the CPU to full
pTable[pidIndex].State = 1; // Change pTable status to Running
if(verboseLog) cout << "\n\n process.TimeCompletion: " << process.TimeCompletion << "\n\n";
float operationDuration = process.TimeCompletion; // Duration of the CORE operation
process.TimeCompletion = ClockTime + operationDuration; // Scheduling completion
MainQueue.push(process);
}
// [B] If the Core is Full
else {
if(verboseLog) cout << "CPU full, process " << process.PID << " is moved to the ready queue" << endl;
pTable[pidIndex].State = 2; // Change the status of the event to ready
RQ.push(process);
}
}
void SSDRequest(Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable) {
if(verboseLog) cout << "SSDRequest reached with " << process.PID << " " << process.Instruction << endl;
float ssdOperationDuration = 0.1; // Fixed duration for SSD operations
if (process.Instruction == "READ") {
// Determine if read is physical or logical
if (inputTable[processTable[process.PID].CurrentLine].time >= process.BufferSize) {
//physical read, get from buffer, increase curBSIZE
if(verboseLog) cout << "physical read, push to main queue or SSD queue if SSD full\n" << endl;
if (SSDisEmpty) {
process.BufferSize = handleBuffer(inputTable[processTable[process.PID].CurrentLine].time, process.BufferSize);
process.TimeCompletion = ClockTime + ssdOperationDuration;
process.NumPhyReads++;
SSDisEmpty = false;
MainQueue.push(process); // Directly process as SSD is empty
} else {
SQ.push(process); // SSD is full, push to SSD queue
}
} else {
// Logical Read, remove read bits from curBSIZE
if(verboseLog) cout << "logical read, core request called for next command\n" << endl;
process.NumLogReads++;
process.BufferSize = handleBuffer(inputTable[processTable[process.PID].CurrentLine].time, process.BufferSize);
// these lines are just for moving to the next index
processTable[process.PID].CurrentLine++;
string command = inputTable[processTable[process.PID].CurrentLine].command;
float time = inputTable[processTable[process.PID].CurrentLine].time;
process.TimeCompletion = time;
process.Instruction = command;
//
CoreRequest(process, processTable, inputTable);
}
} else if (process.Instruction == "WRITE") {
// Writes are always physical
if(verboseLog) cout << "physical write, push to main queue or SSD queue if SSD full\n";
if (SSDisEmpty) {
if(verboseLog) cout << "pushed to main queue\n" << endl;
process.NumPhyWrites++;
process.TimeCompletion = ClockTime + ssdOperationDuration;
SSDisEmpty = false; // Mark SSD as in use
MainQueue.push(process); // Directly process as SSD is empty
} else {
if(verboseLog) cout << "pushed to SSD queue\n" << endl;
SQ.push(process); // SSD is full, push to SSD queue
}
}
}
void CoreCompletion(Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable) {
if(verboseLog){
cout << "\nCore Completion called with " << process.PID << " " << process.Instruction << endl;
cout << "process info-- " << "GLOBAL clock time: " << ClockTime << " " << "completion time: " << process.TimeCompletion << endl;
cout << "logReads: " << process.NumLogReads << " phyReads: " << process.NumPhyReads << " phyWrites: " << process.NumPhyWrites << "\n";
}
CpuIsEmpty = true; // Set the Core to empty
if (!RQ.empty()) {
if(verboseLog) cout << "there is a process inthe SSD queue, sending to CoreRequest" << endl;
// If RQ is not empty, schedule the next process waiting in RQ
Process nextProcess = RQ.front();
if(verboseLog) cout << "waiting process: " << nextProcess.PID << " " << nextProcess.Instruction << endl << endl;
RQ.pop();
CoreRequest(nextProcess, processTable, inputTable);
}
// Retrieve the process entry from the process table
auto& entry = processTable[process.PID]; // Assuming direct access by PID for simplicity
if(verboseLog) cout << "entry data: " << entry.PID << " " << entry.StartLine << " " << entry.EndLine << endl;
if (entry.CurrentLine == entry.EndLine) {
// If End Line == Current Line, we terminate the process
//update to state 4 for terminated, print num of writes and reads
entry.State = 4;
cout << "\nProcess " << process.PID << " terminates at " << ClockTime << " ms" << endl;
cout << "physical reads: [" << process.NumPhyReads << "] logical reads: [" << process.NumLogReads << "] physical writes: [" << process.NumPhyWrites << "]" << endl;
//print each process and its state
cout << "--------------" << endl;
cout << "Process Table:" << endl;
map<int, string> stateMap = {
{0, "Null"},
{1, "Running"},
{2, "Ready"},
{3, "Blocked"},
{4, "Terminated"}
};
for (const auto& entry : processTable) {
cout << "Process " << entry.PID << ": " << stateMap[entry.State] << endl;
}
if(verboseLog) cout << "\n";
return;
} else {
// Increment the current line by 1 for the next instruction
processTable[process.PID].CurrentLine++;
string command = inputTable[processTable[process.PID].CurrentLine].command;
float time = inputTable[processTable[process.PID].CurrentLine].time;
process.TimeCompletion = time;
process.Instruction = command;
if(verboseLog) cout << "process instruction:: " << process.Instruction << " and time: " << process.TimeCompletion << endl;
if (process.Instruction == "READ" || process.Instruction == "WRITE") {
if(verboseLog) cout << "write or read was taken, go to ssd request\n\n" << endl;
SSDRequest(process, processTable, inputTable);
} else if (process.Instruction == "INPUT" || process.Instruction == "DISPLAY") {
if(verboseLog) cout << "I/O, push to mainqueue" << endl;
if(verboseLog) cout << "time duration for I/O operation: " << process.TimeCompletion << endl << endl;
process.TimeCompletion = ClockTime + process.TimeCompletion;
MainQueue.push(process);
}
}
}
void SSDCompletion(Process& process, vector<ProcessEntry>& processTable, const vector<Input>& inputTable) {
if(verboseLog) cout << "SSD Completion reached with " << process.PID << " " << process.Instruction << endl;
SSDisEmpty = true; // Mark the SSD as empty
if (!SQ.empty()) { // If there is a process waiting in the SSD queue
if(verboseLog) cout << "there is a process in the SSD queue, sending to SSD request" << endl;
Process nextProcess = SQ.front();
SQ.pop();
if(verboseLog) cout << "waiting process: " << nextProcess.PID << " " << nextProcess.Instruction << endl << endl;
SSDRequest(nextProcess, processTable, inputTable); // Send the next process to the SSD request function
}
// proceed with the completed process's next command
processTable[process.PID].CurrentLine++;
string command = inputTable[processTable[process.PID].CurrentLine].command;
float time = inputTable[processTable[process.PID].CurrentLine].time;
process.TimeCompletion = time;
process.Instruction = command;
CoreRequest(process, processTable, inputTable); // Send the process to the Core request function
}