hashtable is much better for quick access in critical sections than iterating over a list of possibilities

This commit is contained in:
Aidan Hahn 2019-05-22 22:45:56 -07:00
parent 0433ead782
commit 7d90f1c87f
No known key found for this signature in database
GPG key ID: 327711E983899316

View file

@ -17,9 +17,8 @@ import java.util.concurrent.Future;
class ProcessManager { class ProcessManager {
// TODO: LOCK_TIMEOUT should be defined in a configuration management system // TODO: LOCK_TIMEOUT should be defined in a configuration management system
private final int LOCK_TIMEOUT = 5; // seconds private final int LOCK_TIMEOUT = 5; // seconds
private ArrayList<ProcessController> processQueue; private HashTable<int, ProcessController> processQueue;
private Boolean processQueueMutex = false; private Boolean processQueueMutex = false;
private Thread backgroundProcessCleaner;
private ExecutorService threadPool = Executors.newCachedThreadPool(); private ExecutorService threadPool = Executors.newCachedThreadPool();
private Callable<void> getLockCallable = new Callable<void>() { private Callable<void> getLockCallable = new Callable<void>() {
@ -37,12 +36,15 @@ class ProcessManager {
* initializes process queue and start the background process checking daemon * initializes process queue and start the background process checking daemon
*/ */
public ProcessManager() { public ProcessManager() {
processQueue = new ArrayList<ProcessController>(); processQueue = new HashTable<int, ProcessController>();
// TODO: In a long running server over a large period of time /* TODO: In a long running server over a large period of time
// It is possible that the streams used to redirect IO in the * It is possible that the streams used to redirect IO in the
// Processes may become a significant use of resources. * Processes may become a significant use of resources.
// In this case a background thread should be called to periodically * In this case a background thread should be called to periodically
// remove dead ProcessControllers after calling kill() on them. * remove dead ProcessControllers after calling kill() on them.
*
* (grab lock, iterate over map, remove processes that are done executing, store exit codes, release lock, sleep, repeat)
*/
} }
/* /*
@ -70,7 +72,7 @@ class ProcessManager {
} }
ProcessController newProc = ProcessController(command); ProcessController newProc = ProcessController(command);
this.processQueue.add(newProc); this.processes.map(newProc.getPid(), newProc);
// Exit critical section // Exit critical section
this.releaseLock(); this.releaseLock();
@ -87,6 +89,8 @@ class ProcessManager {
* 3: couldnt grab lock * 3: couldnt grab lock
*/ */
public int getProcessStatus(int pid) { public int getProcessStatus(int pid) {
int status;
// Enter critical section // Enter critical section
try { try {
this.getLock(); this.getLock();
@ -98,12 +102,11 @@ class ProcessManager {
return 3; return 3;
} }
for (ProcessController iter : this.processQueue) { ProcessController candidate = this.processMap.get(pid);
if (iter.getPid() == pid) { if (candidate != null) {
status = candidate.getStatus();
this.releaseLock(); this.releaseLock();
// release lock on finding process return status;
return iter.getStatus();
}
} }
// process must not exist // process must not exist
@ -118,6 +121,8 @@ class ProcessManager {
* a 258 if process doesnt exist. * a 258 if process doesnt exist.
*/ */
public int getProcessReturn(int pid) { public int getProcessReturn(int pid) {
int ret;
// Enter Critical section // Enter Critical section
try { try {
this.getLock(); this.getLock();
@ -128,11 +133,11 @@ class ProcessManager {
return 257; return 257;
} }
for (ProcessController iter : this.processQueue) { ProcessController candidate = this.processMap.get(pid);
if (iter.getPid() == pid) { if (candidate != null) {
ret = candidate.getReturn();
this.releaseLock(); this.releaseLock();
return iter.getReturn(); return ret;
}
} }
this.releaseLock(); this.releaseLock();
@ -145,6 +150,8 @@ class ProcessManager {
* or returns description of error * or returns description of error
*/ */
public String getProcessOutput(int pid) { public String getProcessOutput(int pid) {
String output;
try { try {
this.getLock(); this.getLock();
@ -154,13 +161,12 @@ class ProcessManager {
return "[-] ERROR: Timeout grabbing lock to access process information"; return "[-] ERROR: Timeout grabbing lock to access process information";
} }
for (ProcessController iter : this.processQueue) { ProcessController candidate = this.processMap.get(pid);
if (iter.getPid() == pid) { if (candidate != null) {
output = iter.getOutput(); output = iter.getOutput();
this.releaseLock(); this.releaseLock();
return output; return output;
} }
}
this.releaseLock(); this.releaseLock();
return "[-] ERROR: Process not found" return "[-] ERROR: Process not found"
@ -180,42 +186,15 @@ class ProcessManager {
return false; return false;
} }
for (ProcessController iter : this.processQueue) { ProcessController candidate = this.processMap.get(pid);
if (iter.getPid() == pid) { if (candidate != null) {
iter.kill(); candidate.kill();
break;
}
} }
this.releaseLock(); this.releaseLock();
return true; return true;
} }
/*
* cleanProcessQueue()
* represents a background thread that sits and cleans finished processes
*/
private void cleanProcessQueue() {
while(true){
try {
this.getLock();
} catch (TimeoutException e) {
continue;
}
for (ProcessController iter : this.processQueue) {
if(!iter.getStatus()) {
iter.kill();
this.processQueue.remove(iter);
}
}
this.releaseLock();
Thread.sleep(5000);
}
}
/* /*
* getLock() * getLock()
* Locks access to this.processQueue * Locks access to this.processQueue