No functional change. Preparation for later commits.
unit_dump(u, stdout, "\t");
log_unit_debug(u, "Creating %s/start job", u->id);
- r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, NULL, &error, NULL);
+ r = manager_add_job(u->manager, JOB_START, u, JOB_REPLACE, &error, /* ret = */ NULL);
if (r < 0)
log_unit_error_errno(u, r, "Failed to create %s/start: %s", u->id, bus_error_message(&error, r));
goto fail;
}
- r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
+ r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, &error, /* ret = */ NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
goto fail;
goto fail;
}
- r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, NULL, &error, NULL);
+ r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, /* ret = */ NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue unmount job: %s", bus_error_message(&error, r));
goto fail;
return -ENOMEM;
}
- r = manager_add_job(u->manager, type, u, mode, affected, error, &j);
+ r = manager_add_job_full(u->manager, type, u, mode, /* extra_flags = */ 0, affected, error, &j);
if (r < 0)
return r;
goto failed;
}
- r = manager_add_job(m, JOB_START, u, JOB_REPLACE, NULL, &error, NULL);
+ r = manager_add_job(m, JOB_START, u, JOB_REPLACE, &error, /* ret = */ NULL);
if (r < 0)
goto failed;
assert(target->load_state == UNIT_LOADED);
- r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, NULL, &error, &job);
+ r = manager_add_job(m, JOB_START, target, JOB_ISOLATE, &error, &job);
if (r == -EPERM) {
log_debug_errno(r, "Default target could not be isolated, starting instead: %s", bus_error_message(&error, r));
sd_bus_error_free(&error);
- r = manager_add_job(m, JOB_START, target, JOB_REPLACE, NULL, &error, &job);
+ r = manager_add_job(m, JOB_START, target, JOB_REPLACE, &error, &job);
if (r < 0) {
*ret_error_message = "Failed to start default target";
return log_struct_errno(LOG_EMERG, r,
}
/* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, NULL, &error, NULL);
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, &error, /* ret = */ NULL);
if (r < 0)
log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
}
continue;
}
- r = manager_add_job(u->manager, JOB_START, u, JOB_FAIL, NULL, &error, NULL);
+ r = manager_add_job(u->manager, JOB_START, u, JOB_FAIL, &error, /* ret = */ NULL);
if (r < 0)
log_unit_warning_errno(u, r, "Failed to enqueue start job, ignoring: %s", bus_error_message(&error, r));
}
continue;
}
- r = manager_add_job(u->manager, JOB_STOP, u, JOB_REPLACE, NULL, &error, NULL);
+ r = manager_add_job(u->manager, JOB_STOP, u, JOB_REPLACE, &error, /* ret = */ NULL);
if (r < 0)
log_unit_warning_errno(u, r, "Failed to enqueue stop job, ignoring: %s", bus_error_message(&error, r));
}
return 0;
}
-int manager_add_job(
+int manager_add_job_full(
Manager *m,
JobType type,
Unit *unit,
JobMode mode,
+ TransactionAddFlags extra_flags,
Set *affected_jobs,
sd_bus_error *error,
Job **ret) {
int r;
assert(m);
- assert(type < _JOB_TYPE_MAX);
+ assert(type >= 0 && type < _JOB_TYPE_MAX);
assert(unit);
- assert(mode < _JOB_MODE_MAX);
+ assert(mode >= 0 && mode < _JOB_MODE_MAX);
+ assert((extra_flags & ~_TRANSACTION_FLAGS_MASK_PUBLIC) == 0);
if (mode == JOB_ISOLATE && type != JOB_START)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Isolate is only valid for start.");
TRANSACTION_MATTERS |
(IN_SET(mode, JOB_IGNORE_DEPENDENCIES, JOB_IGNORE_REQUIREMENTS) ? TRANSACTION_IGNORE_REQUIREMENTS : 0) |
(mode == JOB_IGNORE_DEPENDENCIES ? TRANSACTION_IGNORE_ORDER : 0) |
- (mode == JOB_RESTART_DEPENDENCIES ? TRANSACTION_PROPAGATE_START_AS_RESTART : 0),
+ (mode == JOB_RESTART_DEPENDENCIES ? TRANSACTION_PROPAGATE_START_AS_RESTART : 0) |
+ extra_flags,
error);
if (r < 0)
return r;
return r;
assert(unit);
- return manager_add_job(m, type, unit, mode, affected_jobs, e, ret);
+ return manager_add_job_full(m, type, unit, mode, /* extra_flags = */ 0, affected_jobs, e, ret);
}
int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret) {
#include "job.h"
#include "path-lookup.h"
#include "show-status.h"
+#include "transaction.h"
#include "unit-name.h"
#include "unit.h"
int manager_load_startable_unit_or_warn(Manager *m, const char *name, const char *path, Unit **ret);
int manager_load_unit_from_dbus_path(Manager *m, const char *s, sd_bus_error *e, Unit **_u);
-int manager_add_job(Manager *m, JobType type, Unit *unit, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret);
-int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **_ret);
-int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret);
+int manager_add_job_full(
+ Manager *m,
+ JobType type,
+ Unit *unit,
+ JobMode mode,
+ TransactionAddFlags extra_flags,
+ Set *affected_jobs,
+ sd_bus_error *error,
+ Job **ret);
+static inline int manager_add_job(
+ Manager *m,
+ JobType type,
+ Unit *unit,
+ JobMode mode,
+ sd_bus_error *error,
+ Job **ret) {
+ return manager_add_job_full(m, type, unit, mode, 0, NULL, error, ret);
+}
+int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, sd_bus_error *e, Job **ret);
+int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret);
int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e);
void manager_clear_jobs(Manager *m);
goto fail;
}
- r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, &job);
+ r = manager_add_job(UNIT(p)->manager, JOB_START, trigger, JOB_REPLACE, &error, &job);
if (r < 0) {
log_unit_warning(UNIT(p), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
goto fail;
/* Any units that are bound to this service must also be restarted. We use JOB_START for ourselves
* but then set JOB_RESTART_DEPENDENCIES which will enqueue JOB_RESTART for those dependency jobs. */
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(s), JOB_RESTART_DEPENDENCIES, NULL, &error, NULL);
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(s), JOB_RESTART_DEPENDENCIES, &error, /* ret = */ NULL);
if (r < 0) {
log_unit_warning(UNIT(s), "Failed to schedule restart job: %s", bus_error_message(&error, r));
- service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ false);
- return;
+ return service_enter_dead(s, SERVICE_FAILURE_RESOURCES, /* allow_restart= */ false);
}
/* Count the jobs we enqueue for restarting. This counter is maintained as long as the unit isn't
goto fail;
}
- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, NULL, &error, NULL);
+ r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, &error, /* ret = */ NULL);
if (r < 0)
goto queue_error;
}
s->n_connections++;
- r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL);
+ r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, &error, /* ret = */ NULL);
if (r < 0) {
/* We failed to activate the new service, but it still exists. Let's make sure the
* service closes and forgets the connection fd again, immediately. */
goto fail;
}
- r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, &job);
+ r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, &error, &job);
if (r < 0) {
log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
goto fail;
#pragma once
typedef struct Transaction Transaction;
+typedef enum TransactionAddFlags TransactionAddFlags;
#include "hashmap.h"
#include "job.h"
struct Transaction {
/* Jobs to be added */
- Hashmap *jobs; /* Unit object => Job object list 1:1 */
- Job *anchor_job; /* the job the user asked for */
+ Hashmap *jobs; /* Unit object => Job object list 1:1 */
+ Job *anchor_job; /* The job the user asked for */
bool irreversible;
};
-Transaction *transaction_new(bool irreversible);
-Transaction *transaction_free(Transaction *tr);
-Transaction *transaction_abort_and_free(Transaction *tr);
+Transaction* transaction_new(bool irreversible);
+Transaction* transaction_free(Transaction *tr);
+Transaction* transaction_abort_and_free(Transaction *tr);
DEFINE_TRIVIAL_CLEANUP_FUNC(Transaction*, transaction_abort_and_free);
typedef enum TransactionAddFlags {
/* Indicate that we're in the recursion for processing UNIT_ATOM_PROPAGATE_STOP_GRACEFUL units */
TRANSACTION_PROCESS_PROPAGATE_STOP_GRACEFUL = 1 << 5,
+
+ _TRANSACTION_FLAGS_MASK_PUBLIC = 0,
} TransactionAddFlags;
void transaction_add_propagate_reload_jobs(
Transaction *tr,
- Unit *unit, Job *by,
+ Unit *unit,
+ Job *by,
TransactionAddFlags flags);
+int transaction_add_isolate_jobs(Transaction *tr, Manager *m);
+int transaction_add_triggering_jobs(Transaction *tr, Unit *u);
+
int transaction_add_job_and_dependencies(
Transaction *tr,
JobType type,
sd_bus_error *e);
int transaction_activate(Transaction *tr, Manager *m, JobMode mode, Set *affected, sd_bus_error *e);
-int transaction_add_isolate_jobs(Transaction *tr, Manager *m);
-int transaction_add_triggering_jobs(Transaction *tr, Unit *u);
UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_START_REPLACE) /* Requires= + BindsTo= */
if (!unit_has_dependency(u, UNIT_ATOM_AFTER, other) &&
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- (void) manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, NULL, NULL, NULL);
+ (void) manager_add_job(u->manager, JOB_START, other, JOB_REPLACE, /* error = */ NULL, /* ret = */ NULL);
UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_START_FAIL) /* Wants= */
if (!unit_has_dependency(u, UNIT_ATOM_AFTER, other) &&
!UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(other)))
- (void) manager_add_job(u->manager, JOB_START, other, JOB_FAIL, NULL, NULL, NULL);
+ (void) manager_add_job(u->manager, JOB_START, other, JOB_FAIL, /* error = */ NULL, /* ret = */ NULL);
UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_STOP_ON_START) /* Conflicts= (and inverse) */
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- (void) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL);
+ (void) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, /* error = */ NULL, /* ret = */ NULL);
}
static void retroactively_stop_dependencies(Unit *u) {
/* Pull down units which are bound to us recursively if enabled */
UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_RETROACTIVE_STOP_ON_STOP) /* BoundBy= */
if (!UNIT_IS_INACTIVE_OR_DEACTIVATING(unit_active_state(other)))
- (void) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, NULL, NULL, NULL);
+ (void) manager_add_job(u->manager, JOB_STOP, other, JOB_REPLACE, /* error = */ NULL, /* ret = */ NULL);
}
void unit_start_on_termination_deps(Unit *u, UnitDependencyAtom atom) {
if (n_jobs == 0)
log_unit_info(u, "Triggering %s dependencies.", dependency_name);
- r = manager_add_job(u->manager, JOB_START, other, job_mode, NULL, &error, NULL);
+ r = manager_add_job(u->manager, JOB_START, other, job_mode, &error, /* ret = */ NULL);
if (r < 0)
log_unit_warning_errno(u, r, "Failed to enqueue %s%s job, ignoring: %s",
dependency_name, other->id, bus_error_message(&error, r));
manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
printf("Test1: (Trivial)\n");
- r = manager_add_job(m, JOB_START, c, JOB_REPLACE, NULL, &err, &j);
+ r = manager_add_job(m, JOB_START, c, JOB_REPLACE, &err, &j);
if (sd_bus_error_is_set(&err))
log_error("error: %s: %s", err.name, err.message);
assert_se(r == 0);
manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
printf("Test2: (Cyclic Order, Unfixable)\n");
- assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_START, d, JOB_REPLACE, NULL, &j) == -EDEADLK);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
printf("Test3: (Cyclic Order, Fixable, Garbage Collector)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, e, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
printf("Test4: (Identical transaction)\n");
- assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, e, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
printf("Load3:\n");
manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
printf("Test5: (Colliding transaction, fail)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_START, g, JOB_FAIL, NULL, &j) == -EDEADLK);
printf("Test6: (Colliding transaction, replace)\n");
- assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, g, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
printf("Test7: (Unmergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_FAIL, NULL, &j) == -EDEADLK);
printf("Test8: (Mergeable job type, fail)\n");
- assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_RESTART, g, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
printf("Test9: (Unmergeable job type, replace)\n");
- assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_STOP, g, JOB_REPLACE, NULL, &j) == 0);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
printf("Load4:\n");
manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
printf("Test10: (Unmergeable job type of auxiliary job, fail)\n");
- assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
printf("Load5:\n");
manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
printf("Test11: (Start/stop job ordering, execution cycle)\n");
- assert_se(manager_add_job(m, JOB_START, i, JOB_FAIL, NULL, NULL, &j) == 0);
+ assert_se(manager_add_job(m, JOB_START, i, JOB_FAIL, NULL, &j) == 0);
assert_se(unit_has_job_type(a, JOB_STOP));
assert_se(unit_has_job_type(d, JOB_STOP));
assert_se(unit_has_job_type(b, JOB_START));
manager_dump_units(m, stdout, /* patterns= */ NULL, "\t");
printf("Test12: (Trivial cycle, Unfixable)\n");
- assert_se(manager_add_job(m, JOB_START, a_conj, JOB_REPLACE, NULL, NULL, &j) == -EDEADLK);
+ assert_se(manager_add_job(m, JOB_START, a_conj, JOB_REPLACE, NULL, &j) == -EDEADLK);
manager_dump_jobs(m, stdout, /* patterns= */ NULL, "\t");
assert_se(!hashmap_get(unit_get_dependencies(a, UNIT_PROPAGATES_RELOAD_TO), b));