Added: #1440 Queue control

--HG--
branch : build_pipeline_v3
hg/feature/build_pipeline_v3
kaetemi 13 years ago
parent 49bfc5584b
commit 05b9119d72

@ -49,7 +49,7 @@ CBuildTaskQueue::CBuildTaskQueue() : m_QueueId(0)
CBuildTaskQueue::~CBuildTaskQueue() CBuildTaskQueue::~CBuildTaskQueue()
{ {
resetQueue();
} }
namespace { namespace {
@ -58,14 +58,15 @@ namespace {
} /* anonymous namespace */ } /* anonymous namespace */
void CBuildTaskQueue::loadQueue(CPipelineWorkspace *workspace) void CBuildTaskQueue::loadQueue(CPipelineWorkspace *workspace, bool bypassDependencyError)
{ {
m_Mutex.lock(); m_Mutex.lock();
nlassert(m_Tasks.empty()); nlassert(m_Tasks.empty());
++m_QueueId; ++m_QueueId;
m_BypassDependencyError = bypassDependencyError;
const std::map<std::string, CPipelineProject *> &projects = workspace->getProjects(); const std::map<std::string, CPipelineProject *> &projects = workspace->getProjects();
std::map<std::string, std::map<uint32, CBuildTaskInfo *> > builtTaskByProjectAndPlugin; std::map<std::string, std::map<uint32, CBuildTaskInfo *> > builtTaskByProjectAndPlugin;
for (std::map<std::string, CPipelineProject *>::const_iterator pr_it = projects.begin(), pr_end = projects.end(); pr_it != pr_end; ++pr_it) for (std::map<std::string, CPipelineProject *>::const_iterator pr_it = projects.begin(), pr_end = projects.end(); pr_it != pr_end; ++pr_it)
@ -123,30 +124,94 @@ CBuildTaskInfo *CBuildTaskQueue::getTaskInfo(uint32 taskId)
return m_Tasks[id.Sub.Task]; return m_Tasks[id.Sub.Task];
} }
CBuildTaskInfo *CBuildTaskQueue::getTaskForSlave(const std::vector<uint32> &availablePlugins, bool bypassDependencyError) CBuildTaskInfo *CBuildTaskQueue::getTaskForSlave(const std::vector<uint32> &availablePlugins)
{ {
m_Mutex.lock(); m_Mutex.lock();
std::vector<CBuildTaskId> availableTasks; std::vector<CBuildTaskInfo *> availableTasks;
createBuildableTaskList(availableTasks, bypassDependencyError); createBuildableTaskList(availableTasks, m_BypassDependencyError);
sortBuildableTaskListByMostDependents(availableTasks); sortBuildableTaskListByMostDependents(availableTasks);
for (std::vector<CBuildTaskId>::iterator it = availableTasks.begin(), end = availableTasks.end(); it != end; ++it) for (std::vector<CBuildTaskInfo *>::iterator it = availableTasks.begin(), end = availableTasks.end(); it != end; ++it)
{ {
CBuildTaskInfo *task = m_Tasks[(*it).Sub.Task]; CBuildTaskInfo *task = (*it);
if (find(availablePlugins.begin(), availablePlugins.end(), task->ProcessPluginId) != availablePlugins.end()) if (find(availablePlugins.begin(), availablePlugins.end(), task->ProcessPluginId) != availablePlugins.end())
{ {
task->State = TASK_WORKING;
m_Mutex.unlock(); m_Mutex.unlock();
return m_Tasks[(*it).Sub.Task]; return task;
} }
} }
m_Mutex.unlock(); m_Mutex.unlock();
return NULL; // no task available for slave. return NULL; // no task available for slave.
} }
uint CBuildTaskQueue::countRemainingBuildableTasks(bool bypassDependencyError) void CBuildTaskQueue::abortedTask(uint32 taskId)
{
m_Mutex.lock();
CBuildTaskInfo *info = getTaskInfo(taskId);
info->State = TASK_ABORTED;
m_Mutex.unlock();
}
void CBuildTaskQueue::rejectedTask(uint32 taskId)
{
m_Mutex.lock();
CBuildTaskInfo *info = getTaskInfo(taskId);
info->State = TASK_WAITING; // make available again
m_Mutex.unlock();
}
void CBuildTaskQueue::erroredTask(uint32 taskId)
{
m_Mutex.lock();
CBuildTaskInfo *info = getTaskInfo(taskId);
info->State = TASK_ERRORED;
m_Mutex.unlock();
}
void CBuildTaskQueue::successTask(uint32 taskId)
{
m_Mutex.lock();
CBuildTaskInfo *info = getTaskInfo(taskId);
info->State = TASK_SUCCESS;
m_Mutex.unlock();
}
void CBuildTaskQueue::abortQueue()
{
m_Mutex.lock();
for (std::vector<CBuildTaskInfo *>::iterator it = m_Tasks.begin(), end = m_Tasks.end(); it != end; ++it)
{
if ((*it)->State == TASK_WAITING)
(*it)->State = TASK_ABORTED;
}
m_Mutex.unlock();
}
void CBuildTaskQueue::resetQueue()
{ {
m_Mutex.lock(); m_Mutex.lock();
std::vector<CBuildTaskId> availableTasks;
createBuildableTaskList(availableTasks, bypassDependencyError); // count remaining and working first and assert its 0
std::vector<CBuildTaskInfo *> availableTasks;
createBuildableTaskList(availableTasks, m_BypassDependencyError);
uint nb = availableTasks.size();
for (std::vector<CBuildTaskInfo *>::iterator it = m_Tasks.begin(), end = m_Tasks.end(); it != end; ++it)
if ((*it)->State == TASK_WORKING)
++nb;
nlassert(nb == 0);
for (std::vector<CBuildTaskInfo *>::iterator it = m_Tasks.begin(), end = m_Tasks.end(); it != end; ++it)
delete (*it);
m_Tasks.clear();
m_Mutex.unlock();
}
uint CBuildTaskQueue::countRemainingBuildableTasks()
{
m_Mutex.lock();
std::vector<CBuildTaskInfo *> availableTasks;
createBuildableTaskList(availableTasks, m_BypassDependencyError);
m_Mutex.unlock(); m_Mutex.unlock();
return availableTasks.size(); return availableTasks.size();
} }
@ -162,11 +227,11 @@ uint CBuildTaskQueue::countWorkingTasks()
return nb; return nb;
} }
uint CBuildTaskQueue::countRemainingBuildableTasksAndWorkingTasks(bool bypassDependencyError) uint CBuildTaskQueue::countRemainingBuildableTasksAndWorkingTasks()
{ {
m_Mutex.lock(); m_Mutex.lock();
std::vector<CBuildTaskId> availableTasks; std::vector<CBuildTaskInfo *> availableTasks;
createBuildableTaskList(availableTasks, bypassDependencyError); createBuildableTaskList(availableTasks, m_BypassDependencyError);
uint nb = availableTasks.size(); uint nb = availableTasks.size();
for (std::vector<CBuildTaskInfo *>::iterator it = m_Tasks.begin(), end = m_Tasks.end(); it != end; ++it) for (std::vector<CBuildTaskInfo *>::iterator it = m_Tasks.begin(), end = m_Tasks.end(); it != end; ++it)
if ((*it)->State == TASK_WORKING) if ((*it)->State == TASK_WORKING)
@ -175,6 +240,14 @@ uint CBuildTaskQueue::countRemainingBuildableTasksAndWorkingTasks(bool bypassDep
return nb; return nb;
} }
void CBuildTaskQueue::listTaskQueueByMostDependents(std::vector<CBuildTaskInfo *> &result)
{
result.clear();
result.reserve(m_Tasks.size());
/*copy(m_Tasks.begin(), m_Tasks.end(), result);
sortBuildableTaskListByMostDependents(result);*/
}
void CBuildTaskQueue::countDependents(uint &dependentResult, CBuildTaskInfo *taskInfo) void CBuildTaskQueue::countDependents(uint &dependentResult, CBuildTaskInfo *taskInfo)
{ {
uint nb = 0; uint nb = 0;
@ -203,7 +276,7 @@ bool CBuildTaskQueue::doesTaskDependOnTask(CBuildTaskInfo *doesThisTask, CBuildT
return false; return false;
} }
void CBuildTaskQueue::createBuildableTaskList(std::vector<CBuildTaskId> &result, bool bypassError) void CBuildTaskQueue::createBuildableTaskList(std::vector<CBuildTaskInfo *> &result, bool bypassError)
{ {
// makes a list of tasks where all dependencies are ready // makes a list of tasks where all dependencies are ready
result.clear(); result.clear();
@ -219,7 +292,7 @@ void CBuildTaskQueue::createBuildableTaskList(std::vector<CBuildTaskId> &result,
if (((dependencyState == TASK_ERRORED) && !bypassError) if (((dependencyState == TASK_ERRORED) && !bypassError)
|| dependencyState == TASK_WAITING || dependencyState == TASK_WAITING
|| dependencyState == TASK_WORKING || dependencyState == TASK_WORKING
|| dependencyState == TASK_ABORTED) || (dependencyState == TASK_ABORTED && !bypassError))
{ {
ok = false; ok = false;
break; break;
@ -227,20 +300,20 @@ void CBuildTaskQueue::createBuildableTaskList(std::vector<CBuildTaskId> &result,
} }
if (ok) if (ok)
{ {
result.push_back((*it)->Id); result.push_back((*it));
} }
} }
} }
// sortBuildableTaskListByMostDependents(result); // sortBuildableTaskListByMostDependents(result);
} }
void CBuildTaskQueue::sortBuildableTaskListByMostDependents(std::vector<CBuildTaskId> &result) void CBuildTaskQueue::sortBuildableTaskListByMostDependents(std::vector<CBuildTaskInfo *> &result)
{ {
// brings most urgent tasks on top // brings most urgent tasks on top
std::vector<uint> dependentsCache; std::vector<uint> dependentsCache;
dependentsCache.resize(result.size()); dependentsCache.resize(result.size());
for (std::vector<uint>::size_type i = 0; i < dependentsCache.size(); ++i) for (std::vector<uint>::size_type i = 0; i < dependentsCache.size(); ++i)
countDependents(dependentsCache[i], m_Tasks[result[i].Sub.Task]); countDependents(dependentsCache[i], result[i]);
uint sc; uint sc;
do do
{ {

@ -91,23 +91,35 @@ protected:
boost::mutex m_Mutex; boost::mutex m_Mutex;
std::vector<CBuildTaskInfo *> m_Tasks; std::vector<CBuildTaskInfo *> m_Tasks;
bool m_BypassDependencyError;
public: public:
CBuildTaskQueue(); CBuildTaskQueue();
virtual ~CBuildTaskQueue(); virtual ~CBuildTaskQueue();
void loadQueue(CPipelineWorkspace *workspace); void loadQueue(CPipelineWorkspace *workspace, bool bypassDependencyError);
CBuildTaskInfo *getTaskInfo(uint32 taskId); CBuildTaskInfo *getTaskInfo(uint32 taskId);
CBuildTaskInfo *getTaskForSlave(const std::vector<uint32> &availablePlugins, bool bypassDependencyError); /// Gets task for slave, state is set to TASK_WORKING, returns NULL if none available
CBuildTaskInfo *getTaskForSlave(const std::vector<uint32> &availablePlugins);
void abortedTask(uint32 taskId);
void rejectedTask(uint32 taskId);
void erroredTask(uint32 taskId);
void successTask(uint32 taskId);
uint countRemainingBuildableTasks(bool bypassDependencyError); void abortQueue();
void resetQueue();
uint countRemainingBuildableTasks();
uint countWorkingTasks(); uint countWorkingTasks();
// when next are 0 the build should stop // when next are 0 the build should stop
uint countRemainingBuildableTasksAndWorkingTasks(bool bypassDependencyError); uint countRemainingBuildableTasksAndWorkingTasks();
// informational listing for sending initial task listing to terminals
void listTaskQueueByMostDependents(std::vector<CBuildTaskInfo *> &result);
private: private:
void countDependencies(uint &waitingResult, uint &failAbortResult, CBuildTaskInfo *taskInfo); // void countDependencies(uint &waitingResult, uint &failAbortResult, CBuildTaskInfo *taskInfo);
/// Recursively count the number of tasks that depend on this task. /// Recursively count the number of tasks that depend on this task.
void countDependents(uint &dependentResult, CBuildTaskInfo *taskInfo); void countDependents(uint &dependentResult, CBuildTaskInfo *taskInfo);
@ -115,8 +127,8 @@ private:
bool doesTaskDependOnTask(CBuildTaskInfo *doesThisTask, CBuildTaskInfo *dependOnThisTask); bool doesTaskDependOnTask(CBuildTaskInfo *doesThisTask, CBuildTaskInfo *dependOnThisTask);
void createBuildableTaskList(std::vector<CBuildTaskId> &result, bool bypassError); void createBuildableTaskList(std::vector<CBuildTaskInfo *> &result, bool bypassError);
void sortBuildableTaskListByMostDependents(std::vector<CBuildTaskId> &result); void sortBuildableTaskListByMostDependents(std::vector<CBuildTaskInfo *> &result);
}; /* class CBuildTaskQueue */ }; /* class CBuildTaskQueue */

Loading…
Cancel
Save