diff options
author | Lennart Poettering <lennart@poettering.net> | 2012-06-09 10:32:38 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-06-17 00:03:12 +0200 |
commit | 089842938dd0f4080084044bb9a1a3b00137926a (patch) | |
tree | ba0e7b04ac312b2f29ee8f3fd99d8c0ed353a5b9 /src/journal | |
parent | 8db4213e7b38ebc54bfdc7215991cc23b9580e3a (diff) |
journal: expose and make use of cutoff times of journal
This helps explaining when the log output of "systemctl status" is
incomplete because the logs got rotated since the service was started.
Diffstat (limited to 'src/journal')
-rw-r--r-- | src/journal/journal-def.h | 4 | ||||
-rw-r--r-- | src/journal/journal-file.c | 72 | ||||
-rw-r--r-- | src/journal/journal-file.h | 3 | ||||
-rw-r--r-- | src/journal/journalctl.c | 20 | ||||
-rw-r--r-- | src/journal/libsystemd-journal.sym | 6 | ||||
-rw-r--r-- | src/journal/sd-journal.c | 75 |
6 files changed, 178 insertions, 2 deletions
diff --git a/src/journal/journal-def.h b/src/journal/journal-def.h index 86aef8f372..b30ae79683 100644 --- a/src/journal/journal-def.h +++ b/src/journal/journal-def.h @@ -160,8 +160,8 @@ _packed_ struct Header { uint8_t state; uint8_t reserved[7]; sd_id128_t file_id; - sd_id128_t machine_id; - sd_id128_t boot_id; + sd_id128_t machine_id; /* last writer */ + sd_id128_t boot_id; /* last writer */ sd_id128_t seqnum_id; le64_t header_size; le64_t arena_size; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 9cec140f58..73420d9c1b 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -183,6 +183,7 @@ static int journal_file_verify_header(JournalFile *f) { if (state == STATE_ONLINE) log_debug("Journal file %s is already online. Assuming unclean closing. Ignoring.", f->path); + /* FIXME: immediately rotate */ else if (state == STATE_ARCHIVED) return -ESHUTDOWN; else if (state != STATE_OFFLINE) @@ -2284,3 +2285,74 @@ void journal_default_metrics(JournalMetrics *m, int fd) { format_bytes(c, sizeof(c), m->min_size), format_bytes(d, sizeof(d), m->keep_free)); } + +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to) { + Object *o; + int r; + + assert(f); + assert(from || to); + + if (from) { + r = journal_file_next_entry(f, NULL, 0, DIRECTION_DOWN, &o, NULL); + if (r <= 0) + return r; + + *from = le64toh(o->entry.realtime); + } + + if (to) { + r = journal_file_next_entry(f, NULL, 0, DIRECTION_UP, &o, NULL); + if (r <= 0) + return r; + + *to = le64toh(o->entry.realtime); + } + + return 1; +} + +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot_id, usec_t *from, usec_t *to) { + char t[9+32+1] = "_BOOT_ID="; + Object *o; + uint64_t p; + int r; + + assert(f); + assert(from || to); + + sd_id128_to_string(boot_id, t + 9); + + r = journal_file_find_data_object(f, t, strlen(t), &o, &p); + if (r <= 0) + return r; + + if (le64toh(o->data.n_entries) <= 0) + return 0; + + if (from) { + r = journal_file_move_to_object(f, OBJECT_ENTRY, le64toh(o->data.entry_offset), &o); + if (r < 0) + return r; + + *from = le64toh(o->entry.monotonic); + } + + if (to) { + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); + if (r < 0) + return r; + + r = generic_array_get_plus_one(f, + le64toh(o->data.entry_offset), + le64toh(o->data.entry_array_offset), + le64toh(o->data.n_entries)-1, + &o, NULL); + if (r <= 0) + return r; + + *to = le64toh(o->entry.monotonic); + } + + return 1; +} diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index aeb6d46c79..a9925c0754 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -125,4 +125,7 @@ void journal_file_post_change(JournalFile *f); void journal_default_metrics(JournalMetrics *m, int fd); +int journal_file_get_cutoff_realtime_usec(JournalFile *f, usec_t *from, usec_t *to); +int journal_file_get_cutoff_monotonic_usec(JournalFile *f, sd_id128_t boot, usec_t *from, usec_t *to); + #endif diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index 9d4403267e..e9d918a733 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -281,6 +281,26 @@ int main(int argc, char *argv[]) { goto finish; } + if (!arg_quiet) { + usec_t start, end; + char start_buf[FORMAT_TIMESTAMP_MAX], end_buf[FORMAT_TIMESTAMP_MAX]; + + r = sd_journal_get_cutoff_realtime_usec(j, &start, &end); + if (r < 0) { + log_error("Failed to get cutoff: %s", strerror(-r)); + goto finish; + } + + if (r > 0) { + if (arg_follow) + printf("Logs begin at %s.\n", format_timestamp(start_buf, sizeof(start_buf), start)); + else + printf("Logs begin at %s, end at %s.\n", + format_timestamp(start_buf, sizeof(start_buf), start), + format_timestamp(end_buf, sizeof(end_buf), end)); + } + } + if (arg_lines >= 0) { r = sd_journal_seek_tail(j); if (r < 0) { diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index 74bd298fdc..d291084262 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -51,3 +51,9 @@ global: sd_journal_send_with_location; sd_journal_sendv_with_location; } LIBSYSTEMD_JOURNAL_38; + +LIBSYSTEMD_JOURNAL_184 { +global: + sd_journal_get_cutoff_realtime_usec; + sd_journal_get_cutoff_monotonic_usec; +} LIBSYSTEMD_JOURNAL_183; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 9f46f5c6aa..5ed8c3f7a5 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -1620,6 +1620,81 @@ _public_ int sd_journal_process(sd_journal *j) { } } +_public_ int sd_journal_get_cutoff_realtime_usec(sd_journal *j, uint64_t *from, uint64_t *to) { + Iterator i; + JournalFile *f; + bool first = true; + int r; + + if (!j) + return -EINVAL; + if (!from && !to) + return -EINVAL; + + HASHMAP_FOREACH(f, j->files, i) { + usec_t fr, t; + + r = journal_file_get_cutoff_realtime_usec(f, &fr, &t); + if (r < 0) + return r; + if (r == 0) + continue; + + if (first) { + if (from) + *from = fr; + if (to) + *to = t; + first = false; + } else { + if (from) + *from = MIN(fr, *from); + if (to) + *to = MIN(t, *to); + } + } + + return first ? 0 : 1; +} + +_public_ int sd_journal_get_cutoff_monotonic_usec(sd_journal *j, sd_id128_t boot_id, uint64_t *from, uint64_t *to) { + Iterator i; + JournalFile *f; + bool first = true; + int r; + + if (!j) + return -EINVAL; + if (!from && !to) + return -EINVAL; + + HASHMAP_FOREACH(f, j->files, i) { + usec_t fr, t; + + r = journal_file_get_cutoff_monotonic_usec(f, boot_id, &fr, &t); + if (r < 0) + return r; + if (r == 0) + continue; + + if (first) { + if (from) + *from = fr; + if (to) + *to = t; + first = false; + } else { + if (from) + *from = MIN(fr, *from); + if (to) + *to = MIN(t, *to); + } + } + + return first ? 0 : 1; +} + + /* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */ /* if (!j) */ /* return -EINVAL; */ |