1SD_JOURNAL_GET_FD(3) sd_journal_get_fd SD_JOURNAL_GET_FD(3)
2
3
4
6 sd_journal_get_fd, sd_journal_get_events, sd_journal_get_timeout,
7 sd_journal_process, sd_journal_wait, sd_journal_reliable_fd,
8 SD_JOURNAL_NOP, SD_JOURNAL_APPEND, SD_JOURNAL_INVALIDATE - Journal
9 change notification interface
10
12 #include <systemd/sd-journal.h>
13
14 int sd_journal_get_fd(sd_journal *j);
15
16 int sd_journal_get_events(sd_journal *j);
17
18 int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec);
19
20 int sd_journal_process(sd_journal *j);
21
22 int sd_journal_wait(sd_journal *j, uint64_t timeout_usec);
23
24 int sd_journal_reliable_fd(sd_journal *j);
25
27 sd_journal_get_fd() returns a file descriptor that may be
28 asynchronously polled in an external event loop and is signaled as soon
29 as the journal changes, because new entries or files were added,
30 rotation took place, or files have been deleted, and similar. The file
31 descriptor is suitable for usage in poll(2). Use
32 sd_journal_get_events() for an events mask to watch for. The call takes
33 one argument: the journal context object. Note that not all file
34 systems are capable of generating the necessary events for wakeups from
35 this file descriptor for changes to be noticed immediately. In
36 particular network files systems do not generate suitable file change
37 events in all cases. Cases like this can be detected with
38 sd_journal_reliable_fd(), below. sd_journal_get_timeout() will ensure
39 in these cases that wake-ups happen frequently enough for changes to be
40 noticed, although with a certain latency.
41
42 sd_journal_get_events() will return the poll() mask to wait for. This
43 function will return a combination of POLLIN and POLLOUT and similar to
44 fill into the ".events" field of struct pollfd.
45
46 sd_journal_get_timeout() will return a timeout value for usage in
47 poll(). This returns a value in microseconds since the epoch of
48 CLOCK_MONOTONIC for timing out poll() in timeout_usec. See
49 clock_gettime(2) for details about CLOCK_MONOTONIC. If there is no
50 timeout to wait for, this will fill in (uint64_t) -1 instead. Note that
51 poll() takes a relative timeout in milliseconds rather than an absolute
52 timeout in microseconds. To convert the absolute 'us' timeout into
53 relative 'ms', use code like the following:
54
55 uint64_t t;
56 int msec;
57 sd_journal_get_timeout(m, &t);
58 if (t == (uint64_t) -1)
59 msec = -1;
60 else {
61 struct timespec ts;
62 uint64_t n;
63 clock_gettime(CLOCK_MONOTONIC, &ts);
64 n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
65 msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
66 }
67
68 The code above does not do any error checking for brevity's sake. The
69 calculated msec integer can be passed directly as poll()'s timeout
70 parameter.
71
72 After each poll() wake-up sd_journal_process() needs to be called to
73 process events. This call will also indicate what kind of change has
74 been detected (see below; note that spurious wake-ups are possible).
75
76 A synchronous alternative for using sd_journal_get_fd(),
77 sd_journal_get_events(), sd_journal_get_timeout() and
78 sd_journal_process() is sd_journal_wait(). It will synchronously wait
79 until the journal gets changed. The maximum time this call sleeps may
80 be controlled with the timeout_usec parameter. Pass (uint64_t) -1 to
81 wait indefinitely. Internally this call simply combines
82 sd_journal_get_fd(), sd_journal_get_events(), sd_journal_get_timeout(),
83 poll() and sd_journal_process() into one.
84
85 sd_journal_reliable_fd() may be used to check whether the wake-up
86 events from the file descriptor returned by sd_journal_get_fd() are
87 known to be quickly triggered. On certain file systems where file
88 change events from the OS are not available (such as NFS) changes need
89 to be polled for repeatedly, and hence are detected only with a
90 considerable latency. This call will return a positive value if the
91 journal changes are detected quickly and zero when they need to be
92 polled for. Note that there is usually no need to invoke this function
93 directly as sd_journal_get_timeout() will request appropriate timeouts
94 anyway.
95
96 Note that all of the above change notification interfaces do not report
97 changes instantly. Latencies are introduced for multiple reasons: as
98 mentioned certain storage backends require time-based polling, in other
99 cases wake-ups are optimized by coalescing events, and the OS
100 introduces additional IO/CPU scheduling latencies.
101
103 sd_journal_get_fd() returns a valid file descriptor on success or a
104 negative errno-style error code.
105
106 sd_journal_get_events() returns a combination of POLLIN, POLLOUT and
107 suchlike on success or a negative errno-style error code.
108
109 sd_journal_reliable_fd() returns a positive integer if the file
110 descriptor returned by sd_journal_get_fd() will generate wake-ups
111 immediately for all journal changes. Returns 0 if there might be a
112 latency involved.
113
114 sd_journal_process() and sd_journal_wait() return a negative
115 errno-style error code, or one of SD_JOURNAL_NOP, SD_JOURNAL_APPEND or
116 SD_JOURNAL_INVALIDATE on success:
117
118 • If SD_JOURNAL_NOP is returned, the journal did not change since the
119 last invocation.
120
121 • If SD_JOURNAL_APPEND is returned, new entries have been appended to
122 the end of the journal. In this case it is sufficient to simply
123 continue reading at the previous end location of the journal, to
124 read the newly added entries.
125
126 • If SD_JOURNAL_INVALIDATE, journal files were added to or removed
127 from the set of journal files watched (e.g. due to rotation or
128 vacuuming), and thus entries might have appeared or disappeared at
129 arbitrary places in the log stream, possibly before or after the
130 previous end of the log stream. If SD_JOURNAL_INVALIDATE is
131 returned, live-view UIs that want to reflect on screen the precise
132 state of the log data on disk should probably refresh their entire
133 display (relative to the cursor of the log entry on the top of the
134 screen). Programs only interested in a strictly sequential stream
135 of log data may treat SD_JOURNAL_INVALIDATE the same way as
136 SD_JOURNAL_APPEND, thus ignoring any changes to the log view
137 earlier than the old end of the log stream.
138
140 In general, sd_journal_get_fd(), sd_journal_get_events(), and
141 sd_journal_get_timeout() are not "async signal safe" in the meaning of
142 signal-safety(7). Nevertheless, only the first call to any of those
143 three functions performs unsafe operations, so subsequent calls are
144 safe.
145
146 sd_journal_process() and sd_journal_wait() are not safe.
147 sd_journal_reliable_fd() is safe.
148
150 All functions listed here are thread-agnostic and only a single
151 specific thread may operate on a given object during its entire
152 lifetime. It's safe to allocate multiple independent objects and use
153 each from a specific thread in parallel. However, it's not safe to
154 allocate such an object in one thread, and operate or free it from any
155 other, even if locking is used to ensure these threads don't operate on
156 it at the very same time.
157
158 These APIs are implemented as a shared library, which can be compiled
159 and linked to with the libsystemd pkg-config(1) file.
160
162 Iterating through the journal, in a live view tracking all changes:
163
164 /* SPDX-License-Identifier: CC0-1.0 */
165
166 #include <stdio.h>
167 #include <string.h>
168 #include <systemd/sd-journal.h>
169
170 int main(int argc, char *argv[]) {
171 int r;
172 sd_journal *j;
173 r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
174 if (r < 0) {
175 fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
176 return 1;
177 }
178 for (;;) {
179 const void *d;
180 size_t l;
181 r = sd_journal_next(j);
182 if (r < 0) {
183 fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r));
184 break;
185 }
186 if (r == 0) {
187 /* Reached the end, let's wait for changes, and try again */
188 r = sd_journal_wait(j, (uint64_t) -1);
189 if (r < 0) {
190 fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r));
191 break;
192 }
193 continue;
194 }
195 r = sd_journal_get_data(j, "MESSAGE", &d, &l);
196 if (r < 0) {
197 fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
198 continue;
199 }
200 printf("%.*s\n", (int) l, (const char*) d);
201 }
202 sd_journal_close(j);
203 return 0;
204 }
205
206 Waiting with poll() (this example lacks all error checking for the sake
207 of simplicity):
208
209 /* SPDX-License-Identifier: CC0-1.0 */
210
211 #include <poll.h>
212 #include <time.h>
213 #include <systemd/sd-journal.h>
214
215 int wait_for_changes(sd_journal *j) {
216 uint64_t t;
217 int msec;
218 struct pollfd pollfd;
219
220 sd_journal_get_timeout(j, &t);
221 if (t == (uint64_t) -1)
222 msec = -1;
223 else {
224 struct timespec ts;
225 uint64_t n;
226 clock_gettime(CLOCK_MONOTONIC, &ts);
227 n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
228 msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
229 }
230
231 pollfd.fd = sd_journal_get_fd(j);
232 pollfd.events = sd_journal_get_events(j);
233 poll(&pollfd, 1, msec);
234 return sd_journal_process(j);
235 }
236
238 systemd(1), sd-journal(3), sd_journal_open(3), sd_journal_next(3),
239 poll(2), clock_gettime(2)
240
241
242
243systemd 251 SD_JOURNAL_GET_FD(3)