mirror of
https://github.com/systemd/systemd.git
synced 2024-11-24 02:33:36 +08:00
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.
This commit is contained in:
parent
667c24a6a8
commit
39c155ea0d
@ -45,9 +45,10 @@
|
||||
<refnamediv>
|
||||
<refname>sd_journal_get_fd</refname>
|
||||
<refname>sd_journal_get_events</refname>
|
||||
<refname>sd_journal_reliable_fd</refname>
|
||||
<refname>sd_journal_get_timeout</refname>
|
||||
<refname>sd_journal_process</refname>
|
||||
<refname>sd_journal_wait</refname>
|
||||
<refname>sd_journal_reliable_fd</refname>
|
||||
<refname>SD_JOURNAL_NOP</refname>
|
||||
<refname>SD_JOURNAL_APPEND</refname>
|
||||
<refname>SD_JOURNAL_INVALIDATE</refname>
|
||||
@ -70,8 +71,9 @@
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_journal_reliable_fd</function></funcdef>
|
||||
<funcdef>int <function>sd_journal_get_timeout</function></funcdef>
|
||||
<paramdef>sd_journal* <parameter>j</parameter></paramdef>
|
||||
<paramdef>uint64_t* <parameter>timeout_usec</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
@ -85,6 +87,11 @@
|
||||
<paramdef>uint64_t <parameter>timeout_usec</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_journal_reliable_fd</function></funcdef>
|
||||
<paramdef>sd_journal* <parameter>j</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@ -103,16 +110,15 @@
|
||||
events mask to watch for. The call takes one argument:
|
||||
the journal context object. Note that not all file
|
||||
systems are capable of generating the necessary events
|
||||
for wakeups from this file descriptor to be enirely
|
||||
reliable. In particular network files systems do not
|
||||
generate suitable file change events in all cases. In
|
||||
such a case an application should not rely alone on
|
||||
wake-ups from this file descriptor but wake up and
|
||||
recheck the journal in regular time intervals, for
|
||||
example every 2s. To detect cases where this is
|
||||
necessary, use
|
||||
for wakeups from this file descriptor for changes to
|
||||
be noticed immediately. In particular network files
|
||||
systems do not generate suitable file change events in
|
||||
all cases. Cases like this can be detected with
|
||||
<function>sd_journal_reliable_fd()</function>,
|
||||
below.</para>
|
||||
below. <function>sd_journal_get_timeout()</function>
|
||||
will ensure in these cases that wake-ups happen
|
||||
frequently enough for changes to be noticed, although
|
||||
with a certain latency.</para>
|
||||
|
||||
<para><function>sd_journal_get_events()</function>
|
||||
will return the <function>poll()</function> mask to
|
||||
@ -122,17 +128,36 @@
|
||||
the <literal>.events</literal> field of
|
||||
<literal>struct pollfd</literal>.</para>
|
||||
|
||||
<para><function>sd_journal_reliable_fd()</function>
|
||||
may be used to check whether the wakeup events from
|
||||
the file descriptor returned by
|
||||
<function>sd_journal_get_fd</function> are sufficient
|
||||
to track changes to the journal. If this call returns
|
||||
0, it is necessary to regularly recheck for journal
|
||||
changes (suggestion: every 2s). If this call returns a
|
||||
positive integer this is not necessary, and wakeups
|
||||
from the file descriptor returned by
|
||||
<function>sd_journal_get_fd()</function> are
|
||||
sufficient as only source for wake-ups.</para>
|
||||
<para><function>sd_journal_get_timeout()</function>
|
||||
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
|
||||
<citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
for details about
|
||||
<literal>CLOCK_MONOTONIC</literal>. If there's no
|
||||
timeout to wait for this will fill in
|
||||
<literal>(uint64_t) -1</literal> instead. Note that
|
||||
<function>poll()</function> takes a relative timeout
|
||||
in milliseconds rather than an absolute timeout in
|
||||
microseconds. To convert the absolute 'us' timeout into
|
||||
relative 'ms', use code like the following:</para>
|
||||
|
||||
<programlisting>uint64_t t;
|
||||
int msec;
|
||||
sd_journal_get_timeout(m, &t);
|
||||
if (t == (uint64_t) -1)
|
||||
msec = -1;
|
||||
else {
|
||||
struct timespec ts;
|
||||
uint64_t n;
|
||||
clock_getttime(CLOCK_MONOTONIC, &ts);
|
||||
n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
|
||||
}</programlisting>
|
||||
|
||||
<para>The code above does not do any error checking
|
||||
for brevity's sake. The calculated <literal>msec</literal>
|
||||
integer can be passed directly as
|
||||
<function>poll()</function>'s timeout
|
||||
parameter.</para>
|
||||
|
||||
<para>After each <function>poll()</function> wake-up
|
||||
<function>sd_journal_process()</function> needs to be
|
||||
@ -143,22 +168,37 @@
|
||||
<para>A synchronous alternative for using
|
||||
<function>sd_journal_get_fd()</function>,
|
||||
<function>sd_journal_get_events()</function>,
|
||||
<function>sd_journal_reliable_fd()</function> and
|
||||
<function>sd_journal_get_timeout()</function> and
|
||||
<function>sd_journal_process()</function> is
|
||||
<function>sd_journal_wait()</function>. It will
|
||||
synchronously wait until the journal gets changed,
|
||||
possibly using a 2s time-out if this is necessary (see
|
||||
above). In either way the maximum time this call
|
||||
sleeps may be controlled with the
|
||||
<parameter>timeout_usec</parameter> parameter. Pass
|
||||
<literal>(uint64_t) -1</literal> to wait
|
||||
indefinitely. Internally this call simply combines
|
||||
<function>sd_journal_get_fd()</function>,
|
||||
synchronously wait until the journal gets changed. The
|
||||
maximum time this call sleeps may be controlled with
|
||||
the <parameter>timeout_usec</parameter>
|
||||
parameter. Pass <literal>(uint64_t) -1</literal> to
|
||||
wait indefinitely. Internally this call simply
|
||||
combines <function>sd_journal_get_fd()</function>,
|
||||
<function>sd_journal_get_events()</function>,
|
||||
<function>sd_journal_reliable_fd()</function>,
|
||||
<function>sd_journal_get_timeout()</function>,
|
||||
<function>poll()</function> and
|
||||
<function>sd_journal_process()</function> into
|
||||
one.</para>
|
||||
|
||||
<para><function>sd_journal_reliable_fd()</function>
|
||||
may be used to check whether the wakeup events from
|
||||
the file descriptor returned by
|
||||
<function>sd_journal_get_fd()</function> are known to
|
||||
be immediately triggered. On certain file systems
|
||||
where file change events from the OS are not available
|
||||
(such as NFS) changes need to be polled for
|
||||
repeatedly, and hence are detected only with a certain
|
||||
latency. This call will return a positive value if the
|
||||
journal changes are detected immediately and zero when
|
||||
they need to be polled for and hence might be noticed
|
||||
only with a certain latency. Note that there's usually
|
||||
no need to invoke this function directly as
|
||||
<function>sd_journal_get_timeout()</function> on these
|
||||
file systems will ask for timeouts explicitly
|
||||
anyway.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -176,11 +216,9 @@
|
||||
<para><function>sd_journal_reliable_fd()</function>
|
||||
returns a positive integer if the file descriptor
|
||||
returned by <function>sd_journal_get_fd()</function>
|
||||
is sufficient as sole wake-up source for journal
|
||||
change events. Returns 0 if it is not sufficient and
|
||||
the journal needs to be checked manually in regular
|
||||
time intervals for changes. Returns a negative
|
||||
errno-style error code on failure.</para>
|
||||
will generate wake-ups immediately for all journal
|
||||
changes. Returns 0 if there might be a latency
|
||||
involved.</para>
|
||||
|
||||
<para><function>sd_journal_process()</function> and
|
||||
<function>sd_journal_wait()</function> return one of
|
||||
@ -270,9 +308,22 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
int wait_for_changes(sd_journal *j) {
|
||||
struct pollfd pollfd;
|
||||
int msec;
|
||||
|
||||
sd_journal_get_timeout(m, &t);
|
||||
if (t == (uint64_t) -1)
|
||||
msec = -1;
|
||||
else {
|
||||
struct timespec ts;
|
||||
uint64_t n;
|
||||
clock_getttime(CLOCK_MONOTONIC, &ts);
|
||||
n = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
msec = t > n ? (int) ((t - n + 999) / 1000) : 0;
|
||||
}
|
||||
|
||||
pollfd.fd = sd_journal_get_fd(j);
|
||||
pollfd.events = sd_journal_get_events(j);
|
||||
poll(&pollfd, 1, sd_journal_reliable_fd(j) > 0 ? -1 : 2000);
|
||||
poll(&pollfd, 1, msec);
|
||||
return sd_journal_process(j);
|
||||
}
|
||||
</programlisting>
|
||||
@ -286,7 +337,8 @@ int wait_for_changes(sd_journal *j) {
|
||||
<citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_open</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>poll</refentrytitle><manvolnum>2</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
@ -126,6 +126,8 @@ struct sd_journal {
|
||||
size_t data_threshold;
|
||||
|
||||
Set *errors;
|
||||
|
||||
usec_t last_process_usec;
|
||||
};
|
||||
|
||||
char *journal_make_match_string(sd_journal *j);
|
||||
|
@ -97,4 +97,5 @@ global:
|
||||
LIBSYSTEMD_JOURNAL_201 {
|
||||
global:
|
||||
sd_journal_get_events;
|
||||
sd_journal_get_timeout;
|
||||
} LIBSYSTEMD_JOURNAL_198;
|
||||
|
@ -1994,6 +1994,30 @@ _public_ int sd_journal_get_events(sd_journal *j) {
|
||||
return POLLIN;
|
||||
}
|
||||
|
||||
_public_ int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec) {
|
||||
int fd;
|
||||
|
||||
if (!j)
|
||||
return -EINVAL;
|
||||
if (!timeout_usec)
|
||||
return -EINVAL;
|
||||
|
||||
fd = sd_journal_get_fd(j);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
if (!j->on_network) {
|
||||
*timeout_usec = (uint64_t) -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we are on the network we need to regularly check for
|
||||
* changes manually */
|
||||
|
||||
*timeout_usec = j->last_process_usec + JOURNAL_FILES_RECHECK_USEC;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void process_inotify_event(sd_journal *j, struct inotify_event *e) {
|
||||
Directory *d;
|
||||
int r;
|
||||
@ -2076,6 +2100,8 @@ _public_ int sd_journal_process(sd_journal *j) {
|
||||
if (!j)
|
||||
return -EINVAL;
|
||||
|
||||
j->last_process_usec = now(CLOCK_MONOTONIC);
|
||||
|
||||
for (;;) {
|
||||
struct inotify_event *e;
|
||||
ssize_t l;
|
||||
@ -2109,6 +2135,7 @@ _public_ int sd_journal_process(sd_journal *j) {
|
||||
|
||||
_public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
|
||||
int r;
|
||||
uint64_t t;
|
||||
|
||||
assert(j);
|
||||
|
||||
@ -2127,12 +2154,18 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
|
||||
return determine_change(j);
|
||||
}
|
||||
|
||||
if (j->on_network) {
|
||||
/* If we are on the network we need to regularly check
|
||||
* for changes manually */
|
||||
r = sd_journal_get_timeout(j, &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (timeout_usec == (uint64_t) -1 || timeout_usec > JOURNAL_FILES_RECHECK_USEC)
|
||||
timeout_usec = JOURNAL_FILES_RECHECK_USEC;
|
||||
if (t != (uint64_t) -1) {
|
||||
usec_t n;
|
||||
|
||||
n = now(CLOCK_MONOTONIC);
|
||||
t = t > n ? t - n : 0;
|
||||
|
||||
if (timeout_usec == (uint64_t) -1 || timeout_usec > t)
|
||||
timeout_usec = t;
|
||||
}
|
||||
|
||||
do {
|
||||
|
@ -128,9 +128,10 @@ void sd_journal_restart_unique(sd_journal *j);
|
||||
|
||||
int sd_journal_get_fd(sd_journal *j);
|
||||
int sd_journal_get_events(sd_journal *j);
|
||||
int sd_journal_reliable_fd(sd_journal *j);
|
||||
int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec);
|
||||
int sd_journal_process(sd_journal *j);
|
||||
int sd_journal_wait(sd_journal *j, uint64_t timeout_usec);
|
||||
int sd_journal_reliable_fd(sd_journal *j);
|
||||
|
||||
int sd_journal_get_catalog(sd_journal *j, char **text);
|
||||
int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret);
|
||||
|
Loading…
Reference in New Issue
Block a user