Commit cd34b3c6 authored by Harald Hoyer's avatar Harald Hoyer

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.
parent 003ac9d0
...@@ -113,7 +113,7 @@ struct sd_journal { ...@@ -113,7 +113,7 @@ struct sd_journal {
int inotify_fd; int inotify_fd;
Match *level0, *level1; Match *level0, *level1, *level2;
unsigned current_invalidate_counter, last_invalidate_counter; unsigned current_invalidate_counter, last_invalidate_counter;
......
...@@ -604,6 +604,10 @@ static int add_this_boot(sd_journal *j) { ...@@ -604,6 +604,10 @@ static int add_this_boot(sd_journal *j) {
return r; return r;
} }
r = sd_journal_add_conjunction(j);
if (r < 0)
return r;
return 0; return 0;
} }
...@@ -627,13 +631,16 @@ static int add_unit(sd_journal *j) { ...@@ -627,13 +631,16 @@ static int add_unit(sd_journal *j) {
if (r < 0) if (r < 0)
return r; return r;
r = sd_journal_add_conjunction(j);
if (r < 0)
return r;
return 0; return 0;
} }
static int add_priorities(sd_journal *j) { static int add_priorities(sd_journal *j) {
char match[] = "PRIORITY=0"; char match[] = "PRIORITY=0";
int i, r; int i, r;
assert(j); assert(j);
if (arg_priorities == 0xFF) if (arg_priorities == 0xFF)
...@@ -650,6 +657,10 @@ static int add_priorities(sd_journal *j) { ...@@ -650,6 +657,10 @@ static int add_priorities(sd_journal *j) {
} }
} }
r = sd_journal_add_conjunction(j);
if (r < 0)
return r;
return 0; return 0;
} }
...@@ -1106,11 +1117,11 @@ int main(int argc, char *argv[]) { ...@@ -1106,11 +1117,11 @@ int main(int argc, char *argv[]) {
if (r < 0) if (r < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
r = add_matches(j, argv + optind); r = add_priorities(j);
if (r < 0) if (r < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
r = add_priorities(j); r = add_matches(j, argv + optind);
if (r < 0) if (r < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
......
...@@ -203,7 +203,7 @@ static void match_free_if_empty(Match *m) { ...@@ -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) { _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; le64_t le_hash;
if (!j) if (!j)
...@@ -218,44 +218,52 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) ...@@ -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)) if (!match_is_valid(data, size))
return -EINVAL; return -EINVAL;
/* level 0: OR term /* level 0: AND term
* level 1: AND terms * level 1: OR terms
* level 2: OR terms * level 2: AND terms
* level 3: concrete matches */ * level 3: OR terms
* level 4: concrete matches */
if (!j->level0) { if (!j->level0) {
j->level0 = match_new(NULL, MATCH_OR_TERM); j->level0 = match_new(NULL, MATCH_AND_TERM);
if (!j->level0) if (!j->level0)
return -ENOMEM; return -ENOMEM;
} }
if (!j->level1) { if (!j->level1) {
j->level1 = match_new(j->level0, MATCH_AND_TERM); j->level1 = match_new(j->level0, MATCH_OR_TERM);
if (!j->level1) if (!j->level1)
return -ENOMEM; return -ENOMEM;
} }
assert(j->level0->type == MATCH_OR_TERM); if (!j->level2) {
assert(j->level1->type == MATCH_AND_TERM); 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)); le_hash = htole64(hash64(data, size));
LIST_FOREACH(matches, l2, j->level1->matches) { LIST_FOREACH(matches, l3, j->level2->matches) {
assert(l2->type == MATCH_OR_TERM); assert(l3->type == MATCH_OR_TERM);
LIST_FOREACH(matches, l3, l2->matches) { LIST_FOREACH(matches, l4, l3->matches) {
assert(l3->type == MATCH_DISCRETE); assert(l4->type == MATCH_DISCRETE);
/* Exactly the same match already? Then ignore /* Exactly the same match already? Then ignore
* this addition */ * this addition */
if (l3->le_hash == le_hash && if (l4->le_hash == le_hash &&
l3->size == size && l4->size == size &&
memcmp(l3->data, data, size) == 0) memcmp(l4->data, data, size) == 0)
return 0; return 0;
/* Same field? Then let's add this to this OR term */ /* Same field? Then let's add this to this OR term */
if (same_field(data, size, l3->data, l3->size)) { if (same_field(data, size, l4->data, l4->size)) {
add_here = l2; add_here = l3;
break; break;
} }
} }
...@@ -265,7 +273,7 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size) ...@@ -265,7 +273,7 @@ _public_ int sd_journal_add_match(sd_journal *j, const void *data, size_t size)
} }
if (!add_here) { if (!add_here) {
add_here = match_new(j->level1, MATCH_OR_TERM); add_here = match_new(j->level2, MATCH_OR_TERM);
if (!add_here) if (!add_here)
goto fail; goto fail;
} }
...@@ -288,6 +296,9 @@ fail: ...@@ -288,6 +296,9 @@ fail:
if (add_here) if (add_here)
match_free_if_empty(add_here); match_free_if_empty(add_here);
if (j->level2)
match_free_if_empty(j->level2);
if (j->level1) if (j->level1)
match_free_if_empty(j->level1); match_free_if_empty(j->level1);
...@@ -297,9 +308,7 @@ fail: ...@@ -297,9 +308,7 @@ fail:
return -ENOMEM; return -ENOMEM;
} }
_public_ int sd_journal_add_disjunction(sd_journal *j) { _public_ int sd_journal_add_conjunction(sd_journal *j) {
Match *m;
assert(j); assert(j);
if (!j->level0) if (!j->level0)
...@@ -311,11 +320,28 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) { ...@@ -311,11 +320,28 @@ _public_ int sd_journal_add_disjunction(sd_journal *j) {
if (!j->level1->matches) if (!j->level1->matches)
return 0; return 0;
m = match_new(j->level0, MATCH_AND_TERM); j->level1 = NULL;
if (!m) j->level2 = NULL;
return -ENOMEM;
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; return 0;
} }
...@@ -380,7 +406,7 @@ _public_ void sd_journal_flush_matches(sd_journal *j) { ...@@ -380,7 +406,7 @@ _public_ void sd_journal_flush_matches(sd_journal *j) {
if (j->level0) if (j->level0)
match_free(j->level0); match_free(j->level0);
j->level0 = j->level1 = NULL; j->level0 = j->level1 = j->level2 = NULL;
detach_location(j); detach_location(j);
} }
......
...@@ -54,11 +54,23 @@ int main(int argc, char *argv[]) { ...@@ -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, "ONE=two", 0) >= 0);
assert_se(sd_journal_add_match(j, "TWO=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); 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; return 0;
} }
...@@ -106,6 +106,7 @@ void sd_journal_restart_data(sd_journal *j); ...@@ -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_match(sd_journal *j, const void *data, size_t size);
int sd_journal_add_disjunction(sd_journal *j); int sd_journal_add_disjunction(sd_journal *j);
int sd_journal_add_conjunction(sd_journal *j);
void sd_journal_flush_matches(sd_journal *j); void sd_journal_flush_matches(sd_journal *j);
int sd_journal_seek_head(sd_journal *j); int sd_journal_seek_head(sd_journal *j);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment