systemctl: show waiting jobs when "systemctl list-jobs --after/--before" is called

Let's expose the new bus functions we added in the previous commit in
systemctl.
This commit is contained in:
Lennart Poettering 2016-11-16 16:44:05 +01:00
parent 15ea79f85c
commit 82948f6c8e
2 changed files with 66 additions and 2 deletions

View file

@ -209,6 +209,10 @@
<varname>RequiresMountsFor=</varname>). Both explicitly <varname>RequiresMountsFor=</varname>). Both explicitly
and implicitly introduced dependencies are shown with and implicitly introduced dependencies are shown with
<command>list-dependencies</command>.</para> <command>list-dependencies</command>.</para>
<para>When passed to the <command>list-jobs</command> command, for each printed job show which other jobs are
waiting for it. May be combined with <option>--before</option> to show both the jobs waiting for each job as
well as all jobs each job is waiting for.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -220,6 +224,10 @@
units that are ordered after the specified unit. In other units that are ordered after the specified unit. In other
words, recursively list units following the words, recursively list units following the
<varname>Before=</varname> dependency.</para> <varname>Before=</varname> dependency.</para>
<para>When passed to the <command>list-jobs</command> command, for each printed job show which other jobs it
is waiting for. May be combined with <option>--after</option> to show both the jobs waiting for each job as
well as all jobs each job is waiting for.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -1388,6 +1396,10 @@ kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service
<para>List jobs that are in progress. If one or more <para>List jobs that are in progress. If one or more
<replaceable>PATTERN</replaceable>s are specified, only <replaceable>PATTERN</replaceable>s are specified, only
jobs for units matching one of them are shown.</para> jobs for units matching one of them are shown.</para>
<para>When combined with <option>--after</option> or <option>--before</option> the list is augmented with
information on which other job each job is waiting for, and which other jobs are waiting for it, see
above.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View file

@ -173,6 +173,8 @@ static OutputMode arg_output = OUTPUT_SHORT;
static bool arg_plain = false; static bool arg_plain = false;
static bool arg_firmware_setup = false; static bool arg_firmware_setup = false;
static bool arg_now = 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 daemon_reload(int argc, char *argv[], void* userdata);
static int trivial_method(int argc, char *argv[], void *userdata); static int trivial_method(int argc, char *argv[], void *userdata);
@ -2195,12 +2197,55 @@ finish:
return r; 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 { struct job_info {
uint32_t id; uint32_t id;
const char *name, *type, *state; 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; unsigned id_len, unit_len, type_len, state_len;
const struct job_info *j; const struct job_info *j;
const char *on, *off; const char *on, *off;
@ -2262,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, on, unit_len, e ? e : j->name, off,
type_len, j->type, type_len, j->type,
on, state_len, j->state, off); 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) { if (!arg_no_legend) {
@ -2330,7 +2380,7 @@ static int list_jobs(int argc, char *argv[], void *userdata) {
pager_open(arg_no_pager, false); pager_open(arg_no_pager, false);
output_jobs_list(jobs, c, skipped); output_jobs_list(bus, jobs, c, skipped);
return 0; return 0;
} }
@ -7305,10 +7355,12 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
case ARG_AFTER: case ARG_AFTER:
arg_dependency = DEPENDENCY_AFTER; arg_dependency = DEPENDENCY_AFTER;
arg_jobs_after = true;
break; break;
case ARG_BEFORE: case ARG_BEFORE:
arg_dependency = DEPENDENCY_BEFORE; arg_dependency = DEPENDENCY_BEFORE;
arg_jobs_before = true;
break; break;
case ARG_SHOW_TYPES: case ARG_SHOW_TYPES: