summaryrefslogtreecommitdiff
path: root/src/systemctl/systemctl.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-11-16 21:16:13 -0500
committerGitHub <noreply@github.com>2016-11-16 21:16:13 -0500
commit4a58145f0f06970cc93377e034a9e27b3c0283ad (patch)
tree5917ecbde63fb2082ff78d85ed73a227b0fdeb5f /src/systemctl/systemctl.c
parentc4027307a29c6e234fd4f05b212b45ef72a47072 (diff)
parent7d992a6ede8034a36699c25c19f03e95476eedac (diff)
Merge pull request #4678 from poettering/gc-device
Automatically GC device jobs when there's no need to keep them in the job queue anymore. Implement systemctl list-jobs --before/--after. Allow systemd-run -p After/Before/Wants/Requires= ...
Diffstat (limited to 'src/systemctl/systemctl.c')
-rw-r--r--src/systemctl/systemctl.c59
1 files changed, 57 insertions, 2 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 49a97ff268..db836639b5 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -173,6 +173,8 @@ static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_plain = false;
static bool arg_firmware_setup = false;
static bool arg_now = false;
+static bool arg_jobs_before = false;
+static bool arg_jobs_after = false;
static int daemon_reload(int argc, char *argv[], void* userdata);
static int trivial_method(int argc, char *argv[], void *userdata);
@@ -204,6 +206,9 @@ static int acquire_bus(BusFocus focus, sd_bus **ret) {
if (arg_transport != BUS_TRANSPORT_LOCAL)
focus = BUS_FULL;
+ if (getenv_bool("SYSTEMCTL_FORCE_BUS") > 0)
+ focus = BUS_FULL;
+
if (!busses[focus]) {
bool user;
@@ -2192,12 +2197,55 @@ finish:
return r;
}
+static void output_waiting_jobs(sd_bus *bus, uint32_t id, const char *method, const char *prefix) {
+ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
+ const char *name, *type, *state, *job_path, *unit_path;
+ uint32_t other_id;
+ int r;
+
+ assert(bus);
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ method,
+ &error,
+ &reply,
+ "u", id);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to get waiting jobs for job %" PRIu32, id);
+ return;
+ }
+
+ r = sd_bus_message_enter_container(reply, 'a', "(usssoo)");
+ if (r < 0) {
+ bus_log_parse_error(r);
+ return;
+ }
+
+ while ((r = sd_bus_message_read(reply, "(usssoo)", &other_id, &name, &type, &state, &job_path, &unit_path)) > 0)
+ printf("%s%u (%s/%s)\n", prefix, other_id, name, type);
+ if (r < 0) {
+ bus_log_parse_error(r);
+ return;
+ }
+
+ r = sd_bus_message_exit_container(reply);
+ if (r < 0) {
+ bus_log_parse_error(r);
+ return;
+ }
+}
+
struct job_info {
uint32_t id;
const char *name, *type, *state;
};
-static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipped) {
+static void output_jobs_list(sd_bus *bus, const struct job_info* jobs, unsigned n, bool skipped) {
unsigned id_len, unit_len, type_len, state_len;
const struct job_info *j;
const char *on, *off;
@@ -2259,6 +2307,11 @@ static void output_jobs_list(const struct job_info* jobs, unsigned n, bool skipp
on, unit_len, e ? e : j->name, off,
type_len, j->type,
on, state_len, j->state, off);
+
+ if (arg_jobs_after)
+ output_waiting_jobs(bus, j->id, "GetJobAfter", "\tA job waits for this job: ");
+ if (arg_jobs_before)
+ output_waiting_jobs(bus, j->id, "GetJobBefore", "\tThis job waits for a job: ");
}
if (!arg_no_legend) {
@@ -2327,7 +2380,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
pager_open(arg_no_pager, false);
- output_jobs_list(jobs, c, skipped);
+ output_jobs_list(bus, jobs, c, skipped);
return 0;
}
@@ -7302,10 +7355,12 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
case ARG_AFTER:
arg_dependency = DEPENDENCY_AFTER;
+ arg_jobs_after = true;
break;
case ARG_BEFORE:
arg_dependency = DEPENDENCY_BEFORE;
+ arg_jobs_before = true;
break;
case ARG_SHOW_TYPES: