-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathController.java
More file actions
319 lines (256 loc) · 10.3 KB
/
Controller.java
File metadata and controls
319 lines (256 loc) · 10.3 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
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import java.util.*;
/*************************************************************
* The Virtual Memory Management Manager a.k.a Controller
* Sends messages to the tables with any new updates dictacted
* by the file input.
* Points the GUI to the right tables to update its contents.
* @author Gloire Rubambiza
* @since 11/22/2017
**************************************************************/
public class Controller implements ActionListener {
/** The GUI to be displayed. */
private SystemGUI gui;
/** The table object that holds the frame and page table. */
private Tables table;
/** The Queue of inputs read from the file. */
private Queue<Integer[]> input;
/** The buttons for handling user actions. */
private JButton next, runf, runc, exit;
/** The array of action buttons. */
private JButton [] userActionBtns;
/*************************************************
* Instantiates the tables, GUI, and buttons to be
* used for user actions.
*************************************************/
public Controller (SystemGUI pGUI, Tables pTable, Queue<Integer[]> pInput) {
gui = pGUI;
table = pTable;
input = pInput;
userActionBtns = gui.sendButtons();
next = userActionBtns[0];
runf = userActionBtns[1];
runc = userActionBtns[2];
exit = userActionBtns[3];
addCommandListeners();
}
/*******************************************
* Adds the action listeners for the buttons.
********************************************/
private void addCommandListeners() {
next.addActionListener(this);
runf.addActionListener(this);
runc.addActionListener(this);
exit.addActionListener(this);
}
/**********************************************
* Instructs the GUI to display the latest page
* table for a given process.
* @param pid is the PID of the process.
**********************************************/
public void updatePageTable (int pid) {
gui.displayPageTable(table.passProcessTable(pid), pid);
}
/**************************************************
* Instructs the GUI to display the latest state of
* the frame table i.e. physical memory.
* @param fault color the frame based on fault kind.
* @param frame is the frame that needs coloring.
*************************************************/
public void updateFrameTable (boolean fault, int frame) {
gui.displayFrameTable(table.passFrameTable(), fault, frame);
}
/*********************************************
* Instructs the GUI to display the latest page
* reference for a given process.
* @param pid is the PID of the process.
* @param ref is the page that was referenced.
**********************************************/
public void updateReference (int pid, int ref) {
gui.displayReference(pid, ref);
}
/*******************************************
* Instructs the GUI to display final stats.
*******************************************/
public void updateStats () {
gui.displayStats(table.passPCBArray());
}
/********************************************************************
* Pops input from the queue to be read when the user presses next.
* Tells the controller whether the read caused a page fault.
* Otherwise the LRU Queue is updated with the least recently
* used frame if the page is already in memory.
* @param queue is the input queue.
* @return 1 if we're done reading input, -1 if there was a page
* fault, 0 if the page was already in memory.
*******************************************************************/
private int readNext ( Queue<Integer[]> myQ ) {
// Check if we have input.
Integer [] pair = new Integer[2];
if ( ( pair = myQ.poll() ) == null ) { // Error checking
return 1; // Input is done.
}
// Send the input to check for a page fault.
int procNum = pair[0];
int page = pair[1];
if ( isFault(procNum, page) ) {
return -1; // Page fault occured.
} else {
return 0;
}
}
/*****************************************************************
* Handles the given input and takes care of page faults as needed.
* @param procNum is the processing reading in a page.
* @param pageNum is the page being read.
* @return true if the update caused a page fault, false otherwise.
*****************************************************************/
private boolean isFault ( int procNum, int pageNum ) {
// Check if there is a free frame.
int freeFrame;
if ( table.checkPageInTable( procNum, pageNum) ) { // Check in memory
// Handles the case of a page being already in memory.
this.handlePageInMemory(procNum, pageNum);
// The page is in memory. No page fault.
return false;
} else if ( (freeFrame = table.checkFreeFrame()) >= 0 ) {
// Handles the case of a page fault with free frames available.
this.handleFreeFrameAvailable(procNum, pageNum, freeFrame);
// The page is not in memory. It's a page fault, but we have free frames.
return true;
} else { // We actually have to kick a process' page out of memory.
// Handles the case of a page fault with replacement.
this.handlePageReplacement(procNum, pageNum);
// The page is not in memory. It's a page fault, a replacement occured.
return true;
}
}
/****************************************************
* Handles the case of a page already being in memory
* after the input is read.
* @param pid is the PID of the process.
* @param page is the page already in memory.
*****************************************************/
private void handlePageInMemory( int pid, int page ) {
// Update the referenced page on the GUI.
this.updateReference(pid, page);
// Update the reference count.
table.updateProcessRefCount(pid);
// Search which frame is associated with the process/page pair.
int frameOfInterest = (table.searchAssociatedFrame(pid, page))[0];
// Add the reference frame to LRU Queue as a replacement candidate.
table.addCandidateFrame(frameOfInterest);
// Display the page table for the process of interest.
this.updatePageTable(pid);
}
/****************************************************
* Handles the case of a page fault with free frames
* being available.
* @param pid is the PID of the process.
* @param page is the page already in memory.
* @param freeFrame is the frame that is available.
*****************************************************/
private void handleFreeFrameAvailable( int pid, int page, int freeFrame ) {
// Update the referenced page on the GUI.
this.updateReference(pid, page);
// Update all the tables with the right info regarding the page fault.
table.updateProcessFaultCount(pid);
table.updateProcessRefCount(pid);
table.updateFrameTable(freeFrame, pid, page);
table.updatePageTable(false, pid, page, freeFrame);
// Add the reference frame to LRU Queue as a replacement candidate.
table.addCandidateFrame(freeFrame);
// Display the page table for the process of interest.
this.updatePageTable(pid);
// Display the frame table with the new updates.
this.updateFrameTable(false, -1);
}
/****************************************************
* Handles the case of replacing a page when a page fault
* occurs and there are no free frame availables.
* Picks a victim and updates the tables accordingly.
* @param procNum is the PID of the process.
* @param pageNum is the page already in memory.
*****************************************************/
private void handlePageReplacement( int procNum, int pageNum ) {
// Update the referenced page on the GUI.
this.updateReference(procNum, pageNum);
// Increment reference and fault counts for the process.
table.updateProcessFaultCount(procNum);
table.updateProcessRefCount(procNum);
// Find a victim.
int [] victimInfo = table.pickVictim();
int victimFrame = victimInfo[0];
// Notify the GUI that a victim was picked.
this.notifyGUI(victimInfo);
// Send the victim a message to update their page table.
int [] replacementPair = table.searchVictimPair(victimFrame);
int pid = replacementPair[0];
int page = replacementPair[1];
table.updatePageTable(true, pid, page, victimFrame);
// Send a message to the replacing process to update their page table.
table.updatePageTable(false, procNum, pageNum, victimFrame);
// Update the frame table.
table.updateFrameTable(victimFrame, procNum, pageNum);
// Add the reference frame to LRU Queue as a replacement candidate.
table.addCandidateFrame(victimFrame);
// Update the page/frame table on the GUI.
this.updatePageTable(procNum);
this.updateFrameTable(true, victimFrame);
}
/***************************************************
* Notifies the GUI that a page replacement occured.
* GUI Updates who was the victim on the replacement.
* @param vic is info about the victim that was picked.
****************************************************/
public void notifyGUI( int [] vic ) {
gui.displayVictim(vic);
}
/******************************************************
* Disables all the buttons when the input is done.
* @param btns is the collection of user action buttons.
*******************************************************/
private void disableButtons( JButton[] btns ) {
int i;
for ( i = 0; i < 3; i++ ) {
btns[i].setEnabled(false);
}
}
@Override
public void actionPerformed(ActionEvent e) {
// Get the source of event;
JButton click = (JButton) e.getSource();
if ( click.equals(next) ) {
int check = this.readNext(input);
if ( check > 0 ) { // Inputs are done, deactivate buttons
this.updateStats();
this.disableButtons(userActionBtns);
}
} else if ( click.equals(runf) ) {
int check;
// Keep reading until we're done with input or a page fault occurs.
while ( ( check = this.readNext(input)) >= 0 ) {
if (check < 0 ) {
break;
} else if ( check > 0 ) { // Input ended while searching for page fault.
this.updateStats();
this.disableButtons(userActionBtns);
break;
}
}
} else if ( click.equals(runc) ) {
int check;
while ( ( check = this.readNext(input)) > -2 ) {
if ( check == 1 ){
this.updateStats();
this.disableButtons(userActionBtns);
break;
}
}
} else if ( click.equals(exit) ) {
System.exit(0);
}
}
}