]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/journal/test-journal-interleaving.c
update TODO
[thirdparty/systemd.git] / src / journal / test-journal-interleaving.c
CommitLineData
7a050b54
MV
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Marius Vollmer
5cb24cd3 7 Copyright 2013 Zbigniew Jędrzejewski-Szmek
7a050b54
MV
8
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21***/
22
23#include <unistd.h>
24#include <fcntl.h>
25
c6878637 26#include "sd-journal.h"
7a050b54 27#include "journal-file.h"
5cb24cd3 28#include "journal-vacuum.h"
7a050b54
MV
29#include "util.h"
30#include "log.h"
c6878637 31#include "rm-rf.h"
7a050b54
MV
32
33/* This program tests skipping around in a multi-file journal.
34 */
35
5cb24cd3
ZJS
36static bool arg_keep = false;
37
919ce0b7 38noreturn static void log_assert_errno(const char *text, int eno, const char *file, int line, const char *func) {
79008bdd
LP
39 log_internal(LOG_CRIT, 0, file, line, func,
40 "'%s' failed at %s:%u (%s): %s.",
41 text, file, line, func, strerror(eno));
7a050b54
MV
42 abort();
43}
44
45#define assert_ret(expr) \
46 do { \
47 int _r_ = (expr); \
48 if (_unlikely_(_r_ < 0)) \
49 log_assert_errno(#expr, -_r_, __FILE__, __LINE__, __PRETTY_FUNCTION__); \
50 } while (false)
51
510b857f 52static JournalFile *test_open(const char *name) {
7a050b54 53 JournalFile *f;
5cb24cd3 54 assert_ret(journal_file_open(name, O_RDWR|O_CREAT, 0644, true, false, NULL, NULL, NULL, &f));
7a050b54
MV
55 return f;
56}
57
510b857f 58static void test_close(JournalFile *f) {
7a050b54
MV
59 journal_file_close (f);
60}
61
510b857f 62static void append_number(JournalFile *f, int n, uint64_t *seqnum) {
7a050b54
MV
63 char *p;
64 dual_timestamp ts;
65 struct iovec iovec[1];
66
67 dual_timestamp_get(&ts);
68
69 assert_se(asprintf(&p, "NUMBER=%d", n) >= 0);
70 iovec[0].iov_base = p;
71 iovec[0].iov_len = strlen(p);
5cb24cd3 72 assert_ret(journal_file_append_entry(f, &ts, iovec, 1, seqnum, NULL, NULL));
510b857f 73 free(p);
7a050b54
MV
74}
75
510b857f 76static void test_check_number (sd_journal *j, int n) {
7a050b54 77 const void *d;
510b857f 78 _cleanup_free_ char *k;
7a050b54
MV
79 size_t l;
80 int x;
81
82 assert_ret(sd_journal_get_data(j, "NUMBER", &d, &l));
83 assert_se(k = strndup(d, l));
84 printf("%s\n", k);
85
86 assert_se(safe_atoi(k + 7, &x) >= 0);
87 assert_se(n == x);
88}
89
510b857f
LP
90static void test_check_numbers_down (sd_journal *j, int count) {
91 int i;
92
93 for (i = 1; i <= count; i++) {
7a050b54
MV
94 int r;
95 test_check_number(j, i);
96 assert_ret(r = sd_journal_next(j));
97 if (i == count)
98 assert_se(r == 0);
99 else
100 assert_se(r == 1);
101 }
102
103}
104
510b857f 105static void test_check_numbers_up (sd_journal *j, int count) {
7a050b54
MV
106 for (int i = count; i >= 1; i--) {
107 int r;
108 test_check_number(j, i);
109 assert_ret(r = sd_journal_previous(j));
110 if (i == 1)
111 assert_se(r == 0);
112 else
113 assert_se(r == 1);
114 }
115
116}
117
118static void setup_sequential(void) {
119 JournalFile *one, *two;
120 one = test_open("one.journal");
121 two = test_open("two.journal");
5cb24cd3
ZJS
122 append_number(one, 1, NULL);
123 append_number(one, 2, NULL);
124 append_number(two, 3, NULL);
125 append_number(two, 4, NULL);
7a050b54
MV
126 test_close(one);
127 test_close(two);
128}
129
130static void setup_interleaved(void) {
131 JournalFile *one, *two;
132 one = test_open("one.journal");
133 two = test_open("two.journal");
5cb24cd3
ZJS
134 append_number(one, 1, NULL);
135 append_number(two, 2, NULL);
136 append_number(one, 3, NULL);
137 append_number(two, 4, NULL);
7a050b54
MV
138 test_close(one);
139 test_close(two);
140}
141
510b857f 142static void test_skip(void (*setup)(void)) {
7a050b54
MV
143 char t[] = "/tmp/journal-skip-XXXXXX";
144 sd_journal *j;
145 int r;
146
7a050b54
MV
147 assert_se(mkdtemp(t));
148 assert_se(chdir(t) >= 0);
149
150 setup();
151
152 /* Seek to head, iterate down.
153 */
154 assert_ret(sd_journal_open_directory(&j, t, 0));
155 assert_ret(sd_journal_seek_head(j));
156 assert_ret(sd_journal_next(j));
157 test_check_numbers_down(j, 4);
158 sd_journal_close(j);
159
160 /* Seek to tail, iterate up.
161 */
162 assert_ret(sd_journal_open_directory(&j, t, 0));
163 assert_ret(sd_journal_seek_tail(j));
164 assert_ret(sd_journal_previous(j));
165 test_check_numbers_up(j, 4);
166 sd_journal_close(j);
167
168 /* Seek to tail, skip to head, iterate down.
169 */
170 assert_ret(sd_journal_open_directory(&j, t, 0));
171 assert_ret(sd_journal_seek_tail(j));
172 assert_ret(r = sd_journal_previous_skip(j, 4));
173 assert_se(r == 4);
174 test_check_numbers_down(j, 4);
175 sd_journal_close(j);
176
177 /* Seek to head, skip to tail, iterate up.
178 */
179 assert_ret(sd_journal_open_directory(&j, t, 0));
180 assert_ret(sd_journal_seek_head(j));
181 assert_ret(r = sd_journal_next_skip(j, 4));
182 assert_se(r == 4);
183 test_check_numbers_up(j, 4);
184 sd_journal_close(j);
185
5cb24cd3
ZJS
186 log_info("Done...");
187
188 if (arg_keep)
189 log_info("Not removing %s", t);
190 else {
dbd2a83f 191 journal_directory_vacuum(".", 3000000, 0, NULL, true);
5cb24cd3 192
c6878637 193 assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
5cb24cd3
ZJS
194 }
195
196 puts("------------------------------------------------------------");
197}
198
199static void test_sequence_numbers(void) {
200
201 char t[] = "/tmp/journal-seq-XXXXXX";
202 JournalFile *one, *two;
203 uint64_t seqnum = 0;
204 sd_id128_t seqnum_id;
205
206 assert_se(mkdtemp(t));
207 assert_se(chdir(t) >= 0);
208
209 assert_se(journal_file_open("one.journal", O_RDWR|O_CREAT, 0644,
210 true, false, NULL, NULL, NULL, &one) == 0);
211
212 append_number(one, 1, &seqnum);
213 printf("seqnum=%"PRIu64"\n", seqnum);
0c0cdb06 214 assert_se(seqnum == 1);
5cb24cd3
ZJS
215 append_number(one, 2, &seqnum);
216 printf("seqnum=%"PRIu64"\n", seqnum);
0c0cdb06 217 assert_se(seqnum == 2);
5cb24cd3 218
0c0cdb06
RC
219 assert_se(one->header->state == STATE_ONLINE);
220 assert_se(!sd_id128_equal(one->header->file_id, one->header->machine_id));
221 assert_se(!sd_id128_equal(one->header->file_id, one->header->boot_id));
222 assert_se(sd_id128_equal(one->header->file_id, one->header->seqnum_id));
5cb24cd3
ZJS
223
224 memcpy(&seqnum_id, &one->header->seqnum_id, sizeof(sd_id128_t));
225
226 assert_se(journal_file_open("two.journal", O_RDWR|O_CREAT, 0644,
227 true, false, NULL, NULL, one, &two) == 0);
228
0c0cdb06
RC
229 assert_se(two->header->state == STATE_ONLINE);
230 assert_se(!sd_id128_equal(two->header->file_id, one->header->file_id));
231 assert_se(sd_id128_equal(one->header->machine_id, one->header->machine_id));
232 assert_se(sd_id128_equal(one->header->boot_id, one->header->boot_id));
233 assert_se(sd_id128_equal(one->header->seqnum_id, one->header->seqnum_id));
5cb24cd3
ZJS
234
235 append_number(two, 3, &seqnum);
236 printf("seqnum=%"PRIu64"\n", seqnum);
0c0cdb06 237 assert_se(seqnum == 3);
5cb24cd3
ZJS
238 append_number(two, 4, &seqnum);
239 printf("seqnum=%"PRIu64"\n", seqnum);
0c0cdb06 240 assert_se(seqnum == 4);
5cb24cd3
ZJS
241
242 test_close(two);
243
244 append_number(one, 5, &seqnum);
245 printf("seqnum=%"PRIu64"\n", seqnum);
0c0cdb06 246 assert_se(seqnum == 5);
5cb24cd3
ZJS
247
248 append_number(one, 6, &seqnum);
249 printf("seqnum=%"PRIu64"\n", seqnum);
0c0cdb06 250 assert_se(seqnum == 6);
5cb24cd3
ZJS
251
252 test_close(one);
253
254 /* restart server */
255 seqnum = 0;
256
257 assert_se(journal_file_open("two.journal", O_RDWR, 0,
258 true, false, NULL, NULL, NULL, &two) == 0);
259
0c0cdb06 260 assert_se(sd_id128_equal(two->header->seqnum_id, seqnum_id));
5cb24cd3
ZJS
261
262 append_number(two, 7, &seqnum);
263 printf("seqnum=%"PRIu64"\n", seqnum);
0c0cdb06 264 assert_se(seqnum == 5);
5cb24cd3
ZJS
265
266 /* So..., here we have the same seqnum in two files with the
267 * same seqnum_id. */
268
269 test_close(two);
270
271 log_info("Done...");
272
273 if (arg_keep)
274 log_info("Not removing %s", t);
275 else {
dbd2a83f 276 journal_directory_vacuum(".", 3000000, 0, NULL, true);
5cb24cd3 277
c6878637 278 assert_se(rm_rf(t, REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
5cb24cd3 279 }
7a050b54
MV
280}
281
282int main(int argc, char *argv[]) {
5cb24cd3
ZJS
283 log_set_max_level(LOG_DEBUG);
284
143bfdaf
HHPF
285 /* journal_file_open requires a valid machine id */
286 if (access("/etc/machine-id", F_OK) != 0)
287 return EXIT_TEST_SKIP;
288
5cb24cd3
ZJS
289 arg_keep = argc > 1;
290
7a050b54
MV
291 test_skip(setup_sequential);
292 test_skip(setup_interleaved);
293
5cb24cd3
ZJS
294 test_sequence_numbers();
295
7a050b54
MV
296 return 0;
297}