dependency management implemented -- this should be polished later to say the task name in the exception message. last feature to implement is logging.
parent
c92be3f4be
commit
5f85185e8d
|
@ -1,4 +1,5 @@
|
||||||
{
|
{
|
||||||
"units_path": "/home/phanes/development/internal/Examplar/conf/units/all_test.units",
|
"units_path": "/home/phanes/development/internal/Examplar/conf/units/all_test.units",
|
||||||
"plan_path": "/home/phanes/development/internal/Examplar/conf/plans/test.plan"
|
"plan_path": "/home/phanes/development/internal/Examplar/conf/plans/test.plan",
|
||||||
|
"config_version": "1"
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
"plan": [
|
"plan": [
|
||||||
{ "name": "independent test 1", "dependencies": [ null ] },
|
{ "name": "independent test 1", "dependencies": [ null ] },
|
||||||
{ "name": "independent test 2", "dependencies": [ null ] },
|
{ "name": "independent test 2", "dependencies": [ null ] },
|
||||||
{ "name": "dependent test", "dependencies": [ "independent test 1", null, null ] }
|
{ "name": "dependent test", "dependencies": [ "independent test 1" ] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
"target": "/usr/bin/false",
|
"target": "/usr/bin/false",
|
||||||
"rectifier": "/usr/bin/true",
|
"rectifier": "/usr/bin/true",
|
||||||
"active": true,
|
"active": true,
|
||||||
"required": true,
|
"required": false,
|
||||||
"rectify": true
|
"rectify": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "independent test 2",
|
"name": "independent test 2",
|
||||||
"target": "/usr/bin/false",
|
"target": "/usr/bin/true",
|
||||||
"rectifier": "/usr/bin/false",
|
"rectifier": "/usr/bin/true",
|
||||||
"active": true,
|
"active": true,
|
||||||
"required": false,
|
"required": false,
|
||||||
"rectify": false
|
"rectify": false
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "dependent test",
|
"name": "dependent test",
|
||||||
"target": "ssh root@phanes.silogroup.org",
|
"target": "/usr/bin/true",
|
||||||
"rectifier": "/usr/bin/false",
|
"rectifier": "/usr/bin/false",
|
||||||
"active": true,
|
"active": true,
|
||||||
"required": false,
|
"required": false,
|
||||||
|
|
|
@ -11,6 +11,14 @@ class Plan_InvalidTaskName: public std::runtime_error { public:
|
||||||
Plan_InvalidTaskName(): std::runtime_error("Plan: Attempted to access a Task using an invalid name.") {}
|
Plan_InvalidTaskName(): std::runtime_error("Plan: Attempted to access a Task using an invalid name.") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// Plan_Task_Missing_Dependency - Exception thrown when a Plan tries to access a contained Task's value by name not present
|
||||||
|
/// in the Unit.
|
||||||
|
class Plan_Task_Missing_Dependency: public std::runtime_error { public:
|
||||||
|
Plan_Task_Missing_Dependency(): std::runtime_error("Plan: Attempted to execute a task that had unmet dependencies.") {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Plan::Plan() - Constructor for Plan class. A Plan is a managed container for a Task vector. These tasks reference
|
/// Plan::Plan() - Constructor for Plan class. A Plan is a managed container for a Task vector. These tasks reference
|
||||||
/// Units that are defined in the Units files (Suite). If Units are definitions, Tasks are selections of those
|
/// Units that are defined in the Units files (Suite). If Units are definitions, Tasks are selections of those
|
||||||
/// definitions to execute, and if Units together form a Suite, Tasks together form a Plan.
|
/// definitions to execute, and if Units together form a Suite, Tasks together form a Plan.
|
||||||
|
@ -53,7 +61,7 @@ void Plan::load_plan_file(std::string filename, bool verbose)
|
||||||
/// \param result - The variable receiving the value.
|
/// \param result - The variable receiving the value.
|
||||||
/// \param index - The numerical index in the Task vector to retrieve a value for.
|
/// \param index - The numerical index in the Task vector to retrieve a value for.
|
||||||
/// \param verbose - Whether to print verbose output to STDOUT.
|
/// \param verbose - Whether to print verbose output to STDOUT.
|
||||||
void Plan::get_task(Task & result, int index, bool verbose)
|
void Plan::get_task(Task & result, int index )
|
||||||
{
|
{
|
||||||
if ( index <= this->tasks.size() )
|
if ( index <= this->tasks.size() )
|
||||||
{
|
{
|
||||||
|
@ -63,30 +71,6 @@ void Plan::get_task(Task & result, int index, bool verbose)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Plan::get_task - Retrieves a task by name.
|
|
||||||
///
|
|
||||||
/// \param result - The variable receiving the value.
|
|
||||||
/// \param provided_name - The name to find a task by.
|
|
||||||
/// \param verbose - Whether to print verbose output to STDOUT.
|
|
||||||
void Plan::get_task(Task & result, std::string provided_name, bool verbose)
|
|
||||||
{
|
|
||||||
bool foundMatch = false;
|
|
||||||
|
|
||||||
for ( int i = 0; i < this->tasks.size(); i++ )
|
|
||||||
{
|
|
||||||
if ( this->tasks[i].get_name() == provided_name )
|
|
||||||
{
|
|
||||||
result = this->tasks[i];
|
|
||||||
foundMatch = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (! foundMatch )
|
|
||||||
{
|
|
||||||
std::cerr << "Task name \"" << provided_name << "\" was referenced but not defined!" << std::endl;
|
|
||||||
throw Plan_InvalidTaskName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Plan::load_definitions - Load the units corresponding to each task in plan from the given Suite.
|
/// Plan::load_definitions - Load the units corresponding to each task in plan from the given Suite.
|
||||||
///
|
///
|
||||||
|
@ -108,6 +92,63 @@ void Plan::load_definitions( Suite unit_definitions, bool verbose )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Plan::get_task - Retrieves a task by name.
|
||||||
|
///
|
||||||
|
/// \param result - The variable receiving the value.
|
||||||
|
/// \param provided_name - The name to find a task by.
|
||||||
|
/// \param verbose - Whether to print verbose output to STDOUT.
|
||||||
|
void Plan::get_task(Task & result, std::string provided_name )
|
||||||
|
{
|
||||||
|
bool foundMatch = false;
|
||||||
|
|
||||||
|
for ( int i = 0; i < this->tasks.size(); i++ )
|
||||||
|
{
|
||||||
|
if ( this->tasks[i].get_name() == provided_name )
|
||||||
|
{
|
||||||
|
result = this->tasks[i];
|
||||||
|
foundMatch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! foundMatch )
|
||||||
|
{
|
||||||
|
std::cerr << "Task name \"" << provided_name << "\" was referenced but not defined!" << std::endl;
|
||||||
|
throw Plan_InvalidTaskName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO dependency check goes here
|
||||||
|
// This should check to see if there are unmet dependencies.
|
||||||
|
// done -- add a "completed" attribute to Task
|
||||||
|
// Iterate through Task::dependencies, a vector attached to tasks[i] containing task names
|
||||||
|
// use Plan::get_task( name ) method to retrieve that task
|
||||||
|
// check if it is in a ready state
|
||||||
|
// return ready/not ready
|
||||||
|
bool Plan::all_dependencies_complete(std::string name)
|
||||||
|
{
|
||||||
|
// get the task by name
|
||||||
|
Task named_task;
|
||||||
|
this->get_task( named_task, name );
|
||||||
|
|
||||||
|
// get the dependencies of that task
|
||||||
|
std::vector<std::string> deps = named_task.get_dependencies();
|
||||||
|
|
||||||
|
// create an empty task to assign values to during iteration
|
||||||
|
Task tmpTask;
|
||||||
|
// iterate through its dependencies
|
||||||
|
for ( int i = 0; i < deps.size(); i++ )
|
||||||
|
{
|
||||||
|
this->get_task( tmpTask, deps[i]);
|
||||||
|
if (! tmpTask.is_complete() )
|
||||||
|
{
|
||||||
|
// error message?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// Plan::execute() - Iterates through all tasks in a plan and executes them.
|
/// Plan::execute() - Iterates through all tasks in a plan and executes them.
|
||||||
///
|
///
|
||||||
/// \param verbose
|
/// \param verbose
|
||||||
|
@ -116,15 +157,17 @@ void Plan::execute( bool verbose )
|
||||||
// for each task in this plan
|
// for each task in this plan
|
||||||
for ( int i = 0; i < this->tasks.size(); i++ )
|
for ( int i = 0; i < this->tasks.size(); i++ )
|
||||||
{
|
{
|
||||||
if ( verbose ) {
|
if (this->all_dependencies_complete(this->tasks[i].get_name()) )
|
||||||
std::cout << "Executing task \"" << this->tasks[i].get_name() << "\"." << std::endl;
|
{
|
||||||
// std::cout << "Executing task \"" << this->tasks[0].get_name() << "\"." << std::endl;
|
if ( verbose )
|
||||||
|
{
|
||||||
|
std::cout << "Executing task \"" << this->tasks[i].get_name() << "\"." << std::endl;
|
||||||
|
}
|
||||||
|
this->tasks[i].execute( verbose );
|
||||||
|
} else {
|
||||||
|
throw Plan_Task_Missing_Dependency();
|
||||||
|
// not all deps met for this task
|
||||||
}
|
}
|
||||||
this->tasks[i].execute( verbose );
|
|
||||||
// this->tasks[0].execute( verbose );
|
|
||||||
|
|
||||||
// for testing a logic issue in Task.execute(), remove when done
|
|
||||||
// throw Plan_InvalidTaskIndex();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,10 @@ class Plan: public JSON_Loader
|
||||||
void load_plan_file( std::string filename, bool verbose );
|
void load_plan_file( std::string filename, bool verbose );
|
||||||
|
|
||||||
// fetch a task from this->tasks
|
// fetch a task from this->tasks
|
||||||
void get_task( Task & result, std::string provided_name, bool verbose );
|
void get_task( Task & result, std::string provided_name );
|
||||||
|
|
||||||
// fetch a task from this->tasks
|
// fetch a task from this->tasks
|
||||||
void get_task( Task & result, int index, bool verbose );
|
void get_task( Task & result, int index );
|
||||||
|
|
||||||
// load unit definitions from a provided suite and import them into individual tasks
|
// load unit definitions from a provided suite and import them into individual tasks
|
||||||
void load_definitions( Suite unit_definitions, bool verbose );
|
void load_definitions( Suite unit_definitions, bool verbose );
|
||||||
|
@ -32,6 +32,8 @@ class Plan: public JSON_Loader
|
||||||
|
|
||||||
// execute all tasks in this plan
|
// execute all tasks in this plan
|
||||||
void execute( bool verbose );
|
void execute( bool verbose );
|
||||||
|
|
||||||
|
bool all_dependencies_complete(std::string name);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FTESTS_PLAN_H
|
#endif //FTESTS_PLAN_H
|
||||||
|
|
|
@ -91,6 +91,20 @@ bool Task::is_complete()
|
||||||
return this->complete;
|
return this->complete;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Task::mark_complete - Marks the task complete..
|
||||||
|
void Task::mark_complete()
|
||||||
|
{
|
||||||
|
this->complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Task::get_dependencies - returns a pointer to the dependencies vector.
|
||||||
|
std::vector<std::string> Task::get_dependencies()
|
||||||
|
{
|
||||||
|
return this->dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
/// Task::has_definition - Indicator if the task has attached its definition from a Suite.
|
/// Task::has_definition - Indicator if the task has attached its definition from a Suite.
|
||||||
bool Task::has_definition()
|
bool Task::has_definition()
|
||||||
{
|
{
|
||||||
|
@ -102,10 +116,10 @@ bool Task::has_definition()
|
||||||
/// \param verbose - Verbosity level - not implemented yet.
|
/// \param verbose - Verbosity level - not implemented yet.
|
||||||
void Task::execute( bool verbose )
|
void Task::execute( bool verbose )
|
||||||
{
|
{
|
||||||
// DUFFING
|
// DUFFING - If Examplar is broken it's probably going to be in this block.
|
||||||
|
|
||||||
// PREWORK
|
// PREWORK
|
||||||
// throw if unit not coupled to all necessary values since Task is stateful (stateful is okay)
|
// throw if unit not coupled to all necessary values since Task is stateful (yes, stateful is okay)
|
||||||
if (! this->has_definition() ) {
|
if (! this->has_definition() ) {
|
||||||
throw Task_NotReady();
|
throw Task_NotReady();
|
||||||
}
|
}
|
||||||
|
@ -133,6 +147,7 @@ void Task::execute( bool verbose )
|
||||||
if ( verbose ) {
|
if ( verbose ) {
|
||||||
std::cout << "\tTarget " << task_name << " succeeded." << std::endl;
|
std::cout << "\tTarget " << task_name << " succeeded." << std::endl;
|
||||||
}
|
}
|
||||||
|
this->mark_complete();
|
||||||
// next
|
// next
|
||||||
} else {
|
} else {
|
||||||
// Non-Zero d[0] from initial target execution, get to d[1]
|
// Non-Zero d[0] from initial target execution, get to d[1]
|
||||||
|
|
|
@ -42,6 +42,11 @@ class Task
|
||||||
|
|
||||||
// execute this task's definition
|
// execute this task's definition
|
||||||
void execute( bool verbose );
|
void execute( bool verbose );
|
||||||
|
|
||||||
|
void mark_complete();
|
||||||
|
|
||||||
|
// returns a pointer to the dependencies vector
|
||||||
|
std::vector<std::string> get_dependencies();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FTESTS_TASK_H
|
#endif //FTESTS_TASK_H
|
||||||
|
|
Loading…
Reference in New Issue