[systemd-commits] man/sd_journal_get_fd.xml src/journal src/systemd

Lennart Poettering lennart at kemper.freedesktop.org
Thu Apr 4 11:09:28 PDT 2013


 man/sd_journal_get_fd.xml          |  130 +++++++++++++++++++++++++------------
 src/journal/journal-internal.h     |    2 
 src/journal/libsystemd-journal.sym |    1 
 src/journal/sd-journal.c           |   43 ++++++++++--
 src/systemd/sd-journal.h           |    3 
 5 files changed, 134 insertions(+), 45 deletions(-)

New commits:
commit 39c155ea0d8b24895017fd5cf48508924ce2016d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Apr 4 20:07:48 2013 +0200

    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.

diff --git a/man/sd_journal_get_fd.xml b/man/sd_journal_get_fd.xml
index f29aeaa..33d2980 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, &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>
 
diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h
index bc9e44d..3accf14 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 e241318..cdebf10 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 3eba4cd..c1f6982 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 aa7693a..afafee2 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);



More information about the systemd-commits mailing list