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 wakeup events
86 from the file descriptor returned by sd_journal_get_fd() are known to
87 be immediately triggered. On certain file systems where file change
88 events from the OS are not available (such as NFS) changes need to be
89 polled for repeatedly, and hence are detected only with a certain
90 latency. This call will return a positive value if the journal changes
91 are detected immediately and zero when they need to be polled for and
92 hence might be noticed only with a certain latency. Note that there is
93 usually no need to invoke this function directly as
94 sd_journal_get_timeout() on these file systems will ask for timeouts
95 explicitly anyway.
96
98 sd_journal_get_fd() returns a valid file descriptor on success or a
99 negative errno-style error code.
100
101 sd_journal_get_events() returns a combination of POLLIN, POLLOUT and
102 suchlike on success or a negative errno-style error code.
103
104 sd_journal_reliable_fd() returns a positive integer if the file
105 descriptor returned by sd_journal_get_fd() will generate wake-ups
106 immediately for all journal changes. Returns 0 if there might be a
107 latency involved.
108
109 sd_journal_process() and sd_journal_wait() return a negative
110 errno-style error code, or one of SD_JOURNAL_NOP, SD_JOURNAL_APPEND or
111 SD_JOURNAL_INVALIDATE on success:
112
113 · If SD_JOURNAL_NOP is returned, the journal did not change since the
114 last invocation.
115
116 · If SD_JOURNAL_APPEND is returned, new entries have been appended to
117 the end of the journal. In this case it is sufficient to simply
118 continue reading at the previous end location of the journal, to
119 read the newly added entries.
120
121 · If SD_JOURNAL_INVALIDATE, journal files were added to or removed
122 from the set of journal files watched (e.g. due to rotation or
123 vacuuming), and thus entries might have appeared or disappeared at
124 arbitrary places in the log stream, possibly before or after the
125 previous end of the log stream. If SD_JOURNAL_INVALIDATE is
126 returned, live-view UIs that want to reflect on screen the precise
127 state of the log data on disk should probably refresh their entire
128 display (relative to the cursor of the log entry on the top of the
129 screen). Programs only interested in a strictly sequential stream
130 of log data may treat SD_JOURNAL_INVALIDATE the same way as
131 SD_JOURNAL_APPEND, thus ignoring any changes to the log view
132 earlier than the old end of the log stream.
133
135 In general, sd_journal_get_fd(), sd_journal_get_events(), and
136 sd_journal_get_timeout() are not "async signal safe" in the meaning of
137 signal-safety(7). Nevertheless, only the first call to any of those
138 three functions performs unsafe operations, so subsequent calls are
139 safe.
140
141 sd_journal_process() and sd_journal_wait() are not safe.
142 sd_journal_reliable_fd() is safe.
143
145 The sd_journal_get_fd(), sd_journal_get_events(),
146 sd_journal_reliable_fd(), sd_journal_process() and sd_journal_wait()
147 interfaces are available as a shared library, which can be compiled and
148 linked to with the libsystemd pkg-config(1) file.
149
151 Iterating through the journal, in a live view tracking all changes:
152
153 #include <stdio.h>
154 #include <string.h>
155 #include <systemd/sd-journal.h>
156
157 int main(int argc, char *argv[]) {
158 int r;
159 sd_journal *j;
160 r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
161 if (r < 0) {
162 fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
163 return 1;
164 }
165 for (;;) {
166 const void *d;
167 size_t l;
168 r = sd_journal_next(j);
169 if (r < 0) {
170 fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r));
171 break;
172 }
173 if (r == 0) {
174 /* Reached the end, let's wait for changes, and try again */
175 r = sd_journal_wait(j, (uint64_t) -1);
176 if (r < 0) {
177 fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r));
178 break;
179 }
180 continue;
181 }
182 r = sd_journal_get_data(j, "MESSAGE", &d, &l);
183 if (r < 0) {
184 fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
185 continue;
186 }
187 printf("%.*s\n", (int) l, (const char*) d);
188 }
189 sd_journal_close(j);
190 return 0;
191 }
192
193 Waiting with poll() (this example lacks all error checking for the sake
194 of simplicity):
195
196 #include <poll.h>
197 #include <time.h>
198 #include <systemd/sd-journal.h>
199
200 int wait_for_changes(sd_journal *j) {
201 uint64_t t;
202 int msec;
203 struct pollfd pollfd;
204
205 sd_journal_get_timeout(j, &t);
206 if (t == (uint64_t) -1)
207 msec = -1;
208 else {
209 struct timespec ts;
210 uint64_t n;
211 clock_gettime(CLOCK_MONOTONIC, &ts);
212 n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
213 msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
214 }
215
216 pollfd.fd = sd_journal_get_fd(j);
217 pollfd.events = sd_journal_get_events(j);
218 poll(&pollfd, 1, msec);
219 return sd_journal_process(j);
220 }
221
223 systemd(1), sd-journal(3), sd_journal_open(3), sd_journal_next(3),
224 poll(2), clock_gettime(2)
225
226
227
228systemd 239 SD_JOURNAL_GET_FD(3)