Fleshed out JobPool and ScannerPool. git-svn-id: https://svn.microneil.com/svn/SNF4CGP/trunk@11 59e8e3e7-56fa-483b-b4b4-fa6ab0af3dfcmaster
using namespace std; | 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 CheckOutputProccessorWasConstructed("ExecutiveProcess::initializeOutput() Check(0 != Output)"); | ||||
RuntimeCheck CheckOutputProcessorWasStarted("ExecutiveProcess::initializeOutput() Check(Output->isRunning())"); | RuntimeCheck CheckOutputProcessorWasStarted("ExecutiveProcess::initializeOutput() Check(Output->isRunning())"); | ||||
void ExecutiveProcess::initializeOutput() { | void ExecutiveProcess::initializeOutput() { | ||||
CheckJobPoolNotNull(0 != Jobs); | |||||
try { Output = new OutputProcessor(*Jobs); } catch(...) {} | try { Output = new OutputProcessor(*Jobs); } catch(...) {} | ||||
CheckOutputProcessorWasConstructed(0 != Output); | CheckOutputProcessorWasConstructed(0 != Output); | ||||
try { Output->start() } catch(...) {} | try { Output->start() } catch(...) {} | ||||
} | } | ||||
void ExecutiveProcess::initializeJobPool() { | void ExecutiveProcess::initializeJobPool() { | ||||
Jobs = new JobPool(ConfigInfo | |||||
} | } | ||||
void ExecutiveProcess::initializeWorkerPool() { | void ExecutiveProcess::initializeWorkerPool() { |
const string VersionInfo; // Knows Version and | const string VersionInfo; // Knows Version and | ||||
const string ConfigInfo; // Configuration. | 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. | unsigned int QuitJobNumber; // Quit job number 0 until QUIT. | ||||
// SNF4CGP/JobPool.hpp | // SNF4CGP/JobPool.hpp | ||||
// Copyright (C) 2009 ARM Research Labs, LLC | // Copyright (C) 2009 ARM Research Labs, LLC | ||||
// See www.armresearch.com for more information. | // 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 |
#include "OutputProcessor.hpp" | #include "OutputProcessor.hpp" | ||||
#include "../SNF4CGP/CodeDweller/faults.hpp" | |||||
using namespace std; | |||||
const ThreadType OutputProcessor::Type("Output Processor"); | const ThreadType OutputProcessor::Type("Output Processor"); | ||||
const ThreadState OutputProcessor::Uninitialized("Uninitialized"); | |||||
const ThreadState OutputProcessor::StartingUp("Starting"); | |||||
const ThreadState OutputProcessor::WaitingForJobs("Waiting"); | const ThreadState OutputProcessor::WaitingForJobs("Waiting"); | ||||
const ThreadState OutputProcessor::PostingResponses("Posting"); | 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. | 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. | isTimeToStop(false) {} // Not time to stop. | ||||
OutputProcessor::~OutputProcessor() { // Destructor to clean things up. | 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. | void OutputProcessor::outputJob(Job* J) { // Take this job and ... you know. |
class OutputProcessor : private Thread { // Process job outputs. | class OutputProcessor : private Thread { // Process job outputs. | ||||
private: | 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. | ProductionQueue<Job*> CompletedJobs; // Input queue for jobs to process. | ||||
bool isTimeToStop; // Flag for when we need to stop. | bool isTimeToStop; // Flag for when we need to stop. | ||||
public: | public: | ||||
OutputProcessor(JobPool& J); // Constructed with the JobPool. | |||||
OutputProcessor(); // Constructed with the JobPool. | |||||
~OutputProcessor(); // Destructor to clean things up. | ~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. | void stop(); // Finish off the queue and quit. | ||||
const static ThreadType Type; | const static ThreadType Type; | ||||
const static ThreadState Uninitialized; | |||||
const static ThreadState StartingUp; | |||||
const static ThreadState WaitingForJobs; | const static ThreadState WaitingForJobs; | ||||
const static ThreadState PostingResponses; | const static ThreadState PostingResponses; | ||||
const static ThreadState ShuttingDown; | |||||
}; | }; | ||||
using namespace std; | using namespace std; | ||||
// Constructing a scanner is essentially constructing an snf_EngineHandler in a wrapper. | |||||
class Scanner { // SNF Scanner instance for the pool | class Scanner { // SNF Scanner instance for the pool | ||||
private: | private: | ||||
snf_RulebaseHandler& Rulebase_; // Rulebase the scanner uses. | snf_RulebaseHandler& Rulebase_; // Rulebase the scanner uses. | ||||
class ScannerPool { // Pool of SNF Scanners | class ScannerPool { // Pool of SNF Scanners | ||||
private: | 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. | unsigned int ScannerCount; // Allocates and counts scanners. | ||||
ProductionQueue<Scanner*> PooledScanners; // Pool of ready-to-go scanners. | ProductionQueue<Scanner*> PooledScanners; // Pool of ready-to-go scanners. | ||||
public: | public: | ||||
ScannerPool(string Configuration); // Constructed with Rulebase config. | |||||
ScannerPool(); // Constructed with Rulebase config. | |||||
~ScannerPool(); // Cleans up when destroyed. | ~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 | // Since Scanners are used for as short a time as possible it is usefule to have them | ||||
ScopeScanner(ScannerPool& P); // Grabs a scanner on construction. | ScopeScanner(ScannerPool& P); // Grabs a scanner on construction. | ||||
~ScopeScanner(); // Drops the scanner on destruction. | ~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 | #endif |