mirror of
https://github.com/systemd/systemd.git
synced 2024-12-23 21:35:11 +03:00
journal: unify code for up and for down traversal
This commit is contained in:
parent
de7b95cdc3
commit
e892bd1797
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user