From: Lennart Poettering Date: Fri, 14 Oct 2011 23:38:44 +0000 (+0200) Subject: journal: unify code for up and for down traversal X-Git-Tag: v38~144^2~47 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=e892bd1797e99c8afaa6afdbe413fda78937c9c3 journal: unify code for up and for down traversal --- diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 555702814..ab45132f0 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -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; diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h index 0294555ca..795a446dc 100644 --- a/src/journal/journal-file.h +++ b/src/journal/journal-file.h @@ -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); diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index bc6d25566..985e3210c 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -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) { diff --git a/src/journal/test-journal.c b/src/journal/test-journal.c index 3b67f1aa9..93e2b4dab 100644 --- a/src/journal/test-journal.c +++ b/src/journal/test-journal.c @@ -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);