unit: distuingish mandatory from triggering conditions

This commit is contained in:
Lennart Poettering 2011-03-08 03:04:47 +01:00
parent 08672cb507
commit 267632f0ab
6 changed files with 62 additions and 26 deletions

2
TODO
View File

@ -14,8 +14,6 @@ F15:
* hook emergency.target into local-fs.target in some way as OnFailure with isolate
* introduce simple way to do mandatory conditions (make current conditions mandatory, and introduce =| as non-mandatory conditions)
* mount /dev/.run and /var/run as bind mounts
* Make use of UnknownInterface, UnknownObject

View File

@ -622,8 +622,8 @@
environment and optionally test
whether it is a specific
implementation. Takes either boolean
value to check if being executed in any
virtual environment or one of the
value to check if being executed in
any virtual environment or one of the
<varname>qemu</varname>,
<varname>kvm</varname>,
<varname>vmware</varname>,
@ -642,9 +642,20 @@
will always fail, otherwise
succeed. If multiple conditions are
specified the unit will be executed if
at least one of them applies (i.e. a
logical OR is
applied).</para></listitem>
all of them apply (i.e. a logical AND
is applied). Condition checks can be
prefixed with a pipe symbol (|) in
which case a condition becomes a
triggering condition. If at least one
triggering condition is defined for a
unit then the unit will be executed if
at least one of the triggering
conditions apply and all of the
non-triggering conditions. If you
prefix an argument with the pipe
symbol and an exclamation mark the
pipe symbol must be passed first, the
exclamation second.</para></listitem>
</varlistentry>
</variablelist>

View File

@ -27,11 +27,12 @@
#include "util.h"
#include "condition.h"
Condition* condition_new(ConditionType type, const char *parameter, bool negate) {
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate) {
Condition *c;
c = new0(Condition, 1);
c->type = type;
c->trigger = trigger;
c->negate = negate;
if (parameter)
@ -153,17 +154,28 @@ bool condition_test(Condition *c) {
bool condition_test_list(Condition *first) {
Condition *c;
int triggered = -1;
/* If the condition list is empty, then it is true */
if (!first)
return true;
/* Otherwise, if any of the conditions apply we return true */
LIST_FOREACH(conditions, c, first)
if (condition_test(c))
return true;
/* Otherwise, if all of the non-trigger conditions apply and
* if any of the trigger conditions apply (unless there are
* none) we return true */
LIST_FOREACH(conditions, c, first) {
bool b;
return false;
b = condition_test(c);
if (!c->trigger && !b)
return false;
if (c->trigger && triggered <= 0)
triggered = b;
}
return triggered != 0;
}
void condition_dump(Condition *c, FILE *f, const char *prefix) {
@ -174,9 +186,10 @@ void condition_dump(Condition *c, FILE *f, const char *prefix) {
prefix = "";
fprintf(f,
"%s%s: %s%s\n",
"%s%s: %s%s%s\n",
prefix,
condition_type_to_string(c->type),
c->trigger ? "|" : "",
c->negate ? "!" : "",
c->parameter);
}

View File

@ -39,12 +39,14 @@ typedef enum ConditionType {
typedef struct Condition {
ConditionType type;
char *parameter;
bool negate;
bool trigger:1;
bool negate:1;
LIST_FIELDS(struct Condition, conditions);
} Condition;
Condition* condition_new(ConditionType type, const char *parameter, bool negate);
Condition* condition_new(ConditionType type, const char *parameter, bool trigger, bool negate);
void condition_free(Condition *c);
void condition_free_list(Condition *c);

View File

@ -1397,7 +1397,7 @@ static int config_parse_condition_path(
void *userdata) {
Unit *u = data;
bool negate;
bool trigger, negate;
Condition *c;
assert(filename);
@ -1405,6 +1405,9 @@ static int config_parse_condition_path(
assert(rvalue);
assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!'))
rvalue++;
@ -1414,7 +1417,7 @@ static int config_parse_condition_path(
}
if (!(c = condition_new(streq(lvalue, "ConditionPathExists") ? CONDITION_PATH_EXISTS : CONDITION_DIRECTORY_NOT_EMPTY,
rvalue, negate)))
rvalue, trigger, negate)))
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@ -1431,7 +1434,7 @@ static int config_parse_condition_kernel(
void *userdata) {
Unit *u = data;
bool negate;
bool trigger, negate;
Condition *c;
assert(filename);
@ -1439,10 +1442,13 @@ static int config_parse_condition_kernel(
assert(rvalue);
assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!'))
rvalue++;
if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, negate)))
if (!(c = condition_new(CONDITION_KERNEL_COMMAND_LINE, rvalue, trigger, negate)))
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@ -1459,7 +1465,7 @@ static int config_parse_condition_virt(
void *userdata) {
Unit *u = data;
bool negate;
bool trigger, negate;
Condition *c;
assert(filename);
@ -1467,10 +1473,13 @@ static int config_parse_condition_virt(
assert(rvalue);
assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!'))
rvalue++;
if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, negate)))
if (!(c = condition_new(CONDITION_VIRTUALIZATION, rvalue, trigger, negate)))
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);
@ -1488,7 +1497,7 @@ static int config_parse_condition_null(
Unit *u = data;
Condition *c;
bool negate;
bool trigger, negate;
int b;
assert(filename);
@ -1496,6 +1505,9 @@ static int config_parse_condition_null(
assert(rvalue);
assert(data);
if ((trigger = rvalue[0] == '|'))
rvalue++;
if ((negate = rvalue[0] == '!'))
rvalue++;
@ -1507,7 +1519,7 @@ static int config_parse_condition_null(
if (!b)
negate = !negate;
if (!(c = condition_new(CONDITION_NULL, NULL, negate)))
if (!(c = condition_new(CONDITION_NULL, NULL, trigger, negate)))
return -ENOMEM;
LIST_PREPEND(Condition, conditions, u->meta.conditions, c);

View File

@ -11,8 +11,8 @@ DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service
Before=sysinit.target shutdown.target
ConditionPathExists=/etc/sysctl.conf
ConditionDirectoryNotEmpty=/etc/sysctl.d
ConditionPathExists=|/etc/sysctl.conf
ConditionDirectoryNotEmpty=|/etc/sysctl.d
[Service]
Type=oneshot