From: Yu Watanabe Date: Wed, 3 May 2023 23:13:59 +0000 (+0900) Subject: journalctl: split out show() X-Git-Tag: v254-rc1~337^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e4c4a9db87f79292d79abae2afadaec240026829;p=thirdparty%2Fsystemd.git journalctl: split out show() No functional changes, just refactoring. --- diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 75af23ecc87..0f1a738fa54 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -2156,16 +2156,162 @@ static int wait_for_change(sd_journal *j, int poll_fd) { return 0; } +typedef struct Context { + sd_journal *journal; + bool need_seek; + bool since_seeked; + bool ellipsized; + bool previous_boot_id_valid; + sd_id128_t previous_boot_id; + sd_id128_t previous_boot_id_output; + dual_timestamp previous_ts_output; +} Context; + +static int show(Context *c) { + sd_journal *j; + int r, n_shown = 0; + + assert(c); + + j = ASSERT_PTR(c->journal); + + while (arg_lines < 0 || n_shown < arg_lines || arg_follow) { + int flags; + size_t highlight[2] = {}; + + if (c->need_seek) { + if (!arg_reverse) + r = sd_journal_next(j); + else + r = sd_journal_previous(j); + if (r < 0) + return log_error_errno(r, "Failed to iterate through journal: %m"); + if (r == 0) + break; + } + + if (arg_until_set && !arg_reverse && (arg_lines < 0 || arg_since_set)) { + /* If --lines= is set, we usually rely on the n_shown to tell us + * when to stop. However, if --since= is set too, we may end up + * having less than --lines= to output. In this case let's also + * check if the entry is in range. */ + + usec_t usec; + + r = sd_journal_get_realtime_usec(j, &usec); + if (r < 0) + return log_error_errno(r, "Failed to determine timestamp: %m"); + if (usec > arg_until) + break; + } + + if (arg_since_set && (arg_reverse || !c->since_seeked)) { + usec_t usec; + + r = sd_journal_get_realtime_usec(j, &usec); + if (r < 0) + return log_error_errno(r, "Failed to determine timestamp: %m"); + + if (usec < arg_since) { + if (arg_reverse) + break; /* Reached the earliest entry */ + + /* arg_lines >= 0 (!since_seeked): + * We jumped arg_lines back and it seems to be too much */ + r = sd_journal_seek_realtime_usec(j, arg_since); + if (r < 0) + return log_error_errno(r, "Failed to seek to date: %m"); + c->since_seeked = true; + + c->need_seek = true; + continue; + } + c->since_seeked = true; /* We're surely within the range of --since now */ + } + + if (!arg_merge && !arg_quiet) { + sd_id128_t boot_id; + + r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); + if (r >= 0) { + if (c->previous_boot_id_valid && + !sd_id128_equal(boot_id, c->previous_boot_id)) + printf("%s-- Boot "SD_ID128_FORMAT_STR" --%s\n", + ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id), ansi_normal()); + + c->previous_boot_id = boot_id; + c->previous_boot_id_valid = true; + } + } + + if (arg_compiled_pattern) { + const void *message; + size_t len; + + r = sd_journal_get_data(j, "MESSAGE", &message, &len); + if (r < 0) { + if (r == -ENOENT) { + c->need_seek = true; + continue; + } + + return log_error_errno(r, "Failed to get MESSAGE field: %m"); + } + + assert_se(message = startswith(message, "MESSAGE=")); + + r = pattern_matches_and_log(arg_compiled_pattern, message, + len - strlen("MESSAGE="), highlight); + if (r < 0) + return r; + if (r == 0) { + c->need_seek = true; + continue; + } + } + + flags = + arg_all * OUTPUT_SHOW_ALL | + arg_full * OUTPUT_FULL_WIDTH | + colors_enabled() * OUTPUT_COLOR | + arg_catalog * OUTPUT_CATALOG | + arg_utc * OUTPUT_UTC | + arg_no_hostname * OUTPUT_NO_HOSTNAME; + + r = show_journal_entry(stdout, j, arg_output, 0, flags, + arg_output_fields, highlight, &c->ellipsized, + &c->previous_ts_output, &c->previous_boot_id_output); + c->need_seek = true; + if (r == -EADDRNOTAVAIL) + break; + if (r < 0) + return r; + + n_shown++; + + /* If journalctl take a long time to process messages, and during that time journal file + * rotation occurs, a journalctl client will keep those rotated files open until it calls + * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below + * in the "following" case. By periodically calling sd_journal_process() during the processing + * loop we shrink the window of time a client instance has open file descriptors for rotated + * (deleted) journal files. */ + if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) { + r = sd_journal_process(j); + if (r < 0) + return log_error_errno(r, "Failed to process inotify events: %m"); + } + } + + return n_shown; +} + static int run(int argc, char *argv[]) { + bool need_seek = false, since_seeked = false, use_cursor = false, after_cursor = false; _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL; _cleanup_(umount_and_freep) char *mounted_dir = NULL; - bool previous_boot_id_valid = false, first_line = true, ellipsized = false, need_seek = false, since_seeked = false; - bool use_cursor = false, after_cursor = false; _cleanup_(sd_journal_closep) sd_journal *j = NULL; - sd_id128_t previous_boot_id = SD_ID128_NULL, previous_boot_id_output = SD_ID128_NULL; - dual_timestamp previous_ts_output = DUAL_TIMESTAMP_NULL; _cleanup_close_ int machine_fd = -EBADF; - int n_shown = 0, r, poll_fd = -EBADF; + int n_shown, r, poll_fd = -EBADF; setlocale(LC_ALL, ""); log_setup(); @@ -2574,148 +2720,41 @@ static int run(int argc, char *argv[]) { } } - for (;;) { - while (arg_lines < 0 || n_shown < arg_lines || (arg_follow && !first_line)) { - int flags; - size_t highlight[2] = {}; - - if (need_seek) { - if (!arg_reverse) - r = sd_journal_next(j); - else - r = sd_journal_previous(j); - if (r < 0) - return log_error_errno(r, "Failed to iterate through journal: %m"); - if (r == 0) - break; - } - - if (arg_until_set && !arg_reverse && (arg_lines < 0 || arg_since_set)) { - /* If --lines= is set, we usually rely on the n_shown to tell us - * when to stop. However, if --since= is set too, we may end up - * having less than --lines= to output. In this case let's also - * check if the entry is in range. */ - - usec_t usec; - - r = sd_journal_get_realtime_usec(j, &usec); - if (r < 0) - return log_error_errno(r, "Failed to determine timestamp: %m"); - if (usec > arg_until) - break; - } - - if (arg_since_set && (arg_reverse || !since_seeked)) { - usec_t usec; - - r = sd_journal_get_realtime_usec(j, &usec); - if (r < 0) - return log_error_errno(r, "Failed to determine timestamp: %m"); - - if (usec < arg_since) { - if (arg_reverse) - break; /* Reached the earliest entry */ - - /* arg_lines >= 0 (!since_seeked): - * We jumped arg_lines back and it seems to be too much */ - r = sd_journal_seek_realtime_usec(j, arg_since); - if (r < 0) - return log_error_errno(r, "Failed to seek to date: %m"); - since_seeked = true; - - need_seek = true; - continue; - } - since_seeked = true; /* We're surely within the range of --since now */ - } - - if (!arg_merge && !arg_quiet) { - sd_id128_t boot_id; - - r = sd_journal_get_monotonic_usec(j, NULL, &boot_id); - if (r >= 0) { - if (previous_boot_id_valid && - !sd_id128_equal(boot_id, previous_boot_id)) - printf("%s-- Boot "SD_ID128_FORMAT_STR" --%s\n", - ansi_highlight(), SD_ID128_FORMAT_VAL(boot_id), ansi_normal()); - - previous_boot_id = boot_id; - previous_boot_id_valid = true; - } - } - - if (arg_compiled_pattern) { - const void *message; - size_t len; - - r = sd_journal_get_data(j, "MESSAGE", &message, &len); - if (r < 0) { - if (r == -ENOENT) { - need_seek = true; - continue; - } - - return log_error_errno(r, "Failed to get MESSAGE field: %m"); - } + Context c = { + .journal = j, + .need_seek = need_seek, + .since_seeked = since_seeked, + }; - assert_se(message = startswith(message, "MESSAGE=")); + if (arg_follow) { + if (arg_lines != 0 || arg_since_set) { + r = show(&c); + if (r < 0) + return r; - r = pattern_matches_and_log(arg_compiled_pattern, message, - len - strlen("MESSAGE="), highlight); - if (r < 0) - return r; - if (r == 0) { - need_seek = true; - continue; - } - } + fflush(stdout); + } - flags = - arg_all * OUTPUT_SHOW_ALL | - arg_full * OUTPUT_FULL_WIDTH | - colors_enabled() * OUTPUT_COLOR | - arg_catalog * OUTPUT_CATALOG | - arg_utc * OUTPUT_UTC | - arg_no_hostname * OUTPUT_NO_HOSTNAME; - - r = show_journal_entry(stdout, j, arg_output, 0, flags, - arg_output_fields, highlight, &ellipsized, - &previous_ts_output, &previous_boot_id_output); - need_seek = true; - if (r == -EADDRNOTAVAIL) - break; + for (;;) { + r = wait_for_change(j, poll_fd); if (r < 0) return r; - n_shown++; - - /* If journalctl take a long time to process messages, and during that time journal file - * rotation occurs, a journalctl client will keep those rotated files open until it calls - * sd_journal_process(), which typically happens as a result of calling sd_journal_wait() below - * in the "following" case. By periodically calling sd_journal_process() during the processing - * loop we shrink the window of time a client instance has open file descriptors for rotated - * (deleted) journal files. */ - if ((n_shown % PROCESS_INOTIFY_INTERVAL) == 0) { - r = sd_journal_process(j); - if (r < 0) - return log_error_errno(r, "Failed to process inotify events: %m"); - } - } + r = show(&c); + if (r < 0) + return r; - if (!arg_follow) { - if (n_shown == 0 && !arg_quiet) - printf("-- No entries --\n"); - break; + fflush(stdout); } + } - fflush(stdout); - - r = wait_for_change(j, poll_fd); - if (r < 0) - return r; + r = show(&c); + if (r < 0) + return r; + n_shown = r; - first_line = false; - } + if (n_shown == 0 && !arg_quiet) + printf("-- No entries --\n"); r = update_cursor(j); if (r < 0)