Skip to content

Commit 39c155e

Browse files
committed
journal: add sd_journal_get_timeout() call to public API
Let's do the wake-up logic on NFS internally, making things simpler for users.
1 parent 667c24a commit 39c155e

File tree

5 files changed

+134
-45
lines changed

5 files changed

+134
-45
lines changed

man/sd_journal_get_fd.xml

Lines changed: 91 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@
4545
<refnamediv>
4646
<refname>sd_journal_get_fd</refname>
4747
<refname>sd_journal_get_events</refname>
48-
<refname>sd_journal_reliable_fd</refname>
48+
<refname>sd_journal_get_timeout</refname>
4949
<refname>sd_journal_process</refname>
5050
<refname>sd_journal_wait</refname>
51+
<refname>sd_journal_reliable_fd</refname>
5152
<refname>SD_JOURNAL_NOP</refname>
5253
<refname>SD_JOURNAL_APPEND</refname>
5354
<refname>SD_JOURNAL_INVALIDATE</refname>
@@ -70,8 +71,9 @@
7071
</funcprototype>
7172

7273
<funcprototype>
73-
<funcdef>int <function>sd_journal_reliable_fd</function></funcdef>
74+
<funcdef>int <function>sd_journal_get_timeout</function></funcdef>
7475
<paramdef>sd_journal* <parameter>j</parameter></paramdef>
76+
<paramdef>uint64_t* <parameter>timeout_usec</parameter></paramdef>
7577
</funcprototype>
7678

7779
<funcprototype>
@@ -85,6 +87,11 @@
8587
<paramdef>uint64_t <parameter>timeout_usec</parameter></paramdef>
8688
</funcprototype>
8789

90+
<funcprototype>
91+
<funcdef>int <function>sd_journal_reliable_fd</function></funcdef>
92+
<paramdef>sd_journal* <parameter>j</parameter></paramdef>
93+
</funcprototype>
94+
8895
</funcsynopsis>
8996
</refsynopsisdiv>
9097

@@ -103,16 +110,15 @@
103110
events mask to watch for. The call takes one argument:
104111
the journal context object. Note that not all file
105112
systems are capable of generating the necessary events
106-
for wakeups from this file descriptor to be enirely
107-
reliable. In particular network files systems do not
108-
generate suitable file change events in all cases. In
109-
such a case an application should not rely alone on
110-
wake-ups from this file descriptor but wake up and
111-
recheck the journal in regular time intervals, for
112-
example every 2s. To detect cases where this is
113-
necessary, use
113+
for wakeups from this file descriptor for changes to
114+
be noticed immediately. In particular network files
115+
systems do not generate suitable file change events in
116+
all cases. Cases like this can be detected with
114117
<function>sd_journal_reliable_fd()</function>,
115-
below.</para>
118+
below. <function>sd_journal_get_timeout()</function>
119+
will ensure in these cases that wake-ups happen
120+
frequently enough for changes to be noticed, although
121+
with a certain latency.</para>
116122

117123
<para><function>sd_journal_get_events()</function>
118124
will return the <function>poll()</function> mask to
@@ -122,17 +128,36 @@
122128
the <literal>.events</literal> field of
123129
<literal>struct pollfd</literal>.</para>
124130

125-
<para><function>sd_journal_reliable_fd()</function>
126-
may be used to check whether the wakeup events from
127-
the file descriptor returned by
128-
<function>sd_journal_get_fd</function> are sufficient
129-
to track changes to the journal. If this call returns
130-
0, it is necessary to regularly recheck for journal
131-
changes (suggestion: every 2s). If this call returns a
132-
positive integer this is not necessary, and wakeups
133-
from the file descriptor returned by
134-
<function>sd_journal_get_fd()</function> are
135-
sufficient as only source for wake-ups.</para>
131+
<para><function>sd_journal_get_timeout()</function>
132+
will return a timeout value for usage in <function>poll()</function>. This returns a value in microseconds since the epoch of CLOCK_MONOTONIC for timing out <function>poll()</function> in <literal>timeout_usec</literal>. See
133+
<citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
134+
for details about
135+
<literal>CLOCK_MONOTONIC</literal>. If there's no
136+
timeout to wait for this will fill in
137+
<literal>(uint64_t) -1</literal> instead. Note that
138+
<function>poll()</function> takes a relative timeout
139+
in milliseconds rather than an absolute timeout in
140+
microseconds. To convert the absolute 'us' timeout into
141+
relative 'ms', use code like the following:</para>
142+
143+
<programlisting>uint64_t t;
144+
int msec;
145+
sd_journal_get_timeout(m, &amp;t);
146+
if (t == (uint64_t) -1)
147+
msec = -1;
148+
else {
149+
struct timespec ts;
150+
uint64_t n;
151+
clock_getttime(CLOCK_MONOTONIC, &amp;ts);
152+
n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
153+
msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
154+
}</programlisting>
155+
156+
<para>The code above does not do any error checking
157+
for brevity's sake. The calculated <literal>msec</literal>
158+
integer can be passed directly as
159+
<function>poll()</function>'s timeout
160+
parameter.</para>
136161

137162
<para>After each <function>poll()</function> wake-up
138163
<function>sd_journal_process()</function> needs to be
@@ -143,22 +168,37 @@
143168
<para>A synchronous alternative for using
144169
<function>sd_journal_get_fd()</function>,
145170
<function>sd_journal_get_events()</function>,
146-
<function>sd_journal_reliable_fd()</function> and
171+
<function>sd_journal_get_timeout()</function> and
147172
<function>sd_journal_process()</function> is
148173
<function>sd_journal_wait()</function>. It will
149-
synchronously wait until the journal gets changed,
150-
possibly using a 2s time-out if this is necessary (see
151-
above). In either way the maximum time this call
152-
sleeps may be controlled with the
153-
<parameter>timeout_usec</parameter> parameter. Pass
154-
<literal>(uint64_t) -1</literal> to wait
155-
indefinitely. Internally this call simply combines
156-
<function>sd_journal_get_fd()</function>,
174+
synchronously wait until the journal gets changed. The
175+
maximum time this call sleeps may be controlled with
176+
the <parameter>timeout_usec</parameter>
177+
parameter. Pass <literal>(uint64_t) -1</literal> to
178+
wait indefinitely. Internally this call simply
179+
combines <function>sd_journal_get_fd()</function>,
157180
<function>sd_journal_get_events()</function>,
158-
<function>sd_journal_reliable_fd()</function>,
181+
<function>sd_journal_get_timeout()</function>,
159182
<function>poll()</function> and
160183
<function>sd_journal_process()</function> into
161184
one.</para>
185+
186+
<para><function>sd_journal_reliable_fd()</function>
187+
may be used to check whether the wakeup events from
188+
the file descriptor returned by
189+
<function>sd_journal_get_fd()</function> are known to
190+
be immediately triggered. On certain file systems
191+
where file change events from the OS are not available
192+
(such as NFS) changes need to be polled for
193+
repeatedly, and hence are detected only with a certain
194+
latency. This call will return a positive value if the
195+
journal changes are detected immediately and zero when
196+
they need to be polled for and hence might be noticed
197+
only with a certain latency. Note that there's usually
198+
no need to invoke this function directly as
199+
<function>sd_journal_get_timeout()</function> on these
200+
file systems will ask for timeouts explicitly
201+
anyway.</para>
162202
</refsect1>
163203

164204
<refsect1>
@@ -176,11 +216,9 @@
176216
<para><function>sd_journal_reliable_fd()</function>
177217
returns a positive integer if the file descriptor
178218
returned by <function>sd_journal_get_fd()</function>
179-
is sufficient as sole wake-up source for journal
180-
change events. Returns 0 if it is not sufficient and
181-
the journal needs to be checked manually in regular
182-
time intervals for changes. Returns a negative
183-
errno-style error code on failure.</para>
219+
will generate wake-ups immediately for all journal
220+
changes. Returns 0 if there might be a latency
221+
involved.</para>
184222

185223
<para><function>sd_journal_process()</function> and
186224
<function>sd_journal_wait()</function> return one of
@@ -270,9 +308,22 @@ int main(int argc, char *argv[]) {
270308

271309
int wait_for_changes(sd_journal *j) {
272310
struct pollfd pollfd;
311+
int msec;
312+
313+
sd_journal_get_timeout(m, &amp;t);
314+
if (t == (uint64_t) -1)
315+
msec = -1;
316+
else {
317+
struct timespec ts;
318+
uint64_t n;
319+
clock_getttime(CLOCK_MONOTONIC, &amp;ts);
320+
n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
321+
msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
322+
}
323+
273324
pollfd.fd = sd_journal_get_fd(j);
274325
pollfd.events = sd_journal_get_events(j);
275-
poll(&amp;pollfd, 1, sd_journal_reliable_fd(j) &gt; 0 ? -1 : 2000);
326+
poll(&amp;pollfd, 1, msec);
276327
return sd_journal_process(j);
277328
}
278329
</programlisting>
@@ -286,7 +337,8 @@ int wait_for_changes(sd_journal *j) {
286337
<citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
287338
<citerefentry><refentrytitle>sd_journal_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
288339
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
289-
<citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry>
340+
<citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
341+
<citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
290342
</para>
291343
</refsect1>
292344

src/journal/journal-internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ struct sd_journal {
126126
size_t data_threshold;
127127

128128
Set *errors;
129+
130+
usec_t last_process_usec;
129131
};
130132

131133
char *journal_make_match_string(sd_journal *j);

src/journal/libsystemd-journal.sym

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,5 @@ global:
9797
LIBSYSTEMD_JOURNAL_201 {
9898
global:
9999
sd_journal_get_events;
100+
sd_journal_get_timeout;
100101
} LIBSYSTEMD_JOURNAL_198;

src/journal/sd-journal.c

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,6 +1994,30 @@ _public_ int sd_journal_get_events(sd_journal *j) {
19941994
return POLLIN;
19951995
}
19961996

1997+
_public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
1998+
int fd;
1999+
2000+
if (!j)
2001+
return -EINVAL;
2002+
if (!timeout_usec)
2003+
return -EINVAL;
2004+
2005+
fd = sd_journal_get_fd(j);
2006+
if (fd < 0)
2007+
return fd;
2008+
2009+
if (!j->on_network) {
2010+
*timeout_usec = (uint64_t) -1;
2011+
return 0;
2012+
}
2013+
2014+
/* If we are on the network we need to regularly check for
2015+
* changes manually */
2016+
2017+
*timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC;
2018+
return 1;
2019+
}
2020+
19972021
static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
19982022
Directory *d;
19992023
int r;
@@ -2076,6 +2100,8 @@ _public_ int sd_journal_process(sd_journal *j) {
20762100
if (!j)
20772101
return -EINVAL;
20782102

2103+
j->last_process_usec = now(CLOCK_MONOTONIC);
2104+
20792105
for (;;) {
20802106
struct inotify_event *e;
20812107
ssize_t l;
@@ -2109,6 +2135,7 @@ _public_ int sd_journal_process(sd_journal *j) {
21092135

21102136
_public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
21112137
int r;
2138+
uint64_t t;
21122139

21132140
assert(j);
21142141

@@ -2127,12 +2154,18 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
21272154
return determine_change(j);
21282155
}
21292156

2130-
if (j->on_network) {
2131-
/* If we are on the network we need to regularly check
2132-
* for changes manually */
2157+
r = sd_journal_get_timeout(j, &t);
2158+
if (r < 0)
2159+
return r;
2160+
2161+
if (t != (uint64_t) -1) {
2162+
usec_t n;
2163+
2164+
n = now(CLOCK_MONOTONIC);
2165+
t = t > n ? t - n : 0;
21332166

2134-
if (timeout_usec == (uint64_t) -1 || timeout_usec > JOURNAL_FILES_RECHECK_USEC)
2135-
timeout_usec = JOURNAL_FILES_RECHECK_USEC;
2167+
if (timeout_usec == (uint64_t) -1 || timeout_usec > t)
2168+
timeout_usec = t;
21362169
}
21372170

21382171
do {

src/systemd/sd-journal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,10 @@ void sd_journal_restart_unique(sd_journal *j);
128128

129129
int sd_journal_get_fd(sd_journal *j);
130130
int sd_journal_get_events(sd_journal *j);
131-
int sd_journal_reliable_fd(sd_journal *j);
131+
int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec);
132132
int sd_journal_process(sd_journal *j);
133133
int sd_journal_wait(sd_journal *j, uint64_t timeout_usec);
134+
int sd_journal_reliable_fd(sd_journal *j);
134135

135136
int sd_journal_get_catalog(sd_journal *j, char **text);
136137
int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret);

0 commit comments

Comments
 (0)