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.
|
/*! 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
|
\return \c true, if there is a demand event, and it has been
|
||||||
triggered by this call. \c false if not.
|
triggered by this call. \c false if not.
|
||||||
*/
|
*/
|
||||||
/*static*/ bool
|
/*static*/ bool
|
||||||
Events::TriggerDemand(Event* event)
|
Events::TriggerDemand(Event* event, bool testOnly)
|
||||||
{
|
{
|
||||||
if (event == NULL || event->Triggered())
|
if (event == NULL || event->Triggered())
|
||||||
return false;
|
return false;
|
||||||
@@ -789,11 +791,14 @@ Events::TriggerDemand(Event* event)
|
|||||||
index++) {
|
index++) {
|
||||||
Event* childEvent = container->Events().ItemAt(index);
|
Event* childEvent = container->Events().ItemAt(index);
|
||||||
if (dynamic_cast<DemandEvent*>(childEvent) != NULL) {
|
if (dynamic_cast<DemandEvent*>(childEvent) != NULL) {
|
||||||
|
if (testOnly)
|
||||||
|
return true;
|
||||||
|
|
||||||
childEvent->Trigger();
|
childEvent->Trigger();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (dynamic_cast<EventContainer*>(childEvent) != NULL) {
|
if (dynamic_cast<EventContainer*>(childEvent) != NULL) {
|
||||||
if (TriggerDemand(childEvent))
|
if (TriggerDemand(childEvent, testOnly))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public:
|
|||||||
const char* name);
|
const char* name);
|
||||||
static void ResetStickyExternalEvent(Event* event,
|
static void ResetStickyExternalEvent(Event* event,
|
||||||
const char* name);
|
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 _InitJobs(Target* target);
|
||||||
void _LaunchJobs(Target* target,
|
void _LaunchJobs(Target* target,
|
||||||
bool forceNow = false);
|
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 _StopJob(Job* job, bool force);
|
||||||
void _AddTarget(Target* target);
|
void _AddTarget(Target* target);
|
||||||
void _SetCondition(BaseJob* job,
|
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
|
/*! Adds the specified \a job to the launch queue
|
||||||
queue, except those that are triggered by events.
|
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
|
Calling this method will trigger a demand event if \c TRIGGER_DEMAND has
|
||||||
been set.
|
been set.
|
||||||
*/
|
*/
|
||||||
void
|
bool
|
||||||
LaunchDaemon::_LaunchJob(Job* job, uint32 options)
|
LaunchDaemon::_LaunchJob(Job* job, uint32 options)
|
||||||
{
|
{
|
||||||
if (job == NULL || !job->CanBeLaunched()
|
if (job != NULL && (job->IsLaunching() || job->IsRunning()))
|
||||||
|| ((options & FORCE_NOW) == 0
|
return true;
|
||||||
&& (!job->EventHasTriggered() || !job->CheckCondition(*this)
|
|
||||||
|| ((options & TRIGGER_DEMAND) != 0
|
|
||||||
&& Events::TriggerDemand(job->Event()))))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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();
|
int32 count = job->Requirements().CountStrings();
|
||||||
for (int32 index = 0; index < count; index++) {
|
for (int32 index = 0; index < count; index++) {
|
||||||
Job* requirement = FindJob(job->Requirements().StringAt(index));
|
Job* requirement = FindJob(job->Requirements().StringAt(index));
|
||||||
if (requirement != NULL) {
|
if (requirement != NULL) {
|
||||||
// TODO: For jobs that have their communication channels set up,
|
// TODO: For jobs that have their communication channels set up,
|
||||||
// we would not need to trigger demand at this point
|
// 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) {
|
if (status != B_OK) {
|
||||||
debug_printf("Adding job %s to queue failed: %s\n", job->Name(),
|
debug_printf("Adding job %s to queue failed: %s\n", job->Name(),
|
||||||
strerror(status));
|
strerror(status));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user