From 84653d99fa2d9539f5e2165e502cf66b2a6ebf4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 22 Feb 2019 09:18:42 +0100 Subject: [PATCH 1/2] analyze: split out loop innards into a separate function This was intended to be just a refactoring, but it also fixes a minor bug: after printing "never", we would skip subsequent expressions: $ systemd-analyze calendar --iterations=20 @0 @1 systemd-analyze calendar --iterations=20 @0 @1 Original form: @0 Normalized form: 1970-01-01 00:00:00 UTC Next elapse: never (the second expression was skipped). --- src/analyze/analyze.c | 128 +++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 65 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 064525d64d..337089a40d 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -1671,78 +1671,76 @@ static int dump_timespan(int argc, char *argv[], void *userdata) { return EXIT_SUCCESS; } +static int test_calendar_one(usec_t n, const char *p) { + _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL; + _cleanup_free_ char *t = NULL; + int r; + + r = calendar_spec_from_string(p, &spec); + if (r < 0) + return log_error_errno(r, "Failed to parse calendar specification '%s': %m", p); + + r = calendar_spec_normalize(spec); + if (r < 0) + return log_error_errno(r, "Failed to normalize calendar specification '%s': %m", p); + + r = calendar_spec_to_string(spec, &t); + if (r < 0) + return log_error_errno(r, "Failed to format calendar specification '%s': %m", p); + + if (!streq(t, p)) + printf(" Original form: %s\n", p); + + printf("Normalized form: %s\n", t); + + for (unsigned i = 0; i < arg_iterations; i++) { + char buffer[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESTAMP_RELATIVE_MAX)]; + usec_t next; + + r = calendar_spec_next_usec(spec, n, &next); + if (r == -ENOENT) { + if (i == 0) + printf(" Next elapse: never\n"); + return 0; + } + if (r < 0) + return log_error_errno(r, "Failed to determine next elapse for '%s': %m", p); + + if (i == 0) + printf(" Next elapse: %s\n", format_timestamp(buffer, sizeof(buffer), next)); + else { + int k = DECIMAL_STR_WIDTH(i+1); + + if (k < 8) + k = 8 - k; + else + k = 0; + + printf("%*sIter. #%u: %s\n", k, "", i+1, format_timestamp(buffer, sizeof(buffer), next)); + } + + if (!in_utc_timezone()) + printf(" (in UTC): %s\n", format_timestamp_utc(buffer, sizeof(buffer), next)); + + printf(" From now: %s\n", format_timestamp_relative(buffer, sizeof(buffer), next)); + + n = next; + } + + return 0; +} + static int test_calendar(int argc, char *argv[], void *userdata) { int ret = 0, r; char **p; usec_t n; - n = now(CLOCK_REALTIME); + n = now(CLOCK_REALTIME); /* We want to use the same "base" for all expressions */ STRV_FOREACH(p, strv_skip(argv, 1)) { - _cleanup_(calendar_spec_freep) CalendarSpec *spec = NULL; - _cleanup_free_ char *t = NULL; - unsigned i; - - r = calendar_spec_from_string(*p, &spec); - if (r < 0) { - ret = log_error_errno(r, "Failed to parse calendar specification '%s': %m", *p); - continue; - } - - r = calendar_spec_normalize(spec); - if (r < 0) { - ret = log_error_errno(r, "Failed to normalize calendar specification '%s': %m", *p); - continue; - } - - r = calendar_spec_to_string(spec, &t); - if (r < 0) { - ret = log_error_errno(r, "Failed to format calendar specification '%s': %m", *p); - continue; - } - - if (!streq(t, *p)) - printf(" Original form: %s\n", *p); - - printf("Normalized form: %s\n", t); - - for (i = 0; i < arg_iterations; i++) { - char buffer[CONST_MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESTAMP_RELATIVE_MAX)]; - usec_t next; - - r = calendar_spec_next_usec(spec, n, &next); - if (r == -ENOENT) { - if (i > 0) - break; - - printf(" Next elapse: never\n"); - return ret; - } - if (r < 0) { - ret = log_error_errno(r, "Failed to determine next elapse for '%s': %m", *p); - break; - } - - if (i == 0) - printf(" Next elapse: %s\n", format_timestamp(buffer, sizeof(buffer), next)); - else { - int k = DECIMAL_STR_WIDTH(i+1); - - if (k < 8) - k = 8 - k; - else - k = 0; - - printf("%*sIter. #%u: %s\n", k, "", i+1, format_timestamp(buffer, sizeof(buffer), next)); - } - - if (!in_utc_timezone()) - printf(" (in UTC): %s\n", format_timestamp_utc(buffer, sizeof(buffer), next)); - - printf(" From now: %s\n", format_timestamp_relative(buffer, sizeof(buffer), next)); - - n = next; - } + r = test_calendar_one(n, *p); + if (ret == 0 && r < 0) + ret = r; if (*(p+1)) putchar('\n'); From deed4d50a2e437493d95be0f2e0b845222fff702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Fri, 22 Feb 2019 09:29:23 +0100 Subject: [PATCH 2/2] analyze: add color highlighting when printing calendar elapses With multiple iterations, I found it hard to pick out the interesting bits in the column of text. I tried plain highlighting first, but it doesn't seem enough. But blue/yellow makes it easy to jump to the right iteration. --- src/analyze/analyze.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c index 337089a40d..77adbed83d 100644 --- a/src/analyze/analyze.c +++ b/src/analyze/analyze.c @@ -1700,14 +1700,16 @@ static int test_calendar_one(usec_t n, const char *p) { r = calendar_spec_next_usec(spec, n, &next); if (r == -ENOENT) { if (i == 0) - printf(" Next elapse: never\n"); + printf(" Next elapse: %snever%s\n", + ansi_highlight_yellow(), ansi_normal()); return 0; } if (r < 0) return log_error_errno(r, "Failed to determine next elapse for '%s': %m", p); if (i == 0) - printf(" Next elapse: %s\n", format_timestamp(buffer, sizeof(buffer), next)); + printf(" Next elapse: %s%s%s\n", + ansi_highlight_blue(), format_timestamp(buffer, sizeof(buffer), next), ansi_normal()); else { int k = DECIMAL_STR_WIDTH(i+1); @@ -1716,7 +1718,9 @@ static int test_calendar_one(usec_t n, const char *p) { else k = 0; - printf("%*sIter. #%u: %s\n", k, "", i+1, format_timestamp(buffer, sizeof(buffer), next)); + printf("%*sIter. #%u: %s%s%s\n", + k, "", i+1, + ansi_highlight_blue(), format_timestamp(buffer, sizeof(buffer), next), ansi_normal()); } if (!in_utc_timezone())