1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-28 11:55:44 +03:00

journal: unify code for up and for down traversal

This commit is contained in:
Lennart Poettering 2011-10-15 01:38:44 +02:00
parent de7b95cdc3
commit e892bd1797
4 changed files with 52 additions and 144 deletions

View 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,10 +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)
p = le64toh(direction == DIRECTION_DOWN ?
o->data.head_entry_offset :
o->data.tail_entry_offset);
if (p == 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;
@ -1003,55 +1010,6 @@ int journal_file_find_first_entry(JournalFile *f, const void *data, uint64_t siz
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;
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)
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;
if (ret)
*ret = o;
if (offset)
*offset = p;
return 1;
}
p = le64toh(o->data.prev_hash_offset);
}
return 0;
}
void journal_file_dump(JournalFile *f) {
char a[33], b[33], c[33];
Object *o;

View 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);

View 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_next(sd_journal *j) {
return real_journal_next(j, DIRECTION_DOWN);
}
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;
}
return 0;
return real_journal_next(j, DIRECTION_UP);
}
int sd_journal_get_cursor(sd_journal *j, char **cursor) {

View 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);