launch_daemon: Conditions now know if they are constant.
* This allows to remove a job in the init phase already, if its condition is not only constant, but also failing. * Also removed the special Job::LaunchInSafeMode() method; this is now done using the conditions (the config option no_safemode remains, though).
This commit is contained in:
parent
004cd6709d
commit
e0fc09b439
@ -21,9 +21,13 @@
|
||||
class ConditionContainer : public Condition {
|
||||
protected:
|
||||
ConditionContainer(const BMessage& args);
|
||||
ConditionContainer();
|
||||
|
||||
public:
|
||||
void AddCondition(Condition* condition);
|
||||
|
||||
virtual bool IsConstant(ConditionContext& context) const;
|
||||
|
||||
protected:
|
||||
void ToString(BString& string) const;
|
||||
|
||||
@ -35,6 +39,7 @@ protected:
|
||||
class AndCondition : public ConditionContainer {
|
||||
public:
|
||||
AndCondition(const BMessage& args);
|
||||
AndCondition();
|
||||
|
||||
virtual bool Test(ConditionContext& context) const;
|
||||
virtual BString ToString() const;
|
||||
@ -46,6 +51,8 @@ public:
|
||||
OrCondition(const BMessage& args);
|
||||
|
||||
virtual bool Test(ConditionContext& context) const;
|
||||
virtual bool IsConstant(ConditionContext& context) const;
|
||||
|
||||
virtual BString ToString() const;
|
||||
};
|
||||
|
||||
@ -53,6 +60,7 @@ public:
|
||||
class NotCondition : public ConditionContainer {
|
||||
public:
|
||||
NotCondition(const BMessage& args);
|
||||
NotCondition();
|
||||
|
||||
virtual bool Test(ConditionContext& context) const;
|
||||
virtual BString ToString() const;
|
||||
@ -62,6 +70,8 @@ public:
|
||||
class SafeModeCondition : public Condition {
|
||||
public:
|
||||
virtual bool Test(ConditionContext& context) const;
|
||||
virtual bool IsConstant(ConditionContext& context) const;
|
||||
|
||||
virtual BString ToString() const;
|
||||
};
|
||||
|
||||
@ -71,6 +81,8 @@ public:
|
||||
ReadOnlyCondition(const BMessage& args);
|
||||
|
||||
virtual bool Test(ConditionContext& context) const;
|
||||
virtual bool IsConstant(ConditionContext& context) const;
|
||||
|
||||
virtual BString ToString() const;
|
||||
|
||||
private:
|
||||
@ -124,6 +136,13 @@ Condition::~Condition()
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Condition::IsConstant(ConditionContext& context) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -145,6 +164,13 @@ ConditionContainer::ConditionContainer(const BMessage& args)
|
||||
}
|
||||
|
||||
|
||||
ConditionContainer::ConditionContainer()
|
||||
:
|
||||
fConditions(10, true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ConditionContainer::AddCondition(Condition* condition)
|
||||
{
|
||||
@ -153,6 +179,25 @@ ConditionContainer::AddCondition(Condition* condition)
|
||||
}
|
||||
|
||||
|
||||
/*! A single constant failing condition makes this constant, too, otherwise,
|
||||
a single non-constant condition makes this non-constant as well.
|
||||
*/
|
||||
bool
|
||||
ConditionContainer::IsConstant(ConditionContext& context) const
|
||||
{
|
||||
bool fixed = true;
|
||||
for (int32 index = 0; index < fConditions.CountItems(); index++) {
|
||||
const Condition* condition = fConditions.ItemAt(index);
|
||||
if (condition->IsConstant(context)) {
|
||||
if (!condition->Test(context))
|
||||
return true;
|
||||
} else
|
||||
fixed = false;
|
||||
}
|
||||
return fixed;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ConditionContainer::ToString(BString& string) const
|
||||
{
|
||||
@ -177,6 +222,11 @@ AndCondition::AndCondition(const BMessage& args)
|
||||
}
|
||||
|
||||
|
||||
AndCondition::AndCondition()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AndCondition::Test(ConditionContext& context) const
|
||||
{
|
||||
@ -223,6 +273,25 @@ OrCondition::Test(ConditionContext& context) const
|
||||
}
|
||||
|
||||
|
||||
/*! If there is a single succeeding constant condition, this is constant, too.
|
||||
Otherwise, it is non-constant if there is a single non-constant condition.
|
||||
*/
|
||||
bool
|
||||
OrCondition::IsConstant(ConditionContext& context) const
|
||||
{
|
||||
bool fixed = true;
|
||||
for (int32 index = 0; index < fConditions.CountItems(); index++) {
|
||||
const Condition* condition = fConditions.ItemAt(index);
|
||||
if (condition->IsConstant(context)) {
|
||||
if (condition->Test(context))
|
||||
return true;
|
||||
} else
|
||||
fixed = false;
|
||||
}
|
||||
return fixed;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
OrCondition::ToString() const
|
||||
{
|
||||
@ -242,6 +311,11 @@ NotCondition::NotCondition(const BMessage& args)
|
||||
}
|
||||
|
||||
|
||||
NotCondition::NotCondition()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NotCondition::Test(ConditionContext& context) const
|
||||
{
|
||||
@ -273,6 +347,13 @@ SafeModeCondition::Test(ConditionContext& context) const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SafeModeCondition::IsConstant(ConditionContext& context) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
SafeModeCondition::ToString() const
|
||||
{
|
||||
@ -314,6 +395,13 @@ ReadOnlyCondition::Test(ConditionContext& context) const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ReadOnlyCondition::IsConstant(ConditionContext& context) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
ReadOnlyCondition::ToString() const
|
||||
{
|
||||
@ -370,3 +458,20 @@ Conditions::FromMessage(const BMessage& message)
|
||||
{
|
||||
return create_condition("and", message);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ Condition*
|
||||
Conditions::AddNotSafeMode(Condition* condition)
|
||||
{
|
||||
AndCondition* and = dynamic_cast<AndCondition*>(condition);
|
||||
if (and == NULL)
|
||||
and = new AndCondition();
|
||||
if (and != condition && condition != NULL)
|
||||
and->AddCondition(condition);
|
||||
|
||||
NotCondition* not = new NotCondition();
|
||||
not->AddCondition(new SafeModeCondition());
|
||||
|
||||
and->AddCondition(not);
|
||||
return and;
|
||||
}
|
||||
|
@ -24,6 +24,12 @@ public:
|
||||
virtual ~Condition();
|
||||
|
||||
virtual bool Test(ConditionContext& context) const = 0;
|
||||
|
||||
/*! Determines whether or not the result of this condition is fixed,
|
||||
and will not change anymore.
|
||||
*/
|
||||
virtual bool IsConstant(ConditionContext& context) const;
|
||||
|
||||
virtual BString ToString() const = 0;
|
||||
};
|
||||
|
||||
@ -31,6 +37,7 @@ public:
|
||||
class Conditions {
|
||||
public:
|
||||
static Condition* FromMessage(const BMessage& message);
|
||||
static Condition* AddNotSafeMode(Condition* condition);
|
||||
};
|
||||
|
||||
|
||||
|
@ -20,7 +20,6 @@ Job::Job(const char* name)
|
||||
fEnabled(true),
|
||||
fService(false),
|
||||
fCreateDefaultPort(false),
|
||||
fLaunchInSafeMode(true),
|
||||
fInitStatus(B_NO_INIT),
|
||||
fTeam(-1),
|
||||
fTarget(NULL)
|
||||
@ -34,7 +33,6 @@ Job::Job(const Job& other)
|
||||
fEnabled(other.IsEnabled()),
|
||||
fService(other.IsService()),
|
||||
fCreateDefaultPort(other.CreateDefaultPort()),
|
||||
fLaunchInSafeMode(other.LaunchInSafeMode()),
|
||||
fInitStatus(B_NO_INIT),
|
||||
fTeam(-1),
|
||||
fTarget(other.Target())
|
||||
@ -115,20 +113,6 @@ Job::AddPort(BMessage& data)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Job::LaunchInSafeMode() const
|
||||
{
|
||||
return fLaunchInSafeMode;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Job::SetLaunchInSafeMode(bool launch)
|
||||
{
|
||||
fLaunchInSafeMode = launch;
|
||||
}
|
||||
|
||||
|
||||
const BStringList&
|
||||
Job::Arguments() const
|
||||
{
|
||||
|
@ -42,9 +42,6 @@ public:
|
||||
|
||||
void AddPort(BMessage& data);
|
||||
|
||||
bool LaunchInSafeMode() const;
|
||||
void SetLaunchInSafeMode(bool launch);
|
||||
|
||||
const BStringList& Arguments() const;
|
||||
BStringList& Arguments();
|
||||
void AddArgument(const char* argument);
|
||||
@ -82,7 +79,6 @@ private:
|
||||
bool fEnabled;
|
||||
bool fService;
|
||||
bool fCreateDefaultPort;
|
||||
bool fLaunchInSafeMode;
|
||||
PortMap fPortMap;
|
||||
status_t fInitStatus;
|
||||
team_id fTeam;
|
||||
|
@ -102,7 +102,8 @@ private:
|
||||
void _LaunchJobs(Target* target);
|
||||
void _AddLaunchJob(Job* job);
|
||||
void _AddTarget(Target* target);
|
||||
void _SetCondition(BaseJob* job, BMessage& message);
|
||||
void _SetCondition(BaseJob* job,
|
||||
const BMessage& message);
|
||||
|
||||
status_t _StartSession(const char* login,
|
||||
const char* password);
|
||||
@ -589,8 +590,6 @@ LaunchDaemon::_AddJob(Target* target, bool service, BMessage& message)
|
||||
job->SetEnabled(!message.GetBool("disabled", !job->IsEnabled()));
|
||||
job->SetService(service);
|
||||
job->SetCreateDefaultPort(!message.GetBool("legacy", !service));
|
||||
job->SetLaunchInSafeMode(
|
||||
!message.GetBool("no_safemode", !job->LaunchInSafeMode()));
|
||||
job->SetTarget(target);
|
||||
|
||||
_SetCondition(job, message);
|
||||
@ -628,9 +627,13 @@ LaunchDaemon::_InitJobs()
|
||||
JobMap::iterator remove = iterator++;
|
||||
|
||||
status_t status = B_NO_INIT;
|
||||
if (job->IsEnabled() && (!IsSafeMode() || job->LaunchInSafeMode())) {
|
||||
std::set<BString> dependencies;
|
||||
status = job->Init(*this, dependencies);
|
||||
if (job->IsEnabled()) {
|
||||
// Filter out jobs that have a constant and failing condition
|
||||
if (job->Condition() == NULL || !job->Condition()->IsConstant(*this)
|
||||
|| job->Condition()->Test(*this)) {
|
||||
std::set<BString> dependencies;
|
||||
status = job->Init(*this, dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
if (status != B_OK) {
|
||||
@ -679,14 +682,19 @@ LaunchDaemon::_AddTarget(Target* target)
|
||||
|
||||
|
||||
void
|
||||
LaunchDaemon::_SetCondition(BaseJob* job, BMessage& message)
|
||||
LaunchDaemon::_SetCondition(BaseJob* job, const BMessage& message)
|
||||
{
|
||||
Condition* condition = NULL;
|
||||
|
||||
BMessage conditions;
|
||||
if (message.FindMessage("if", &conditions) == B_OK) {
|
||||
Condition* condition = Conditions::FromMessage(conditions);
|
||||
if (condition != NULL)
|
||||
job->SetCondition(condition);
|
||||
}
|
||||
if (message.FindMessage("if", &conditions) == B_OK)
|
||||
condition = Conditions::FromMessage(conditions);
|
||||
|
||||
if (message.GetBool("no_safemode"))
|
||||
condition = Conditions::AddNotSafeMode(condition);
|
||||
|
||||
if (condition != NULL)
|
||||
job->SetCondition(condition);
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,6 +126,7 @@ const static settings_template kTargetTemplate[] = {
|
||||
{B_STRING_TYPE, "name", NULL, true},
|
||||
{B_BOOL_TYPE, "reset", NULL},
|
||||
{B_MESSAGE_TYPE, "if", kConditionTemplate},
|
||||
{B_BOOL_TYPE, "no_safemode", NULL},
|
||||
{B_MESSAGE_TYPE, "job", kJobTemplate},
|
||||
{B_MESSAGE_TYPE, "service", kJobTemplate},
|
||||
{0, NULL, NULL}
|
||||
|
@ -43,6 +43,7 @@ ConditionsTest::TestSafemode()
|
||||
{
|
||||
Condition* condition = _Condition("safemode");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(condition->IsConstant(sConditionContext));
|
||||
|
||||
class SafemodeConditionContext : public ConditionContext {
|
||||
public:
|
||||
@ -52,6 +53,7 @@ ConditionsTest::TestSafemode()
|
||||
}
|
||||
} safemodeContext;
|
||||
CPPUNIT_ASSERT(condition->Test(safemodeContext));
|
||||
CPPUNIT_ASSERT(condition->IsConstant(safemodeContext));
|
||||
}
|
||||
|
||||
|
||||
@ -60,6 +62,7 @@ ConditionsTest::TestFileExists()
|
||||
{
|
||||
Condition* condition = _Condition("file_exists /boot");
|
||||
CPPUNIT_ASSERT(condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("file_exists /boot/don't fool me!");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
@ -73,17 +76,34 @@ ConditionsTest::TestOr()
|
||||
"file_exists /boot\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("or {\n"
|
||||
"file_exists /nowhere\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("or {\n"
|
||||
"file_exists /boot\n"
|
||||
"file_exists /nowhere\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("or {\n"
|
||||
"not safemode\n"
|
||||
"file_exists /boot\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("or {\n"
|
||||
"safemode\n"
|
||||
"file_exists /boot\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
}
|
||||
|
||||
|
||||
@ -94,17 +114,40 @@ ConditionsTest::TestAnd()
|
||||
"file_exists /boot\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("and {\n"
|
||||
"file_exists /nowhere\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("and {\n"
|
||||
"file_exists /boot\n"
|
||||
"file_exists /nowhere\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("and {\n"
|
||||
"safemode\n"
|
||||
"file_exists /nowhere\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("and {\n"
|
||||
"not safemode\n"
|
||||
"file_exists /nowhere\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(!condition->IsConstant(sConditionContext));
|
||||
|
||||
condition = _Condition("and {\n"
|
||||
"safemode\n"
|
||||
"}\n");
|
||||
CPPUNIT_ASSERT(!condition->Test(sConditionContext));
|
||||
CPPUNIT_ASSERT(condition->IsConstant(sConditionContext));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user