-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJobManager.cpp
executable file
·217 lines (166 loc) · 5.98 KB
/
JobManager.cpp
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
/* file: JobManager.cpp
Job Manager Class Implementation File
==================================================
Wimpy Shell Project - Com Sci 342
Shea Daniels
This class manages and keeps track of all the background
jobs that are being run. It is in charge of starting,
managing the status of, and waiting for all of the
background jobs spawned by the shell. Each background
job is represented by an instance of the BackJob class.
*/
#include "JobManager.h"
/******************************************************
This is the basic constructor for the class.
POST: No jobs have been created yet. Job counters
set to zero.
*/
JobManager::JobManager() {
// no jobs yet
num_running = 0;
num_finished = 0;
}
/******************************************************
Creates and tries to execute as a background job
the command the user passes.
PRE: new_command must be a parsed Command object.
POST: If the job starts successfully, it is added to
the jobs vector as a running job and the running
jobs counter is increased by one. Otherwise, it
is recorded as failed in the jobs vector.
*/
void JobManager::createBackgroundJob(Command new_command) {
// create new background job
jobs.push_back(BackJob(new_command));
// try to run job, if successful
if (jobs[jobs.size()-1].execute())
num_running++;
}
/******************************************************
Tries to suspend the process until the background
job specified by the int job_num has finished
executing.
PRE: job_num is an integer.
POST: Returns true after the background process is
finished. Returns false if the job number
specified by the user doesn't correspond
to a running process or if an error was
encountered.
*/
bool JobManager::waitForJob(int job_num) {
int job_index = noToVec(job_num);
// assume job number given is not running
bool valid_job = false;
// validate job number
if (!(job_index >= jobs.size())) {
if (jobs[job_index].isRunning()) {
valid_job = true;
}
}
// wait for job
if (valid_job) {
bool success = jobs[job_index].waitForMe();
if (success) {
num_running--;
num_finished++;
}
return success;
}
// still here, so job_num was invalid
cout << "Could not wait for job:" << endl;
cout << " Invalid job number." << endl;
return false;
}
/******************************************************
Checks for all background jobs that have finished
executing and updates their status.
POST: All finished jobs are set to finished.
*/
void JobManager::updateJobStatus() {
// linux system call to get a terminated child
int finished_pid = waitpid(-1, NULL, WNOHANG);
// update until no terminated children left
while ((finished_pid != -1) && (finished_pid != 0)) {
// update job in vector to "finished" status
for (int updateCtr = 0; updateCtr < jobs.size(); updateCtr++) {
if (finished_pid == jobs[updateCtr].getPid()) {
jobs[updateCtr].setFinished(true);
num_running--;
num_finished++;
}
}
// system call again
finished_pid = waitpid(-1, NULL, WNOHANG);
}
// check if something nasty happend
if ((finished_pid == -1) && (errno != 10)) { // errno 10 is "no children found"
cout << "Background process update error: pid " << finished_pid << endl;
cout << " " << strerror(errno) << "." << endl;
}
}
/******************************************************
Prints to standard out all of the running and
recently finished jobs.
POST: All running and finished jobs are printed.
*/
void JobManager::printJobs() {
// print all running jobs
if (num_running > 0) {
cout << " Running:" << endl;
for (int runCtr = 0; runCtr < jobs.size(); runCtr++) {
if (jobs[runCtr].isRunning()) {
cout << " [" << vecToNo(runCtr) << "] " << jobs[runCtr].getCommand().getCommandText() << endl;
}
}
}
// print all finished jobs
if (num_finished > 0) {
cout << " Finished:" << endl;
for (int finCtr = 0; finCtr < jobs.size(); finCtr++) {
if (jobs[finCtr].isFinished()) {
cout << " [" << vecToNo(finCtr) << "] " << jobs[finCtr].getCommand().getCommandText() << endl;
}
}
}
}
/******************************************************
Clears out all recently finished background jobs.
If no jobs are running and there is nothing left
to display to the user, the job history is cleaned
out. (next new background job will have a job # of 1)
POST: All finished jobs are set to terminated. If no
jobs are left running or set to be displayed,
the jobs vector is cleared.
*/
void JobManager::clearOldJobs() {
// go through vector and set all "finshed" jobs to "terminated"
for (int termCtr = 0; termCtr < jobs.size(); termCtr++) {
if(jobs[termCtr].isFinished()) {
jobs[termCtr].setTerminated(true);
num_finished--;
}
}
// clear out vector if all info is old
if ((num_running == 0) && (num_finished == 0)) {
jobs.clear();
}
}
/******************************************************
Converts a job number into a vector index.
PRE: job_num is an integer.
POST: Returns the vector index of that job number.
*/
int JobManager::noToVec(int job_num) {
int vec_index = job_num - 1;
return vec_index;
}
/******************************************************
Converts a vector index into a job number.
PRE: vec_index is an integer.
POST: Returns the job number corresponding to the
passed index.
*/
int JobManager::vecToNo(int vec_index) {
int job_num = vec_index + 1;
return job_num;
}