From: Harald Hoyer Date: Thu, 11 Apr 2013 13:27:55 +0000 (+0200) Subject: journal: add one more level on top with AND X-Git-Tag: v202~48 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=cd34b3c6670df8a3fd49179131fe762b2dd86b01;p=elogind.git journal: add one more level on top with AND When using "-p" and "-b" in combination with "-u", the output is not what you would expect. The reason is the sd_journal_add_disjunction() call in add_matches_for_unit() and add_matches_for_user_unit(), which adds two ORs without taking the other conditions to every OR. Adding another level on top with AND and sd_journal_add_conjunction() solves the problem. Output before: $ journalctl -o short-monotonic -ab -p 0 -u sshd.service -- Reboot -- [ 3.216305] lenovo systemd[1]: Starting OpenSSH server daemon... -- Reboot -- [ 3.168666] lenovo systemd[1]: Starting OpenSSH server daemon... [ 3.169639] lenovo systemd[1]: Started OpenSSH server daemon. [36285.635389] lenovo systemd[1]: Stopped OpenSSH server daemon. -- Reboot -- [ 10.838657] lenovo systemd[1]: Starting OpenSSH server daemon... [ 10.913698] lenovo systemd[1]: Started OpenSSH server daemon. [ 6881.035183] lenovo systemd[1]: Stopped OpenSSH server daemon. -- Reboot -- [ 6.636228] lenovo systemd[1]: Starting OpenSSH server daemon... [ 6.662573] lenovo systemd[1]: Started OpenSSH server daemon. [ 6.681148] lenovo sshd[397]: Server listening on 0.0.0.0 port 22. [ 6.681379] lenovo sshd[397]: Server listening on :: port 22. As we see, the output is from _every_ boot and priority 0 is not taken into account. Output after patch: $ journalctl -o short-monotonic -ab -p 0 -u sshd.service -- Logs begin at Sun 2013-02-24 20:54:44 CET, end at Tue 2013-03-19 14:58:21 CET. -- Increasing the priority: $ journalctl -o short-monotonic -ab -p 6 -u sshd.service -- Logs begin at Sun 2013-02-24 20:54:44 CET, end at Tue 2013-03-19 14:59:12 CET. -- [ 6.636228] lenovo systemd[1]: Starting OpenSSH server daemon... [ 6.662573] lenovo systemd[1]: Started OpenSSH server daemon. [ 6.681148] lenovo sshd[397]: Server listening on 0.0.0.0 port 22. [ 6.681379] lenovo sshd[397]: Server listening on :: port 22. --- diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index ff8b34a95..eea56e471 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -113,7 +113,7 @@ struct sd_journal { int inotify_fd; - Match *level0, *level1; + Match *level0, *level1, *level2; unsigned current_invalidate_counter, last_invalidate_counter; diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index c9b2abece..2ebac405c 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -604,6 +604,10 @@ static int add_this_boot(sd_journal *j) { return r; } + r = sd_journal_add_conjunction(j); + if (r < 0) + return r; + return 0; } @@ -627,13 +631,16 @@ static int add_unit(sd_journal *j) { if (r < 0) return r; + r = sd_journal_add_conjunction(j); + if (r < 0) + return r; + return 0; } static int add_priorities(sd_journal *j) { char match[] = "PRIORITY=0"; int i, r; - assert(j); if (arg_priorities == 0xFF) @@ -650,6 +657,10 @@ static int add_priorities(sd_journal *j) { } } + r = sd_journal_add_conjunction(j); + if (r < 0) + return r; + return 0; } @@ -1106,11 +1117,11 @@ int main(int argc, char *argv[]) { if (r < 0) return EXIT_FAILURE; - r = add_matches(j, argv + optind); + r = add_priorities(j); if (r < 0) return EXIT_FAILURE; - r = add_priorities(j); + r = add_matches(j, argv + optind); if (r < 0) return EXIT_FAILURE; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index 7e06a7034..cc11ad9b5 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -203,7 +203,7 @@ static void match_free_if_empty(Match *m) { } _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) { - Match *l2, *l3, *add_here = NULL, *m; + Match *l3, *l4, *add_here = NULL, *m; le64_t le_hash; if (!j) @@ -218,44 +218,52 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) if (!match_is_valid(data, size)) return -EINVAL; - /* level 0: OR term - * level 1: AND terms - * level 2: OR terms - * level 3: concrete matches */ + /* level 0: AND term + * level 1: OR terms + * level 2: AND terms + * level 3: OR terms + * level 4: concrete matches */ if (!j->level0) { - j->level0 = match_new(NULL, MATCH_OR_TERM); + j->level0 = match_new(NULL, MATCH_AND_TERM); if (!j->level0) return -ENOMEM; } if (!j->level1) { - j->level1 = match_new(j->level0, MATCH_AND_TERM); + j->level1 = match_new(j->level0, MATCH_OR_TERM); if (!j->level1) return -ENOMEM; } - assert(j->level0->type == MATCH_OR_TERM); - assert(j->level1->type == MATCH_AND_TERM); + if (!j->level2) { + j->level2 = match_new(j->level1, MATCH_AND_TERM); + if (!j->level2) + return -ENOMEM; + } + + assert(j->level0->type == MATCH_AND_TERM); + assert(j->level1->type == MATCH_OR_TERM); + assert(j->level2->type == MATCH_AND_TERM); le_hash = htole64(hash64(data, size)); - LIST_FOREACH(matches, l2, j->level1->matches) { - assert(l2->type == MATCH_OR_TERM); + LIST_FOREACH(matches, l3, j->level2->matches) { + assert(l3->type == MATCH_OR_TERM); - LIST_FOREACH(matches, l3, l2->matches) { - assert(l3->type == MATCH_DISCRETE); + LIST_FOREACH(matches, l4, l3->matches) { + assert(l4->type == MATCH_DISCRETE); /* Exactly the same match already? Then ignore * this addition */ - if (l3->le_hash == le_hash && - l3->size == size && - memcmp(l3->data, data, size) == 0) + if (l4->le_hash == le_hash && + l4->size == size && + memcmp(l4->data, data, size) == 0) return 0; /* Same field? Then let's add this to this OR term */ - if (same_field(data, size, l3->data, l3->size)) { - add_here = l2; + if (same_field(data, size, l4->data, l4->size)) { + add_here = l3; break; } } @@ -265,7 +273,7 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) } if (!add_here) { - add_here = match_new(j->level1, MATCH_OR_TERM); + add_here = match_new(j->level2, MATCH_OR_TERM); if (!add_here) goto fail; } @@ -288,6 +296,9 @@ fail: if (add_here) match_free_if_empty(add_here); + if (j->level2) + match_free_if_empty(j->level2); + if (j->level1) match_free_if_empty(j->level1); @@ -297,9 +308,7 @@ fail: return -ENOMEM; } -_public_ int sd_journal_add_disjunction(sd_journal *j) { - Match *m; - +_public_ int sd_journal_add_conjunction(sd_journal *j) { assert(j); if (!j->level0) @@ -311,11 +320,28 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) { if (!j->level1->matches) return 0; - m = match_new(j->level0, MATCH_AND_TERM); - if (!m) - return -ENOMEM; + j->level1 = NULL; + j->level2 = NULL; + + return 0; +} + +_public_ int sd_journal_add_disjunction(sd_journal *j) { + assert(j); + + if (!j->level0) + return 0; + + if (!j->level1) + return 0; + + if (!j->level2) + return 0; + + if (!j->level2->matches) + return 0; - j->level1 = m; + j->level2 = NULL; return 0; } @@ -380,7 +406,7 @@ _public_ void sd_journal_flush_matches(sd_journal *j) { if (j->level0) match_free(j->level0); - j->level0 = j->level1 = NULL; + j->level0 = j->level1 = j->level2 = NULL; detach_location(j); } diff --git a/src/journal/test-journal-match.c b/src/journal/test-journal-match.c index 2ca2337c4..7b14568fd 100644 --- a/src/journal/test-journal-match.c +++ b/src/journal/test-journal-match.c @@ -54,11 +54,23 @@ int main(int argc, char *argv[]) { assert_se(sd_journal_add_match(j, "ONE=two", 0) >= 0); assert_se(sd_journal_add_match(j, "TWO=two", 0) >= 0); - assert_se(t = journal_make_match_string(j)); + assert_se(sd_journal_add_conjunction(j) >= 0); + + assert_se(sd_journal_add_match(j, "L4_1=yes", 0) >= 0); + assert_se(sd_journal_add_match(j, "L4_1=ok", 0) >= 0); + assert_se(sd_journal_add_match(j, "L4_2=yes", 0) >= 0); + assert_se(sd_journal_add_match(j, "L4_2=ok", 0) >= 0); + + assert_se(sd_journal_add_disjunction(j) >= 0); - assert_se(streq(t, "((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO)))")); + assert_se(sd_journal_add_match(j, "L3=yes", 0) >= 0); + assert_se(sd_journal_add_match(j, "L3=ok", 0) >= 0); + + assert_se(t = journal_make_match_string(j)); printf("resulting match expression is: %s\n", t); + assert_se(streq(t, "(((L3=ok OR L3=yes) OR ((L4_2=ok OR L4_2=yes) AND (L4_1=ok OR L4_1=yes))) AND ((TWO=two AND (ONE=two OR ONE=one)) OR (PIFF=paff AND (QUUX=yyyyy OR QUUX=xxxxx OR QUUX=mmmm) AND (HALLO= OR HALLO=WALDO))))")); + return 0; } diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index afafee2d8..51653bafe 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -106,6 +106,7 @@ void sd_journal_restart_data(sd_journal *j); int sd_journal_add_match(sd_journal *j, const void *data, size_t size); int sd_journal_add_disjunction(sd_journal *j); +int sd_journal_add_conjunction(sd_journal *j); void sd_journal_flush_matches(sd_journal *j); int sd_journal_seek_head(sd_journal *j);