summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2013-04-04 20:07:48 +0200
committerLennart Poettering <lennart@poettering.net>2013-04-04 20:07:48 +0200
commit39c155ea0d8b24895017fd5cf48508924ce2016d (patch)
tree78512394533074c85ad3df2d3ae2ecc98c89dd29
parent667c24a6a86a5a26a906b7477ae81dcf4c73e64e (diff)
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.
-rw-r--r--man/sd_journal_get_fd.xml130
-rw-r--r--src/journal/journal-internal.h2
-rw-r--r--src/journal/libsystemd-journal.sym1
-rw-r--r--src/journal/sd-journal.c43
-rw-r--r--src/systemd/sd-journal.h3
5 files changed, 134 insertions, 45 deletions
diff --git a/man/sd_journal_get_fd.xml b/man/sd_journal_get_fd.xml
index f29aeaab23..33d2980b3b 100644
--- a/man/sd_journal_get_fd.xml
+++ b/man/sd_journal_get_fd.xml
@@ -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, &amp;t);
+if (t == (uint64_t) -1)
+ msec = -1;
+else {
+ struct timespec ts;
+ uint64_t n;
+ clock_getttime(CLOCK_MONOTONIC, &amp;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, &amp;t);
+ if (t == (uint64_t) -1)
+ msec = -1;
+ else {
+ struct timespec ts;
+ uint64_t n;
+ clock_getttime(CLOCK_MONOTONIC, &amp;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(&amp;pollfd, 1, sd_journal_reliable_fd(j) &gt; 0 ? -1 : 2000);
+ poll(&amp;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>
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
index bc9e44d42d..3accf14c05 100644
--- a/src/journal/journal-internal.h
+++ b/src/journal/journal-internal.h
@@ -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);
diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym
index e241318cb0..cdebf10ded 100644
--- a/src/journal/libsystemd-journal.sym
+++ b/src/journal/libsystemd-journal.sym
@@ -97,4 +97,5 @@ global:
LIBSYSTEMD_JOURNAL_201 {
global:
sd_journal_get_events;
+ sd_journal_get_timeout;
} LIBSYSTEMD_JOURNAL_198;
diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c
index 3eba4cd0d1..c1f69827e9 100644
--- a/src/journal/sd-journal.c
+++ b/src/journal/sd-journal.c
@@ -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 (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 > JOURNAL_FILES_RECHECK_USEC)
- timeout_usec = JOURNAL_FILES_RECHECK_USEC;
+ if (timeout_usec == (uint64_t) -1 || timeout_usec > t)
+ timeout_usec = t;
}
do {
diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h
index aa7693af70..afafee2d82 100644
--- a/src/systemd/sd-journal.h
+++ b/src/systemd/sd-journal.h
@@ -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);