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