chiark / gitweb /
journal: unify code for up and for down traversal
authorLennart Poettering <lennart@poettering.net>
Fri, 14 Oct 2011 23:38:44 +0000 (01:38 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 14 Oct 2011 23:38:44 +0000 (01:38 +0200)
src/journal/journal-file.c
src/journal/journal-file.h
src/journal/sd-journal.c
src/journal/test-journal.c

index 5557028..ab45132 100644 (file)
@@ -892,19 +892,23 @@ int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, ui
         return 0;
 }
 
-int journal_file_next_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset) {
+int journal_file_next_entry(JournalFile *f, Object *o, direction_t direction, Object **ret, uint64_t *offset) {
         uint64_t np;
         int r;
 
         assert(f);
 
         if (!o)
-                np = le64toh(f->header->head_entry_offset);
+                np = le64toh(direction == DIRECTION_DOWN ?
+                             f->header->head_entry_offset :
+                             f->header->tail_entry_offset);
         else {
                 if (le64toh(o->object.type) != OBJECT_ENTRY)
                         return -EINVAL;
 
-                np = le64toh(o->entry.next_entry_offset);
+                np = le64toh(direction == DIRECTION_DOWN ?
+                             o->entry.next_entry_offset :
+                             o->entry.prev_entry_offset);
         }
 
         if (np == 0)
@@ -954,7 +958,7 @@ int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *o
         return 1;
 }
 
-int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) {
+int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, direction_t direction, Object **ret, uint64_t *offset) {
         uint64_t p, osize, hash, h;
         int r;
 
@@ -980,59 +984,13 @@ int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t siz
                         if (le64toh(o->data.hash) != hash)
                                 return -EBADMSG;
 
-                        if (o->data.head_entry_offset == 0)
-                                return 0;
-
-                        p = le64toh(o->data.head_entry_offset);
-                        r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o);
-                        if (r < 0)
-                                return r;
-
-                        if (ret)
-                                *ret = o;
-
-                        if (offset)
-                                *offset = p;
-
-                        return 1;
-                }
-
-                p = le64toh(o->data.next_hash_offset);
-        }
-
-        return 0;
-}
-
-int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset) {
-        uint64_t p, osize, hash, h;
-        int r;
+                        p = le64toh(direction == DIRECTION_DOWN ?
+                                    o->data.head_entry_offset :
+                                    o->data.tail_entry_offset);
 
-        assert(f);
-        assert(data || size == 0);
-
-        osize = offsetof(Object, data.payload) + size;
-
-        hash = hash64(data, size);
-        h = hash % (le64toh(f->header->hash_table_size) / sizeof(HashItem));
-        p = le64toh(f->hash_table[h].tail_hash_offset);
-
-        while (p != 0) {
-                Object *o;
-
-                r = journal_file_move_to_object(f, p, OBJECT_DATA, &o);
-                if (r < 0)
-                        return r;
-
-                if (le64toh(o->object.size) == osize &&
-                    memcmp(o->data.payload, data, size) == 0) {
-
-                        if (le64toh(o->data.hash) != hash)
-                                return -EBADMSG;
-
-                        if (o->data.tail_entry_offset == 0)
+                        if (p == 0)
                                 return 0;
 
-                        p = le64toh(o->data.tail_entry_offset);
                         r = journal_file_move_to_object(f, p, OBJECT_ENTRY, &o);
                         if (r < 0)
                                 return r;
@@ -1046,7 +1004,7 @@ int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size
                         return 1;
                 }
 
-                p = le64toh(o->data.prev_hash_offset);
+                p = le64toh(o->data.next_hash_offset);
         }
 
         return 0;
index 0294555..795a446 100644 (file)
@@ -54,6 +54,11 @@ typedef struct JournalFile {
         uint64_t current_offset;
 } JournalFile;
 
+typedef enum direction {
+        DIRECTION_UP,
+        DIRECTION_DOWN
+} direction_t;
+
 int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile *template, JournalFile **ret);
 
 void journal_file_close(JournalFile *j);
@@ -66,11 +71,9 @@ int journal_file_append_entry(JournalFile *f, const dual_timestamp *ts, const st
 
 int journal_file_move_to_entry(JournalFile *f, uint64_t seqnum, Object **ret, uint64_t *offset);
 
-int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
-int journal_file_find_last_entry(JournalFile *f, const void *data, uint64_t size, Object **ret, uint64_t *offset);
+int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t size, direction_t direction, Object **ret, uint64_t *offset);
 
-int journal_file_next_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset);
-int journal_file_prev_entry(JournalFile *f, Object *o, Object **ret, uint64_t *offset);
+int journal_file_next_entry(JournalFile *f, Object *o, direction_t direction, Object **ret, uint64_t *offset);
 
 void journal_file_dump(JournalFile *f);
 
index bc6d255..985e321 100644 (file)
@@ -162,7 +162,7 @@ static int compare_order(JournalFile *af, Object *ao, uint64_t ap,
         return 0;
 }
 
-static int move_to_next_with_matches(sd_journal *j, JournalFile *f, Object **o, uint64_t *p) {
+static int move_to_next_with_matches(sd_journal *j, JournalFile *f, direction_t direction, Object **o, uint64_t *p) {
         int r;
         uint64_t cp;
         Object *c;
@@ -182,7 +182,7 @@ static int move_to_next_with_matches(sd_journal *j, JournalFile *f, Object **o,
                 } else
                         c = NULL;
 
-                return journal_file_next_entry(f, c, o, p);
+                return journal_file_next_entry(f, c, direction, o, p);
         }
 
         /* So there are matches we have to adhere to, let's find the
@@ -191,7 +191,7 @@ static int move_to_next_with_matches(sd_journal *j, JournalFile *f, Object **o,
         if (f->current_offset > 0)
                 cp = f->current_offset;
         else {
-                r = journal_file_find_first_entry(f, j->matches->data, j->matches->size, &c, &cp);
+                r = journal_file_find_first_entry(f, j->matches->data, j->matches->size, direction, &c, &cp);
                 if (r <= 0)
                         return r;
 
@@ -237,9 +237,18 @@ static int move_to_next_with_matches(sd_journal *j, JournalFile *f, Object **o,
                         /* Hmm, so, this field matched, let's remember
                          * where we'd have to try next, in case the other
                          * matches are not OK */
-                        q = le64toh(c->entry.items[k].next_entry_offset);
-                        if (q > np)
-                                np = q;
+
+                        if (direction == DIRECTION_DOWN) {
+                                q = le64toh(c->entry.items[k].next_entry_offset);
+
+                                if (q > np)
+                                        np = q;
+                        } else {
+                                q = le64toh(c->entry.items[k].prev_entry_offset);
+
+                                if (q != 0 && (np == 0 || q < np))
+                                        np = q;
+                        }
                 }
 
                 /* Did this entry match against all matches? */
@@ -259,7 +268,7 @@ static int move_to_next_with_matches(sd_journal *j, JournalFile *f, Object **o,
         }
 }
 
-int sd_journal_next(sd_journal *j) {
+static int real_journal_next(sd_journal *j, direction_t direction) {
         JournalFile *f, *new_current = NULL;
         Iterator i;
         int r;
@@ -272,7 +281,7 @@ int sd_journal_next(sd_journal *j) {
                 Object *o;
                 uint64_t p;
 
-                r = move_to_next_with_matches(j, f, &o, &p);
+                r = move_to_next_with_matches(j, f, direction, &o, &p);
                 if (r < 0)
                         return r;
                 else if (r == 0)
@@ -300,7 +309,7 @@ int sd_journal_next(sd_journal *j) {
                         if (j->current_file == f)
                                 continue;
 
-                        r = move_to_next_with_matches(j, f, &o, &p);
+                        r = move_to_next_with_matches(j, f, direction, &o, &p);
                         if (r < 0)
                                 return r;
                         else if (r == 0)
@@ -316,74 +325,12 @@ int sd_journal_next(sd_journal *j) {
         return 0;
 }
 
-int sd_journal_previous(sd_journal *j) {
-        JournalFile *f, *new_current = NULL;
-        Iterator i;
-        int r;
-        uint64_t new_offset = 0;
-        Object *new_entry = NULL;
-
-        assert(j);
-
-        HASHMAP_FOREACH(f, j->files, i) {
-                Object *o;
-                uint64_t p;
-
-                if (f->current_offset > 0) {
-                        r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o);
-                        if (r < 0)
-                                return r;
-                } else
-                        o = NULL;
-
-                r = journal_file_prev_entry(f, o, &o, &p);
-                if (r < 0)
-                        return r;
-                else if (r == 0)
-                        continue;
-
-                if (!new_current || compare_order(new_current, new_entry, new_offset, f, o, p) > 0) {
-                        new_current = f;
-                        new_entry = o;
-                        new_offset = p;
-                }
-        }
-
-        if (new_current) {
-                j->current_file = new_current;
-                j->current_file->current_offset = new_offset;
-                j->current_field = 0;
-
-                /* Skip over any identical entries in the other files too */
-
-                HASHMAP_FOREACH(f, j->files, i) {
-                        Object *o;
-                        uint64_t p;
-
-                        if (j->current_file == f)
-                                continue;
-
-                        if (f->current_offset > 0) {
-                                r = journal_file_move_to_object(f, f->current_offset, OBJECT_ENTRY, &o);
-                                if (r < 0)
-                                        return r;
-                        } else
-                                o = NULL;
-
-                        r = journal_file_prev_entry(f, o, &o, &p);
-                        if (r < 0)
-                                return r;
-                        else if (r == 0)
-                                continue;
-
-                        if (compare_order(new_current, new_entry, new_offset, f, o, p) == 0)
-                                f->current_offset = p;
-                }
-
-                return 1;
-        }
+int sd_journal_next(sd_journal *j) {
+        return real_journal_next(j, DIRECTION_DOWN);
+}
 
-        return 0;
+int sd_journal_previous(sd_journal *j) {
+        return real_journal_next(j, DIRECTION_UP);
 }
 
 int sd_journal_get_cursor(sd_journal *j, char **cursor) {
index 3b67f1a..93e2b4d 100644 (file)
@@ -54,30 +54,30 @@ int main(int argc, char *argv[]) {
 
         journal_file_dump(f);
 
-        assert(journal_file_next_entry(f, NULL, &o, NULL) == 1);
+        assert(journal_file_next_entry(f, NULL, DIRECTION_DOWN, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 1);
 
-        assert(journal_file_next_entry(f, o, &o, NULL) == 1);
+        assert(journal_file_next_entry(f, o, DIRECTION_DOWN, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 2);
 
-        assert(journal_file_next_entry(f, o, &o, NULL) == 1);
+        assert(journal_file_next_entry(f, o, DIRECTION_DOWN, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 3);
 
-        assert(journal_file_next_entry(f, o, &o, NULL) == 0);
+        assert(journal_file_next_entry(f, o, DIRECTION_DOWN, &o, NULL) == 0);
 
-        assert(journal_file_find_first_entry(f, test, strlen(test), &o, NULL) == 1);
+        assert(journal_file_find_first_entry(f, test, strlen(test), DIRECTION_DOWN, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 1);
 
-        assert(journal_file_find_last_entry(f, test, strlen(test), &o, NULL) == 1);
+        assert(journal_file_find_first_entry(f, test, strlen(test), DIRECTION_UP, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 3);
 
-        assert(journal_file_find_last_entry(f, test2, strlen(test2), &o, NULL) == 1);
+        assert(journal_file_find_first_entry(f, test2, strlen(test2), DIRECTION_UP, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 2);
 
-        assert(journal_file_find_first_entry(f, test2, strlen(test2), &o, NULL) == 1);
+        assert(journal_file_find_first_entry(f, test2, strlen(test2), DIRECTION_DOWN, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 2);
 
-        assert(journal_file_find_first_entry(f, "quux", 4, &o, NULL) == 0);
+        assert(journal_file_find_first_entry(f, "quux", 4, DIRECTION_DOWN, &o, NULL) == 0);
 
         assert(journal_file_move_to_entry(f, 1, &o, NULL) == 1);
         assert(le64toh(o->entry.seqnum) == 1);