diff options
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; */ |