chiark / gitweb /
journal: add sd_journal_get_timeout() call to public API
authorLennart Poettering <lennart@poettering.net>
Thu, 4 Apr 2013 18:07:48 +0000 (20:07 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 4 Apr 2013 18:07:48 +0000 (20:07 +0200)
Let's do the wake-up logic on NFS internally, making things simpler for
users.

man/sd_journal_get_fd.xml
src/journal/journal-internal.h
src/journal/libsystemd-journal.sym
src/journal/sd-journal.c
src/systemd/sd-journal.h

index f29aeaab23e9b32b8398562920e2f7887cab00a0..33d2980b3b45390d495c79833029babcfa1b6fff 100644 (file)
         <refnamediv>
                 <refname>sd_journal_get_fd</refname>
                 <refname>sd_journal_get_events</refname>
         <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_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>
                 <refname>SD_JOURNAL_NOP</refname>
                 <refname>SD_JOURNAL_APPEND</refname>
                 <refname>SD_JOURNAL_INVALIDATE</refname>
@@ -70,8 +71,9 @@
                         </funcprototype>
 
                         <funcprototype>
                         </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>sd_journal* <parameter>j</parameter></paramdef>
+                                <paramdef>uint64_t* <parameter>timeout_usec</parameter></paramdef>
                         </funcprototype>
 
                         <funcprototype>
                         </funcprototype>
 
                         <funcprototype>
                                 <paramdef>uint64_t <parameter>timeout_usec</parameter></paramdef>
                         </funcprototype>
 
                                 <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>
 
                 </funcsynopsis>
         </refsynopsisdiv>
 
                 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
                 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>,
                 <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
 
                 <para><function>sd_journal_get_events()</function>
                 will return the <function>poll()</function> mask to
                 the <literal>.events</literal> field of
                 <literal>struct pollfd</literal>.</para>
 
                 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
 
                 <para>After each <function>poll()</function> wake-up
                 <function>sd_journal_process()</function> needs to be
                 <para>A synchronous alternative for using
                 <function>sd_journal_get_fd()</function>,
                 <function>sd_journal_get_events()</function>,
                 <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
                 <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_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>
                 <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>
         </refsect1>
 
         <refsect1>
                 <para><function>sd_journal_reliable_fd()</function>
                 returns a positive integer if the file descriptor
                 returned by <function>sd_journal_get_fd()</function>
                 <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
 
                 <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 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);
         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>
         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>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>
 
                 </para>
         </refsect1>
 
index bc9e44d42d335819299ab108b254a431f0675794..3accf14c05ee98734d62b68cef11c8dc7b1248fb 100644 (file)
@@ -126,6 +126,8 @@ struct sd_journal {
         size_t data_threshold;
 
         Set *errors;
         size_t data_threshold;
 
         Set *errors;
+
+        usec_t last_process_usec;
 };
 
 char *journal_make_match_string(sd_journal *j);
 };
 
 char *journal_make_match_string(sd_journal *j);
index e241318cb039f8dd0817747f4d095d992a6c13f8..cdebf10dedcb8e9915b0a68ebc0dd689b0f2158b 100644 (file)
@@ -97,4 +97,5 @@ global:
 LIBSYSTEMD_JOURNAL_201 {
 global:
         sd_journal_get_events;
 LIBSYSTEMD_JOURNAL_201 {
 global:
         sd_journal_get_events;
+        sd_journal_get_timeout;
 } LIBSYSTEMD_JOURNAL_198;
 } LIBSYSTEMD_JOURNAL_198;
index 3eba4cd0d1e8ed1964e43d1c91e493759575dce3..c1f69827e98cd1754049cfd71e3906e4d617ee39 100644 (file)
@@ -1994,6 +1994,30 @@ _public_ int sd_journal_get_events(sd_journal *j) {
         return POLLIN;
 }
 
         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;
 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;
 
         if (!j)
                 return -EINVAL;
 
+        j->last_process_usec = now(CLOCK_MONOTONIC);
+
         for (;;) {
                 struct inotify_event *e;
                 ssize_t l;
         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;
 
 _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
         int r;
+        uint64_t t;
 
         assert(j);
 
 
         assert(j);
 
@@ -2127,12 +2154,18 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) {
                 return determine_change(j);
         }
 
                 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 {
         }
 
         do {
index aa7693af70ba57b454d9e8241f910951cadc8ead..afafee2d8279fe629eb9f83cf0bb2862e8a6615c 100644 (file)
@@ -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_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_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);
 
 int sd_journal_get_catalog(sd_journal *j, char **text);
 int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret);