chiark / gitweb /
journal: use tail/head timestamps from header for cutoff logic
[elogind.git] / src / journal / journal-file.c
index db64a32e615935d2dc5434396ccda4d19de34f77..a110a0090f33c217ca6e55354475adbcd3893733 100644 (file)
@@ -1212,8 +1212,15 @@ static int generic_array_bisect(JournalFile *f,
                         }
                 }
 
-                if (k > n)
+                if (k > n) {
+                        if (direction == DIRECTION_UP) {
+                                i = n;
+                                subtract_one = true;
+                                goto found;
+                        }
+
                         return 0;
+                }
 
                 last_p = lp;
 
@@ -1246,7 +1253,7 @@ found:
                 *offset = p;
 
         if (idx)
-                *idx = t + i - (subtract_one ? 1 : 0);
+                *idx = t + i + (subtract_one ? -1 : 0);
 
         return 1;
 }
@@ -1263,6 +1270,8 @@ static int generic_array_bisect_plus_one(JournalFile *f,
                                          uint64_t *idx) {
 
         int r;
+        bool step_back = false;
+        Object *o;
 
         assert(f);
         assert(test_object);
@@ -1275,34 +1284,81 @@ static int generic_array_bisect_plus_one(JournalFile *f,
         r = test_object(f, extra, needle);
         if (r < 0)
                 return r;
-        else if (r == TEST_FOUND) {
-                Object *o;
 
-                r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
-                if (r < 0)
-                        return r;
+        if (r == TEST_FOUND)
+                r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
 
-                if (ret)
-                        *ret = o;
+        /* if we are looking with DIRECTION_UP then we need to first
+           see if in the actual array there is a matching entry, and
+           return the last one of that. But if there isn't any we need
+           to return this one. Hence remember this, and return it
+           below. */
+        if (r == TEST_LEFT)
+                step_back = direction == DIRECTION_UP;
 
-                if (offset)
-                        *offset = extra;
-
-                if (idx)
-                        *idx = 0;
-
-                return 1;
-        } else if (r == TEST_RIGHT)
-                return 0;
+        if (r == TEST_RIGHT) {
+                if (direction == DIRECTION_DOWN)
+                        goto found;
+                else
+                        return 0;
+        }
 
         r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx);
 
-        if (r > 0)
+        if (r == 0 && step_back)
+                goto found;
+
+        if (r > 0 && idx)
                 (*idx) ++;
 
         return r;
+
+found:
+        r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
+        if (r < 0)
+                return r;
+
+        if (ret)
+                *ret = o;
+
+        if (offset)
+                *offset = extra;
+
+        if (idx)
+                *idx = 0;
+
+        return 1;
+}
+
+static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) {
+        assert(f);
+        assert(p > 0);
+
+        if (p == needle)
+                return TEST_FOUND;
+        else if (p < needle)
+                return TEST_LEFT;
+        else
+                return TEST_RIGHT;
 }
 
+int journal_file_move_to_entry_by_offset(
+                JournalFile *f,
+                uint64_t p,
+                direction_t direction,
+                Object **ret,
+                uint64_t *offset) {
+
+        return generic_array_bisect(f,
+                                    le64toh(f->header->entry_array_offset),
+                                    le64toh(f->header->n_entries),
+                                    p,
+                                    test_object_offset,
+                                    direction,
+                                    ret, offset, NULL);
+}
+
+
 static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
         Object *o;
         int r;
@@ -1404,12 +1460,13 @@ int journal_file_move_to_entry_by_monotonic(
         Object *o;
         int r;
 
-        sd_id128_to_string(boot_id, t + 9);
+        assert(f);
 
+        sd_id128_to_string(boot_id, t + 9);
         r = journal_file_find_data_object(f, t, strlen(t), &o, NULL);
         if (r < 0)
                 return r;
-        else if (r == 0)
+        if (r == 0)
                 return -ENOENT;
 
         return generic_array_bisect_plus_one(f,
@@ -1422,18 +1479,6 @@ int journal_file_move_to_entry_by_monotonic(
                                              ret, offset, NULL);
 }
 
-static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle) {
-        assert(f);
-        assert(p > 0);
-
-        if (p == needle)
-                return TEST_FOUND;
-        else if (p < needle)
-                return TEST_LEFT;
-        else
-                return TEST_RIGHT;
-}
-
 int journal_file_next_entry(
                 JournalFile *f,
                 Object *o, uint64_t p,
@@ -1598,6 +1643,119 @@ int journal_file_next_entry_for_data(
                                           ret, offset);
 }
 
+int journal_file_move_to_entry_by_offset_for_data(
+                JournalFile *f,
+                uint64_t data_offset,
+                uint64_t p,
+                direction_t direction,
+                Object **ret, uint64_t *offset) {
+
+        int r;
+        Object *d;
+
+        assert(f);
+
+        r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
+        if (r < 0)
+                return r;
+
+        return generic_array_bisect_plus_one(f,
+                                             le64toh(d->data.entry_offset),
+                                             le64toh(d->data.entry_array_offset),
+                                             le64toh(d->data.n_entries),
+                                             p,
+                                             test_object_offset,
+                                             direction,
+                                             ret, offset, NULL);
+}
+
+int journal_file_move_to_entry_by_monotonic_for_data(
+                JournalFile *f,
+                uint64_t data_offset,
+                sd_id128_t boot_id,
+                uint64_t monotonic,
+                direction_t direction,
+                Object **ret, uint64_t *offset) {
+
+        char t[9+32+1] = "_BOOT_ID=";
+        Object *o, *d;
+        int r;
+        uint64_t b, z;
+
+        assert(f);
+
+        /* First, seek by time */
+        sd_id128_to_string(boot_id, t + 9);
+        r = journal_file_find_data_object(f, t, strlen(t), &o, &b);
+        if (r < 0)
+                return r;
+        if (r == 0)
+                return -ENOENT;
+
+        r = generic_array_bisect_plus_one(f,
+                                          le64toh(o->data.entry_offset),
+                                          le64toh(o->data.entry_array_offset),
+                                          le64toh(o->data.n_entries),
+                                          monotonic,
+                                          test_object_monotonic,
+                                          direction,
+                                          NULL, &z, NULL);
+        if (r <= 0)
+                return r;
+
+        /* And now, continue seeking until we find an entry that
+         * exists in both bisection arrays */
+
+        for (;;) {
+                Object *qo;
+                uint64_t p, q;
+
+                r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
+                if (r < 0)
+                        return r;
+
+                r = generic_array_bisect_plus_one(f,
+                                                  le64toh(d->data.entry_offset),
+                                                  le64toh(d->data.entry_array_offset),
+                                                  le64toh(d->data.n_entries),
+                                                  z,
+                                                  test_object_offset,
+                                                  direction,
+                                                  NULL, &p, NULL);
+                if (r <= 0)
+                        return r;
+
+                r = journal_file_move_to_object(f, OBJECT_DATA, b, &o);
+                if (r < 0)
+                        return r;
+
+                r = generic_array_bisect_plus_one(f,
+                                                  le64toh(o->data.entry_offset),
+                                                  le64toh(o->data.entry_array_offset),
+                                                  le64toh(o->data.n_entries),
+                                                  p,
+                                                  test_object_offset,
+                                                  direction,
+                                                  &qo, &q, NULL);
+
+                if (r <= 0)
+                        return r;
+
+                if (p == q) {
+                        if (ret)
+                                *ret = qo;
+                        if (offset)
+                                *offset = q;
+
+                        return 1;
+                }
+
+                z = q;
+        }
+
+        return 0;
+}
+
 int journal_file_move_to_entry_by_seqnum_for_data(
                 JournalFile *f,
                 uint64_t data_offset,
@@ -1608,8 +1766,10 @@ int journal_file_move_to_entry_by_seqnum_for_data(
         Object *d;
         int r;
 
+        assert(f);
+
         r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
-        if (r <= 0)
+        if (r < 0)
                 return r;
 
         return generic_array_bisect_plus_one(f,
@@ -1632,8 +1792,10 @@ int journal_file_move_to_entry_by_realtime_for_data(
         Object *d;
         int r;
 
+        assert(f);
+
         r = journal_file_move_to_object(f, OBJECT_DATA, data_offset, &d);
-        if (r <= 0)
+        if (r < 0)
                 return r;
 
         return generic_array_bisect_plus_one(f,
@@ -2150,9 +2312,6 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
             ts.monotonic < le64toh(to->header->tail_entry_monotonic))
                 return -EINVAL;
 
-        if (ts.realtime < le64toh(to->header->tail_entry_realtime))
-                return -EINVAL;
-
         n = journal_file_entry_n_items(o);
         items = alloca(sizeof(EntryItem) * n);
 
@@ -2287,26 +2446,21 @@ void journal_default_metrics(JournalMetrics *m, int fd) {
 }
 
 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;
+                if (f->header->head_entry_realtime == 0)
+                        return -ENOENT;
 
-                *from = le64toh(o->entry.realtime);
+                *from = le64toh(f->header->head_entry_realtime);
         }
 
         if (to) {
-                r = journal_file_next_entry(f, NULL, 0, DIRECTION_UP, &o, NULL);
-                if (r <= 0)
-                        return r;
+                if (f->header->tail_entry_realtime == 0)
+                        return -ENOENT;
 
-                *to = le64toh(o->entry.realtime);
+                *to = le64toh(f->header->tail_entry_realtime);
         }
 
         return 1;