launch_daemon: Jobs were started before their target.
* A job must not be launched when its target hasn't been launched yet. This fixes Tracker launching when the mount_server scanned the initial disk, even though the FirstBootPrompt was showing. * Jobs are no longer initialized when their target has not been launched yet. This also means that you cannot talk to a service beforehand in this case. * Slight refactoring and clarifying, even added some documentation :-) * _TriggerJob() is now called _LaunchJob(), and does all the checks for jobs that _LaunchJobs() does now for targets.
This commit is contained in:
@@ -93,10 +93,15 @@ BaseJob::SetEvent(::Event* event)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Determines whether the events of this job has been triggered
|
||||||
|
already or not.
|
||||||
|
Note, if this job does not have any events, this method returns
|
||||||
|
\c true.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
BaseJob::EventHasTriggered() const
|
BaseJob::EventHasTriggered() const
|
||||||
{
|
{
|
||||||
return Event() != NULL && Event()->Triggered();
|
return Event() == NULL || Event()->Triggered();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
const ::Condition* Condition() const;
|
const ::Condition* Condition() const;
|
||||||
::Condition* Condition();
|
::Condition* Condition();
|
||||||
void SetCondition(::Condition* condition);
|
void SetCondition(::Condition* condition);
|
||||||
bool CheckCondition(ConditionContext& context) const;
|
virtual bool CheckCondition(ConditionContext& context) const;
|
||||||
|
|
||||||
const ::Event* Event() const;
|
const ::Event* Event() const;
|
||||||
::Event* Event();
|
::Event* Event();
|
||||||
|
|||||||
@@ -539,10 +539,15 @@ Events::TriggerRegisteredEvent(Event* event, const char* name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! This will trigger a demand event, if it exists.
|
||||||
|
|
||||||
|
\return \c true, if there is a demand event, and it has been
|
||||||
|
triggered by this call. \c false if not.
|
||||||
|
*/
|
||||||
/*static*/ bool
|
/*static*/ bool
|
||||||
Events::TriggerDemand(Event* event)
|
Events::TriggerDemand(Event* event)
|
||||||
{
|
{
|
||||||
if (event == NULL)
|
if (event == NULL || event->Triggered())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (EventContainer* container = dynamic_cast<EventContainer*>(event)) {
|
if (EventContainer* container = dynamic_cast<EventContainer*>(event)) {
|
||||||
@@ -551,7 +556,7 @@ Events::TriggerDemand(Event* event)
|
|||||||
Event* childEvent = container->Events().ItemAt(index);
|
Event* childEvent = container->Events().ItemAt(index);
|
||||||
if (dynamic_cast<DemandEvent*>(childEvent) != NULL) {
|
if (dynamic_cast<DemandEvent*>(childEvent) != NULL) {
|
||||||
childEvent->Trigger();
|
childEvent->Trigger();
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
if (dynamic_cast<EventContainer*>(childEvent) != NULL) {
|
if (dynamic_cast<EventContainer*>(childEvent) != NULL) {
|
||||||
if (TriggerDemand(childEvent))
|
if (TriggerDemand(childEvent))
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ Job::Job(const Job& other)
|
|||||||
fTarget(other.Target())
|
fTarget(other.Target())
|
||||||
{
|
{
|
||||||
fCondition = other.fCondition;
|
fCondition = other.fCondition;
|
||||||
|
// TODO: copy events
|
||||||
|
//fEvent = other.fEvent;
|
||||||
|
fEnvironment = other.fEnvironment;
|
||||||
|
fSourceFiles = other.fSourceFiles;
|
||||||
|
|
||||||
for (int32 i = 0; i < other.Arguments().CountStrings(); i++)
|
for (int32 i = 0; i < other.Arguments().CountStrings(); i++)
|
||||||
AddArgument(other.Arguments().StringAt(i));
|
AddArgument(other.Arguments().StringAt(i));
|
||||||
@@ -172,6 +176,16 @@ Job::AddRequirement(const char* requirement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
Job::CheckCondition(ConditionContext& context) const
|
||||||
|
{
|
||||||
|
if (Target() != NULL && !Target()->HasLaunched())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return BaseJob::CheckCondition(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Job::Init(const Finder& finder, std::set<BString>& dependencies)
|
Job::Init(const Finder& finder, std::set<BString>& dependencies)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ public:
|
|||||||
BStringList& Requirements();
|
BStringList& Requirements();
|
||||||
void AddRequirement(const char* requirement);
|
void AddRequirement(const char* requirement);
|
||||||
|
|
||||||
|
virtual bool CheckCondition(ConditionContext& context) const;
|
||||||
|
|
||||||
status_t Init(const Finder& jobs,
|
status_t Init(const Finder& jobs,
|
||||||
std::set<BString>& dependencies);
|
std::set<BString>& dependencies);
|
||||||
status_t InitCheck() const;
|
status_t InitCheck() const;
|
||||||
|
|||||||
@@ -134,10 +134,10 @@ private:
|
|||||||
const char* name);
|
const char* name);
|
||||||
void _AddJob(Target* target, bool service,
|
void _AddJob(Target* target, bool service,
|
||||||
BMessage& message);
|
BMessage& message);
|
||||||
void _InitJobs();
|
void _InitJobs(Target* target);
|
||||||
void _LaunchJobs(Target* target);
|
void _LaunchJobs(Target* target,
|
||||||
void _TriggerJob(Job* job);
|
bool forceNow = false);
|
||||||
void _AddLaunchJob(Job* job);
|
void _LaunchJob(Job* job, bool forceNow = false);
|
||||||
void _AddTarget(Target* target);
|
void _AddTarget(Target* target);
|
||||||
void _SetCondition(BaseJob* job,
|
void _SetCondition(BaseJob* job,
|
||||||
const BMessage& message);
|
const BMessage& message);
|
||||||
@@ -361,7 +361,7 @@ LaunchDaemon::ReadyToRun()
|
|||||||
fUserMode ? B_FIND_PATHS_USER_ONLY : B_FIND_PATHS_SYSTEM_ONLY, paths);
|
fUserMode ? B_FIND_PATHS_USER_ONLY : B_FIND_PATHS_SYSTEM_ONLY, paths);
|
||||||
_ReadPaths(paths);
|
_ReadPaths(paths);
|
||||||
|
|
||||||
_InitJobs();
|
_InitJobs(NULL);
|
||||||
_LaunchJobs(NULL);
|
_LaunchJobs(NULL);
|
||||||
|
|
||||||
// Launch run targets (ignores events)
|
// Launch run targets (ignores events)
|
||||||
@@ -414,13 +414,13 @@ LaunchDaemon::MessageReceived(BMessage* message)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
Job* job = FindJob(name);
|
Job* job = FindJob(name);
|
||||||
if (job != NULL && job->EventHasTriggered()) {
|
if (job != NULL) {
|
||||||
_TriggerJob(job);
|
_LaunchJob(job);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Target* target = FindTarget(name);
|
Target* target = FindTarget(name);
|
||||||
if (target != NULL && target->EventHasTriggered()) {
|
if (target != NULL) {
|
||||||
_LaunchJobs(target);
|
_LaunchJobs(target);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -442,7 +442,7 @@ LaunchDaemon::_HandleGetLaunchData(BMessage* message)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
BMessage reply((uint32)B_OK);
|
BMessage reply((uint32)B_OK);
|
||||||
bool triggerJob = true;
|
bool launchJob = true;
|
||||||
|
|
||||||
Job* job = FindJob(get_leaf(message->GetString("name")));
|
Job* job = FindJob(get_leaf(message->GetString("name")));
|
||||||
if (job == NULL) {
|
if (job == NULL) {
|
||||||
@@ -454,7 +454,7 @@ LaunchDaemon::_HandleGetLaunchData(BMessage* message)
|
|||||||
}
|
}
|
||||||
reply.what = B_NAME_NOT_FOUND;
|
reply.what = B_NAME_NOT_FOUND;
|
||||||
} else if (!job->IsLaunched()) {
|
} else if (!job->IsLaunched()) {
|
||||||
if (!job->CheckCondition(*this)) {
|
if (job->InitCheck() == B_NO_INIT || !job->CheckCondition(*this)) {
|
||||||
// The job exists, but cannot be started yet, as its
|
// The job exists, but cannot be started yet, as its
|
||||||
// conditions are not met; don't make it available yet
|
// conditions are not met; don't make it available yet
|
||||||
// TODO: we may not want to initialize jobs with conditions
|
// TODO: we may not want to initialize jobs with conditions
|
||||||
@@ -465,9 +465,8 @@ LaunchDaemon::_HandleGetLaunchData(BMessage* message)
|
|||||||
// The job is not triggered by demand; we cannot start it now
|
// The job is not triggered by demand; we cannot start it now
|
||||||
reply.what = B_NO_INIT;
|
reply.what = B_NO_INIT;
|
||||||
} else {
|
} else {
|
||||||
// The job has already been triggered, don't trigger it
|
// The job has already been triggered, don't launch it again
|
||||||
// again
|
launchJob = false;
|
||||||
triggerJob = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -490,8 +489,9 @@ LaunchDaemon::_HandleGetLaunchData(BMessage* message)
|
|||||||
iterator->second.GetInt32("port", -1));
|
iterator->second.GetInt32("port", -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggerJob)
|
// Launch the job if it hasn't been launched already
|
||||||
_TriggerJob(job);
|
if (launchJob)
|
||||||
|
_LaunchJob(job);
|
||||||
}
|
}
|
||||||
message->SendReply(&reply);
|
message->SendReply(&reply);
|
||||||
}
|
}
|
||||||
@@ -932,13 +932,20 @@ LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Initializes all jobs for the specified target (may be \c NULL).
|
||||||
|
Jobs that cannot be initialized, and those that never will be due to
|
||||||
|
conditions, will be removed from the list.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
LaunchDaemon::_InitJobs()
|
LaunchDaemon::_InitJobs(Target* target)
|
||||||
{
|
{
|
||||||
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();) {
|
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();) {
|
||||||
Job* job = iterator->second;
|
Job* job = iterator->second;
|
||||||
JobMap::iterator remove = iterator++;
|
JobMap::iterator remove = iterator++;
|
||||||
|
|
||||||
|
if (job->Target() != target)
|
||||||
|
continue;
|
||||||
|
|
||||||
status_t status = B_NO_INIT;
|
status_t status = B_NO_INIT;
|
||||||
if (job->IsEnabled()) {
|
if (job->IsEnabled()) {
|
||||||
// Filter out jobs that have a constant and failing condition
|
// Filter out jobs that have a constant and failing condition
|
||||||
@@ -965,51 +972,63 @@ LaunchDaemon::_InitJobs()
|
|||||||
|
|
||||||
|
|
||||||
/*! Adds all jobs for the specified target (may be \c NULL) to the launch
|
/*! Adds all jobs for the specified target (may be \c NULL) to the launch
|
||||||
queue, except those that are triggered by events.
|
queue, except those that are triggered by events that haven't been
|
||||||
|
triggered yet.
|
||||||
|
|
||||||
|
Unless \a forceNow is true, the target is only launched if its events,
|
||||||
|
if any, have been triggered already, and its conditions are met.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
LaunchDaemon::_LaunchJobs(Target* target)
|
LaunchDaemon::_LaunchJobs(Target* target, bool forceNow)
|
||||||
{
|
{
|
||||||
if (target != NULL && !target->CheckCondition(*this))
|
if (!forceNow && target != NULL && (!target->EventHasTriggered()
|
||||||
|
|| !target->CheckCondition(*this))) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target != NULL && !target->HasLaunched()) {
|
||||||
|
target->SetLaunched(true);
|
||||||
|
_InitJobs(target);
|
||||||
|
}
|
||||||
|
|
||||||
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();
|
for (JobMap::iterator iterator = fJobs.begin(); iterator != fJobs.end();
|
||||||
iterator++) {
|
iterator++) {
|
||||||
Job* job = iterator->second;
|
Job* job = iterator->second;
|
||||||
if (job->Target() == target
|
if (job->Target() == target)
|
||||||
&& (job->Event() == NULL || job->Event()->Triggered()))
|
_LaunchJob(job);
|
||||||
_TriggerJob(job);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Adds the specified \a job to the launch queue
|
||||||
|
queue, except those that are triggered by events.
|
||||||
|
|
||||||
|
Unless \a forceNow is true, the target is only launched if its events,
|
||||||
|
if any, have been triggered already.
|
||||||
|
|
||||||
|
Calling this method will trigger a demand event.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
LaunchDaemon::_TriggerJob(Job* job)
|
LaunchDaemon::_LaunchJob(Job* job, bool forceNow)
|
||||||
{
|
{
|
||||||
if (job == NULL)
|
if (job == NULL || job->IsLaunched() || !forceNow
|
||||||
|
&& (!job->EventHasTriggered() || !job->CheckCondition(*this)
|
||||||
|
|| Events::TriggerDemand(job->Event()))) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
||||||
_TriggerJob(requirement);
|
_LaunchJob(requirement);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (job->EventHasTriggered() || !Events::TriggerDemand(job->Event()))
|
|
||||||
_AddLaunchJob(job);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
LaunchDaemon::_AddLaunchJob(Job* job)
|
|
||||||
{
|
|
||||||
if (job->Target() != NULL)
|
if (job->Target() != NULL)
|
||||||
job->Target()->ResolveSourceFiles();
|
job->Target()->ResolveSourceFiles();
|
||||||
if (job->Event() != NULL)
|
if (job->Event() != NULL)
|
||||||
job->Event()->ResetTrigger();
|
job->Event()->ResetTrigger();
|
||||||
|
|
||||||
if (!job->IsLaunched() && job->CheckCondition(*this))
|
|
||||||
fJobQueue.AddJob(job);
|
fJobQueue.AddJob(job);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
Target::Target(const char* name)
|
Target::Target(const char* name)
|
||||||
:
|
:
|
||||||
BaseJob(name)
|
BaseJob(name),
|
||||||
|
fLaunched(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +22,13 @@ Target::AddData(const char* name, BMessage& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
Target::SetLaunched(bool launched)
|
||||||
|
{
|
||||||
|
fLaunched = launched;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Target::Execute()
|
Target::Execute()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,11 +22,16 @@ public:
|
|||||||
const BMessage& Data() const
|
const BMessage& Data() const
|
||||||
{ return fData; }
|
{ return fData; }
|
||||||
|
|
||||||
|
bool HasLaunched() const
|
||||||
|
{ return fLaunched; }
|
||||||
|
void SetLaunched(bool launched);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual status_t Execute();
|
virtual status_t Execute();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMessage fData;
|
BMessage fData;
|
||||||
|
bool fLaunched;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user