Fleshed out JobPool and ScannerPool. git-svn-id: https://svn.microneil.com/svn/SNF4CGP/trunk@11 59e8e3e7-56fa-483b-b4b4-fa6ab0af3dfcmaster
@@ -10,10 +10,19 @@ | |||
using namespace std; | |||
/**** this is wrong | |||
***** Creating the ExecutiveProcess will create the raw JobPool, WorkerPool, Input, and Output modules | |||
***** in an uninitialized state. They will then be initialized by these processes. This prevents the | |||
***** chicken-and-egg problem that happens when one two objects need to know about each other in order | |||
***** to operate properly. This means that each of these objects must have an init() and stop() method. | |||
****/ | |||
RuntimeCheck CheckJobPoolNotNull("ExecutiveProcess::initializeOutput() Check(0 != Jobs)"); | |||
RuntimeCheck CheckOutputProccessorWasConstructed("ExecutiveProcess::initializeOutput() Check(0 != Output)"); | |||
RuntimeCheck CheckOutputProcessorWasStarted("ExecutiveProcess::initializeOutput() Check(Output->isRunning())"); | |||
void ExecutiveProcess::initializeOutput() { | |||
CheckJobPoolNotNull(0 != Jobs); | |||
try { Output = new OutputProcessor(*Jobs); } catch(...) {} | |||
CheckOutputProcessorWasConstructed(0 != Output); | |||
try { Output->start() } catch(...) {} | |||
@@ -21,6 +30,7 @@ void ExecutiveProcess::initializeOutput() { | |||
} | |||
void ExecutiveProcess::initializeJobPool() { | |||
Jobs = new JobPool(ConfigInfo | |||
} | |||
void ExecutiveProcess::initializeWorkerPool() { |
@@ -23,10 +23,10 @@ class ExecutiveProcess { | |||
const string VersionInfo; // Knows Version and | |||
const string ConfigInfo; // Configuration. | |||
JobPool* Jobs; // Keeps pointers to the apps | |||
WorkerPool* Workers; // components so they can be | |||
InputProcessor* Input; // created, destroyed and | |||
OutputProcessor* Output; // connected together. | |||
JobPool Jobs; // Keeps pointers to the apps | |||
WorkerPool Workers; // components so they can be | |||
InputProcessor Input; // created, destroyed and | |||
OutputProcessor Output; // connected together. | |||
unsigned int QuitJobNumber; // Quit job number 0 until QUIT. | |||
@@ -1,3 +1,88 @@ | |||
// SNF4CGP/JobPool.hpp | |||
// Copyright (C) 2009 ARM Research Labs, LLC | |||
// See www.armresearch.com for more information. | |||
// | |||
// This module maintains a pool of SNF4CGP Jobs associated with the scanner pool | |||
// and is aware of the Output module. | |||
// | |||
// Job objects contain the "how to" for processing any command. They also provide | |||
// a handy place for all of the activity to be recoreded during the processing of | |||
// a Job and they preserve the buffer allocation for that in order to minimize | |||
// memory fragmentation and time spent allocating and deallocating memory. | |||
// | |||
// When a Job is requested one is returned from the pool or if none are | |||
// currently available in the pool an additional Job is allocated. | |||
// | |||
// Each Job object is assigned a command. Then (usually) a worker thread will call | |||
// the doIt() method to get the job done. | |||
// | |||
// When the Job is complete the last thing it does is hand itself off to the Output | |||
// module for processing and recycling -- just before it returns from doIt(). | |||
#ifndef IncludedJobPool | |||
#define IncludedJobPool | |||
#include "../SNF4CGP/SNFMulti/SNFMulti.hpp" | |||
#include "../SNF4CGP/CodeDweller/threading.hpp" | |||
#include "InputProcessor.hpp" | |||
#include "ScannerPool.hpp" | |||
#include <string> | |||
#include <vector> | |||
using namespace std; | |||
class Job { // SNF4CGP Job instance. | |||
private: | |||
ScannerPool& Scanners; // Knows where to get scanners. | |||
OutputProcessor& Output; | |||
Command CurrentCommand; // Has a current comand. | |||
string OutputBuffer; // Preserves an output buffer. | |||
vector<unsigned char> ReadBuffer; // Preserves a file read buffer. | |||
unsigned int ReadLength; // How much data in the buffer. | |||
//// These methods embody how we get jobs done. | |||
void doWakeUp(); | |||
void doINTF(); | |||
void doFAIL(); | |||
void doFILE(); | |||
void doRead(); | |||
void doScan(); | |||
void doAction(); | |||
void doBypass(); | |||
void doAllow(); | |||
void doReject(); | |||
void doDelete(); | |||
void doHold(); | |||
public: | |||
Job(ScannerPool& S, OutputProcessor O); // Construct with important links. | |||
~Job(); // Cleanup when destructing. | |||
void setCommand(Command C); // Assign a command for this job. | |||
void doIt(); // Get the job done. | |||
string& Output(); // Read the job's output. | |||
void clear(); // Cleanup for the next command. | |||
}; | |||
class JobPool { // Pool of SNF4CGP Jobs | |||
private: | |||
OutputProcessor* Output_; // Output processor (for job recycling) | |||
OutputProcessor& Output(); // Safe access to the Output Processor. | |||
ScannerPool* Scanners_; // Scanner Pool. | |||
ScannerPool& Scanners(); // Safe access to the Scanner Pool. | |||
Mutex myMutex; // Syncrhonization point. | |||
ProductionQueue<Job*> Jobs; // Recycled jobs holder. | |||
public: | |||
JobPool(); // Basic construction. | |||
~JobPool(); // Safe cleanup on destruction. | |||
init(string Configuration, OutputProcessor& O); // Get ready to allocate jobs. | |||
Job& grab(); // Get a fresh job object. | |||
void drop(Job& J); // Drop a used job object. | |||
stop(); // Shutdown and clean up. | |||
}; | |||
#endif |
@@ -4,19 +4,33 @@ | |||
#include "OutputProcessor.hpp" | |||
#include "../SNF4CGP/CodeDweller/faults.hpp" | |||
using namespace std; | |||
const ThreadType OutputProcessor::Type("Output Processor"); | |||
const ThreadState OutputProcessor::Uninitialized("Uninitialized"); | |||
const ThreadState OutputProcessor::StartingUp("Starting"); | |||
const ThreadState OutputProcessor::WaitingForJobs("Waiting"); | |||
const ThreadState OutputProcessor::PostingResponses("Posting"); | |||
const ThreadState OutputProcessor::ShuttingDown("Stopping"); | |||
OutputProcessor::OutputProcessor(JobPool& J) : // Constructor sets up the basics. | |||
OutputProcessor::OutputProcessor() : // Constructor sets up the basics. | |||
Thread(OutputProcessor::Type, "Output"), // Name the thread. | |||
RecycledJobs(J), // Tie in to the JobPool. | |||
RecycledJobs(0), // No job pool yet. | |||
isTimeToStop(false) {} // Not time to stop. | |||
OutputProcessor::~OutputProcessor() { // Destructor to clean things up. | |||
} | |||
void OutputProcessor::start() { // Start processing. | |||
RuntimeCheck CheckRecyclingNotNull("OutputProcessor::RecycledJobs() Check(0 != RecycledJobs_)"); | |||
JobPool& OutputProcessor::RecycledJobs() { // Safe access to RecycledJobs | |||
CheckRecyclingNotNull(0 != RecycledJobs_); // Throw if we have a null pointer. | |||
return *RecycledJobs_; // Good pointer? return a reference. | |||
} | |||
void OutputProcessor::init(JobPool& J) { // Start processing. | |||
} | |||
void OutputProcessor::outputJob(Job* J) { // Take this job and ... you know. |
@@ -18,7 +18,8 @@ | |||
class OutputProcessor : private Thread { // Process job outputs. | |||
private: | |||
JobPool& RecycledJobs; // Where we put our recycled jobs. | |||
JobPool* Jobs_; // Where we put our recycled jobs. | |||
JobPool& Jobs(); // Safe access to jobs pool. | |||
ProductionQueue<Job*> CompletedJobs; // Input queue for jobs to process. | |||
bool isTimeToStop; // Flag for when we need to stop. | |||
@@ -26,16 +27,19 @@ class OutputProcessor : private Thread { | |||
public: | |||
OutputProcessor(JobPool& J); // Constructed with the JobPool. | |||
OutputProcessor(); // Constructed with the JobPool. | |||
~OutputProcessor(); // Destructor to clean things up. | |||
void start(); // Start processing. | |||
void outputJob(Job* J); // Take this job and ... you know. | |||
void init(JobPool& J); // Start processing. | |||
void outputJob(Job& J); // Take this job and ... you know. | |||
void stop(); // Finish off the queue and quit. | |||
const static ThreadType Type; | |||
const static ThreadState Uninitialized; | |||
const static ThreadState StartingUp; | |||
const static ThreadState WaitingForJobs; | |||
const static ThreadState PostingResponses; | |||
const static ThreadState ShuttingDown; | |||
}; | |||
@@ -16,6 +16,8 @@ | |||
using namespace std; | |||
// Constructing a scanner is essentially constructing an snf_EngineHandler in a wrapper. | |||
class Scanner { // SNF Scanner instance for the pool | |||
private: | |||
snf_RulebaseHandler& Rulebase_; // Rulebase the scanner uses. | |||
@@ -30,15 +32,18 @@ class Scanner { | |||
class ScannerPool { // Pool of SNF Scanners | |||
private: | |||
snf_RulebaseHandler* Rulebase; // Allocates an SNF rulebase. | |||
snf_RulebaseHandler* Rulebase_; // Allocates an SNF rulebase. | |||
snf_RulebaseHandler& Rulebase(); // Safe access to the rulebase. | |||
unsigned int ScannerCount; // Allocates and counts scanners. | |||
ProductionQueue<Scanner*> PooledScanners; // Pool of ready-to-go scanners. | |||
public: | |||
ScannerPool(string Configuration); // Constructed with Rulebase config. | |||
ScannerPool(); // Constructed with Rulebase config. | |||
~ScannerPool(); // Cleans up when destroyed. | |||
Scanner* grab(); // Provides a Scanner from the pool. | |||
void drop(Scanner* S); // Returns a Scanner to the pool. | |||
init(string Configuration); // Get ready to provide scanners. | |||
stop(); // Shutdown and clean up. | |||
Scanner& grab(); // Provides a Scanner from the pool. | |||
void drop(Scanner& S); // Returns a Scanner to the pool. | |||
}; | |||
// Since Scanners are used for as short a time as possible it is usefule to have them | |||
@@ -56,9 +61,8 @@ class ScopeScanner { | |||
ScopeScanner(ScannerPool& P); // Grabs a scanner on construction. | |||
~ScopeScanner(); // Drops the scanner on destruction. | |||
snf_RulebaseHandler& Rulebase(); // Provides the same access as a | |||
snf_EngineHandler& Engine(); // Scanner object. | |||
} | |||
snf_RulebaseHandler& Rulebase(); // Provides safe access the Rulebase. | |||
snf_EngineHandler& Engine(); // Provides safe access to the Engine. | |||
}; | |||
#endif |