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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user