chiark / gitweb /
journal: fix bisection logic for first entry
[elogind.git] / src / journal / journal-file.c
index a60a896c2f3ad7370f43abf8ba97514d0c9f20d2..c468b226972d1ebffe02177584b384aaea642a6c 100644 (file)
@@ -67,9 +67,12 @@ void journal_file_close(JournalFile *f) {
 
         assert(f);
 
-        if (f->header && f->writable)
-                f->header->state = STATE_OFFLINE;
+        if (f->header) {
+                if (f->writable)
+                        f->header->state = STATE_OFFLINE;
 
+                munmap(f->header, PAGE_ALIGN(sizeof(Header)));
+        }
 
         for (t = 0; t < _WINDOW_MAX; t++)
                 if (f->windows[t].ptr)
@@ -96,7 +99,7 @@ static int journal_file_init_header(JournalFile *f, JournalFile *template) {
 
         zero(h);
         memcpy(h.signature, signature, 8);
-        h.arena_offset = htole64(ALIGN64(sizeof(h)));
+        h.header_size = htole64(ALIGN64(sizeof(h)));
 
         r = sd_id128_randomize(&h.file_id);
         if (r < 0)
@@ -158,7 +161,10 @@ static int journal_file_verify_header(JournalFile *f) {
                 return -EPROTONOSUPPORT;
 #endif
 
-        if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->arena_offset) + le64toh(f->header->arena_size)))
+        if (f->header->header_size != htole64(ALIGN64(sizeof(*(f->header)))))
+                return -EBADMSG;
+
+        if ((uint64_t) f->last_stat.st_size < (le64toh(f->header->header_size) + le64toh(f->header->arena_size)))
                 return -ENODATA;
 
         if (f->writable) {
@@ -177,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)
@@ -188,6 +195,7 @@ static int journal_file_verify_header(JournalFile *f) {
 
 static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size) {
         uint64_t old_size, new_size;
+        int r;
 
         assert(f);
 
@@ -196,12 +204,12 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
          * ourselves */
 
         old_size =
-                le64toh(f->header->arena_offset) +
+                le64toh(f->header->header_size) +
                 le64toh(f->header->arena_size);
 
         new_size = PAGE_ALIGN(offset + size);
-        if (new_size < le64toh(f->header->arena_offset))
-                new_size = le64toh(f->header->arena_offset);
+        if (new_size < le64toh(f->header->header_size))
+                new_size = le64toh(f->header->header_size);
 
         if (new_size <= old_size)
                 return 0;
@@ -232,13 +240,14 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
         /* Note that the glibc fallocate() fallback is very
            inefficient, hence we try to minimize the allocation area
            as we can. */
-        if (posix_fallocate(f->fd, old_size, new_size - old_size) < 0)
-                return -errno;
+        r = posix_fallocate(f->fd, old_size, new_size - old_size);
+        if (r != 0)
+                return -r;
 
         if (fstat(f->fd, &f->last_stat) < 0)
                 return -errno;
 
-        f->header->arena_size = htole64(new_size - le64toh(f->header->arena_offset));
+        f->header->arena_size = htole64(new_size - le64toh(f->header->header_size));
 
         return 0;
 }
@@ -452,7 +461,7 @@ static int journal_file_append_object(JournalFile *f, int type, uint64_t size, O
 
         p = le64toh(f->header->tail_object_offset);
         if (p == 0)
-                p = le64toh(f->header->arena_offset);
+                p = le64toh(f->header->header_size);
         else {
                 r = journal_file_move_to_object(f, -1, p, &tail);
                 if (r < 0)
@@ -588,7 +597,7 @@ static int journal_file_link_data(JournalFile *f, Object *o, uint64_t offset, ui
         o->data.n_entries = 0;
 
         h = hash % (le64toh(f->header->data_hash_table_size) / sizeof(HashItem));
-        p = le64toh(f->data_hash_table[h].head_hash_offset);
+        p = le64toh(f->data_hash_table[h].tail_hash_offset);
         if (p == 0) {
                 /* Only entry in the hash table is easy */
                 f->data_hash_table[h].head_hash_offset = htole64(offset);
@@ -1266,7 +1275,11 @@ 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) {
+
+        if (r == TEST_FOUND)
+                r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
+
+        if (r == TEST_RIGHT) {
                 Object *o;
 
                 r = journal_file_move_to_object(f, OBJECT_ENTRY, extra, &o);
@@ -1283,8 +1296,7 @@ static int generic_array_bisect_plus_one(JournalFile *f,
                         *idx = 0;
 
                 return 1;
-        } else if (r == TEST_RIGHT)
-                return 0;
+        }
 
         r = generic_array_bisect(f, first, n-1, needle, test_object, direction, ret, offset, idx);
 
@@ -1391,11 +1403,11 @@ int journal_file_move_to_entry_by_monotonic(
                 Object **ret,
                 uint64_t *offset) {
 
-        char t[8+32+1] = "_BOOT_ID=";
+        char t[9+32+1] = "_BOOT_ID=";
         Object *o;
         int r;
 
-        sd_id128_to_string(boot_id, t + 8);
+        sd_id128_to_string(boot_id, t + 9);
 
         r = journal_file_find_data_object(f, t, strlen(t), &o, NULL);
         if (r < 0)
@@ -1660,7 +1672,7 @@ void journal_file_dump(JournalFile *f) {
                (unsigned long) le64toh(f->header->n_objects),
                (unsigned long) le64toh(f->header->n_entries));
 
-        p = le64toh(f->header->arena_offset);
+        p = le64toh(f->header->header_size);
         while (p != 0) {
                 r = journal_file_move_to_object(f, -1, p, &o);
                 if (r < 0)
@@ -1694,6 +1706,10 @@ void journal_file_dump(JournalFile *f) {
                 case OBJECT_ENTRY_ARRAY:
                         printf("Type: OBJECT_ENTRY_ARRAY\n");
                         break;
+
+                case OBJECT_SIGNATURE:
+                        printf("Type: OBJECT_SIGNATURE\n");
+                        break;
                 }
 
                 if (o->object.flags & OBJECT_COMPRESSED)
@@ -2272,3 +2288,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;
+}