launch_daemon: Check requirements before launching a job.

* They were only launched, but we didn't check if we can actually
  launch them.
This commit is contained in:
Axel Dörfler
2015-11-28 14:00:01 +01:00
parent ea3e5d43d5
commit 236e68efdc
3 changed files with 70 additions and 13 deletions
+7 -2
View File
@@ -775,11 +775,13 @@ Events::ResetStickyExternalEvent(Event* event, const char* name)
/*! This will trigger a demand event, if it exists.
\param testOnly If \c true, the deman will not actually be triggered,
it will only be checked if it could.
\return \c true, if there is a demand event, and it has been
triggered by this call. \c false if not.
*/
/*static*/ bool
Events::TriggerDemand(Event* event)
Events::TriggerDemand(Event* event, bool testOnly)
{
if (event == NULL || event->Triggered())
return false;
@@ -789,11 +791,14 @@ Events::TriggerDemand(Event* event)
index++) {
Event* childEvent = container->Events().ItemAt(index);
if (dynamic_cast<DemandEvent*>(childEvent) != NULL) {
if (testOnly)
return true;
childEvent->Trigger();
break;
}
if (dynamic_cast<EventContainer*>(childEvent) != NULL) {
if (TriggerDemand(childEvent))
if (TriggerDemand(childEvent, testOnly))
break;
}
}
+1 -1
View File
@@ -62,7 +62,7 @@ public:
const char* name);
static void ResetStickyExternalEvent(Event* event,
const char* name);
static bool TriggerDemand(Event* event);
static bool TriggerDemand(Event* event, bool testOnly = false);
};
+62 -10
View File
@@ -184,7 +184,11 @@ private:
void _InitJobs(Target* target);
void _LaunchJobs(Target* target,
bool forceNow = false);
void _LaunchJob(Job* job, uint32 options = 0);
bool _CanLaunchJob(Job* job, uint32 options,
bool testOnly = false);
bool _CanLaunchJobRequirements(Job* job,
uint32 options);
bool _LaunchJob(Job* job, uint32 options = 0);
void _StopJob(Job* job, bool force);
void _AddTarget(Target* target);
void _SetCondition(BaseJob* job,
@@ -1428,6 +1432,45 @@ LaunchDaemon::_LaunchJobs(Target* target, bool forceNow)
}
/*! Checks whether or not the specified \a job can be launched.
If \a testOnly is \c false, calling this method will trigger a demand
to the \a job.
*/
bool
LaunchDaemon::_CanLaunchJob(Job* job, uint32 options, bool testOnly)
{
if (job == NULL || !job->CanBeLaunched())
return false;
return (options & FORCE_NOW) != 0
|| (job->EventHasTriggered() && job->CheckCondition(*this)
&& ((options & TRIGGER_DEMAND) == 0
|| Events::TriggerDemand(job->Event(), testOnly)));
}
/*! Checks recursively if the requirements of the specified job can be launched,
if they are not running already.
Calling this method will not trigger a demand for the requirements.
*/
bool
LaunchDaemon::_CanLaunchJobRequirements(Job* job, uint32 options)
{
int32 count = job->Requirements().CountStrings();
for (int32 index = 0; index < count; index++) {
Job* requirement = FindJob(job->Requirements().StringAt(index));
if (requirement != NULL
&& !requirement->IsRunning() && !requirement->IsLaunching()
&& (!_CanLaunchJob(requirement, options, true)
|| _CanLaunchJobRequirements(requirement, options))) {
return false;
}
}
return true;
}
/*! Adds the specified \a job to the launch queue
queue, except those that are triggered by events.
@@ -1437,24 +1480,30 @@ LaunchDaemon::_LaunchJobs(Target* target, bool forceNow)
Calling this method will trigger a demand event if \c TRIGGER_DEMAND has
been set.
*/
void
bool
LaunchDaemon::_LaunchJob(Job* job, uint32 options)
{
if (job == NULL || !job->CanBeLaunched()
|| ((options & FORCE_NOW) == 0
&& (!job->EventHasTriggered() || !job->CheckCondition(*this)
|| ((options & TRIGGER_DEMAND) != 0
&& Events::TriggerDemand(job->Event()))))) {
return;
}
if (job != NULL && (job->IsLaunching() || job->IsRunning()))
return true;
if (!_CanLaunchJob(job, options))
return false;
// Test if we can launch all requirements
if (!_CanLaunchJobRequirements(job, options | TRIGGER_DEMAND))
return false;
// Actually launch the requirements
int32 count = job->Requirements().CountStrings();
for (int32 index = 0; index < count; index++) {
Job* requirement = FindJob(job->Requirements().StringAt(index));
if (requirement != NULL) {
// TODO: For jobs that have their communication channels set up,
// we would not need to trigger demand at this point
_LaunchJob(requirement, TRIGGER_DEMAND);
if (!_LaunchJob(requirement, options | TRIGGER_DEMAND)) {
// Failed to put a requirement into the launch queue
return false;
}
}
}
@@ -1469,7 +1518,10 @@ LaunchDaemon::_LaunchJob(Job* job, uint32 options)
if (status != B_OK) {
debug_printf("Adding job %s to queue failed: %s\n", job->Name(),
strerror(status));
return false;
}
return true;
}