X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fjob.c;h=bae6ab9f32f5c4fd3d569e09f7da22a67adf6755;hb=cc527a4734d636f1ab5a66576cb7e232af3cc261;hp=e57286fe89171a01a080c3e277d37bfd2608a817;hpb=ac155bb885f9ea8aac3979a6b2686f0c8a9cc6e3;p=elogind.git diff --git a/src/job.c b/src/job.c index e57286fe8..bae6ab9f3 100644 --- a/src/job.c +++ b/src/job.c @@ -164,100 +164,47 @@ bool job_is_anchor(Job *j) { return false; } -static bool types_match(JobType a, JobType b, JobType c, JobType d) { - return - (a == c && b == d) || - (a == d && b == c); -} - -int job_type_merge(JobType *a, JobType b) { - if (*a == b) - return 0; - - /* Merging is associative! a merged with b merged with c is - * the same as a merged with c merged with b. */ - - /* Mergeability is transitive! if a can be merged with b and b - * with c then a also with c */ - - /* Also, if a merged with b cannot be merged with c, then - * either a or b cannot be merged with c either */ - - if (types_match(*a, b, JOB_START, JOB_VERIFY_ACTIVE)) - *a = JOB_START; - else if (types_match(*a, b, JOB_START, JOB_RELOAD) || - types_match(*a, b, JOB_START, JOB_RELOAD_OR_START) || - types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_RELOAD_OR_START) || - types_match(*a, b, JOB_RELOAD, JOB_RELOAD_OR_START)) - *a = JOB_RELOAD_OR_START; - else if (types_match(*a, b, JOB_START, JOB_RESTART) || - types_match(*a, b, JOB_START, JOB_TRY_RESTART) || - types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_RESTART) || - types_match(*a, b, JOB_RELOAD, JOB_RESTART) || - types_match(*a, b, JOB_RELOAD_OR_START, JOB_RESTART) || - types_match(*a, b, JOB_RELOAD_OR_START, JOB_TRY_RESTART) || - types_match(*a, b, JOB_RESTART, JOB_TRY_RESTART)) - *a = JOB_RESTART; - else if (types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_RELOAD)) - *a = JOB_RELOAD; - else if (types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_TRY_RESTART) || - types_match(*a, b, JOB_RELOAD, JOB_TRY_RESTART)) - *a = JOB_TRY_RESTART; - else - return -EEXIST; - - return 0; -} - -bool job_type_is_mergeable(JobType a, JobType b) { - return job_type_merge(&a, b) >= 0; -} - -bool job_type_is_superset(JobType a, JobType b) { +/* + * Merging is commutative, so imagine the matrix as symmetric. We store only + * its lower triangle to avoid duplication. We don't store the main diagonal, + * because A merged with A is simply A. + * + * Merging is associative! A merged with B merged with C is the same as + * A merged with C merged with B. + * + * Mergeability is transitive! If A can be merged with B and B with C then + * A also with C. + * + * Also, if A merged with B cannot be merged with C, then either A or B cannot + * be merged with C either. + */ +static const JobType job_merging_table[] = { +/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD JOB_RELOAD_OR_START JOB_RESTART JOB_TRY_RESTART */ +/************************************************************************************************************************************/ +/*JOB_START */ +/*JOB_VERIFY_ACTIVE */ JOB_START, +/*JOB_STOP */ -1, -1, +/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1, +/*JOB_RELOAD_OR_START*/ JOB_RELOAD_OR_START, JOB_RELOAD_OR_START, -1, JOB_RELOAD_OR_START, +/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART, JOB_RESTART, +/*JOB_TRY_RESTART */ JOB_RESTART, JOB_TRY_RESTART, -1, JOB_TRY_RESTART, JOB_RESTART, JOB_RESTART, +}; - /* Checks whether operation a is a "superset" of b in its - * actions */ +JobType job_type_lookup_merge(JobType a, JobType b) { + assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX * (_JOB_TYPE_MAX - 1) / 2); + assert(a >= 0 && a < _JOB_TYPE_MAX); + assert(b >= 0 && b < _JOB_TYPE_MAX); if (a == b) - return true; - - switch (a) { - case JOB_START: - return b == JOB_VERIFY_ACTIVE; - - case JOB_RELOAD: - return - b == JOB_VERIFY_ACTIVE; - - case JOB_RELOAD_OR_START: - return - b == JOB_RELOAD || - b == JOB_START || - b == JOB_VERIFY_ACTIVE; - - case JOB_RESTART: - return - b == JOB_START || - b == JOB_VERIFY_ACTIVE || - b == JOB_RELOAD || - b == JOB_RELOAD_OR_START || - b == JOB_TRY_RESTART; - - case JOB_TRY_RESTART: - return - b == JOB_VERIFY_ACTIVE || - b == JOB_RELOAD; - default: - return false; + return a; + if (a < b) { + JobType tmp = a; + a = b; + b = tmp; } -} - -bool job_type_is_conflicting(JobType a, JobType b) { - assert(a >= 0 && a < _JOB_TYPE_MAX); - assert(b >= 0 && b < _JOB_TYPE_MAX); - return (a == JOB_STOP) != (b == JOB_STOP); + return job_merging_table[(a - 1) * a / 2 + b]; } bool job_type_is_redundant(JobType a, UnitActiveState b) { @@ -355,6 +302,14 @@ bool job_is_runnable(Job *j) { return true; } +static void job_change_type(Job *j, JobType newtype) { + log_debug("Converting job %s/%s -> %s/%s", + j->unit->id, job_type_to_string(j->type), + j->unit->id, job_type_to_string(newtype)); + + j->type = newtype; +} + int job_run_and_invalidate(Job *j) { int r; uint32_t id; @@ -387,14 +342,21 @@ int job_run_and_invalidate(Job *j) { switch (j->type) { + case JOB_RELOAD_OR_START: + if (unit_active_state(j->unit) == UNIT_ACTIVE) { + job_change_type(j, JOB_RELOAD); + r = unit_reload(j->unit); + break; + } + job_change_type(j, JOB_START); + /* fall through */ + case JOB_START: r = unit_start(j->unit); - /* If this unit cannot be started, then simply - * wait */ + /* If this unit cannot be started, then simply wait */ if (r == -EBADR) r = 0; - break; case JOB_VERIFY_ACTIVE: { @@ -408,11 +370,19 @@ int job_run_and_invalidate(Job *j) { break; } + case JOB_TRY_RESTART: + if (UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(j->unit))) { + r = -ENOEXEC; + break; + } + job_change_type(j, JOB_RESTART); + /* fall through */ + case JOB_STOP: + case JOB_RESTART: r = unit_stop(j->unit); - /* If this unit cannot stopped, then simply - * wait. */ + /* If this unit cannot stopped, then simply wait. */ if (r == -EBADR) r = 0; break; @@ -421,43 +391,6 @@ int job_run_and_invalidate(Job *j) { r = unit_reload(j->unit); break; - case JOB_RELOAD_OR_START: - if (unit_active_state(j->unit) == UNIT_ACTIVE) { - j->type = JOB_RELOAD; - r = unit_reload(j->unit); - } else { - j->type = JOB_START; - r = unit_start(j->unit); - - if (r == -EBADR) - r = 0; - } - break; - - case JOB_RESTART: { - UnitActiveState t = unit_active_state(j->unit); - if (t == UNIT_INACTIVE || t == UNIT_FAILED || t == UNIT_ACTIVATING) { - j->type = JOB_START; - r = unit_start(j->unit); - } else - r = unit_stop(j->unit); - break; - } - - case JOB_TRY_RESTART: { - UnitActiveState t = unit_active_state(j->unit); - if (t == UNIT_INACTIVE || t == UNIT_FAILED || t == UNIT_DEACTIVATING) - r = -ENOEXEC; - else if (t == UNIT_ACTIVATING) { - j->type = JOB_START; - r = unit_start(j->unit); - } else { - j->type = JOB_RESTART; - r = unit_stop(j->unit); - } - break; - } - default: assert_not_reached("Unknown job type"); } @@ -536,14 +469,10 @@ int job_finish_and_invalidate(Job *j, JobResult result) { job_add_to_dbus_queue(j); /* Patch restart jobs so that they become normal start jobs */ - if (result == JOB_DONE && (j->type == JOB_RESTART || j->type == JOB_TRY_RESTART)) { - - log_debug("Converting job %s/%s -> %s/%s", - j->unit->id, job_type_to_string(j->type), - j->unit->id, job_type_to_string(JOB_START)); + if (result == JOB_DONE && j->type == JOB_RESTART) { + job_change_type(j, JOB_START); j->state = JOB_WAITING; - j->type = JOB_START; job_add_to_run_queue(j);