X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=man%2Fsd_journal_get_fd.xml;h=809f00b9f3b8c98e62e4801d639b89752160bc60;hb=51cb9d734a182c4892a6b31f58d75489a2ca432b;hp=6c2660c4a4cb6d65acca0a1bb3fdf354da3c0675;hpb=19125c205aa6084c225b5c11cc6dcbe18c6dbcc0;p=elogind.git
diff --git a/man/sd_journal_get_fd.xml b/man/sd_journal_get_fd.xml
index 6c2660c4a..809f00b9f 100644
--- a/man/sd_journal_get_fd.xml
+++ b/man/sd_journal_get_fd.xml
@@ -44,8 +44,14 @@
sd_journal_get_fd
+ sd_journal_get_events
+ sd_journal_get_timeout
sd_journal_process
sd_journal_wait
+ sd_journal_reliable_fd
+ SD_JOURNAL_NOP
+ SD_JOURNAL_APPEND
+ SD_JOURNAL_INVALIDATE
Journal change notification
interface
@@ -56,20 +62,36 @@
int sd_journal_get_fd
- sd_journal* j
+ sd_journal *j
+
+
+
+ int sd_journal_get_events
+ sd_journal *j
+
+
+
+ int sd_journal_get_timeout
+ sd_journal *j
+ uint64_t *timeout_usec
int sd_journal_process
- sd_journal* j
+ sd_journal *j
int sd_journal_wait
- sd_journal* j
+ sd_journal *j
uint64_t timeout_usec
+
+ int sd_journal_reliable_fd
+ sd_journal *j
+
+
@@ -78,57 +100,147 @@
sd_journal_get_fd() returns
a file descriptor that may be asynchronously polled in
- an external event loop and is signalled readable as
- soon as the journal changes, for example because new
- entries were added. The file descriptor is suitable
+ an external event loop and is signaled as soon as the
+ journal changes, because new entries or files were
+ added, rotation took place, or files have been
+ deleted, and similar. The file descriptor is suitable
for usage in
- poll2
- where it will yield POLLIN on all changes. The call
- takes one argument: the journal context object.
+ poll2. Use
+ sd_journal_get_events() for an
+ 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 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
+ sd_journal_reliable_fd(),
+ below. sd_journal_get_timeout()
+ will ensure in these cases that wake-ups happen
+ frequently enough for changes to be noticed, although
+ with a certain latency.
+
+ sd_journal_get_events()
+ will return the poll() mask to
+ wait for. This function will return a combination of
+ POLLIN and
+ POLLOUT and similar to fill into
+ the .events field of
+ struct pollfd.
+
+ sd_journal_get_timeout()
+ will return a timeout value for usage in
+ poll(). This returns a value in
+ microseconds since the epoch of
+ CLOCK_MONOTONIC for timing out
+ poll() in
+ timeout_usec. See
+ clock_gettime2
+ for details about
+ CLOCK_MONOTONIC. If there is no
+ timeout to wait for, this will fill in
+ (uint64_t) -1 instead. Note that
+ poll() 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:
- After each POLLIN wake-up
+ 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;
+}
+
+ The code above does not do any error checking
+ for brevity's sake. The calculated msec
+ integer can be passed directly as
+ poll()'s timeout
+ parameter.
+
+ After each poll() wake-up
sd_journal_process() needs to be
- called to process events and reset the readable state
- of the file descriptor. This call will also indicate
+ called to process events. This call will also indicate
what kind of change has been detected (see below; note
that spurious wake-ups are possible).
A synchronous alternative for using
- sd_journal_get_fd() and
+ sd_journal_get_fd(),
+ sd_journal_get_events(),
+ sd_journal_get_timeout() and
sd_journal_process() is
sd_journal_wait(). It will
- synchronously wait until the journal gets changed up
- to a certain time-out as specified in its second
- argument. Pass (uint64_t) -1 to
+ synchronously wait until the journal gets changed. The
+ maximum time this call sleeps may be controlled with
+ the timeout_usec
+ parameter. Pass (uint64_t) -1 to
wait indefinitely. Internally this call simply
combines sd_journal_get_fd(),
+ sd_journal_get_events(),
+ sd_journal_get_timeout(),
poll() and
sd_journal_process() into
one.
+ sd_journal_reliable_fd()
+ may be used to check whether the wakeup events from
+ the file descriptor returned by
+ sd_journal_get_fd() 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
+ sd_journal_get_timeout() on these
+ file systems will ask for timeouts explicitly
+ anyway.
Return Value
- sd_journal_get_fd() returns a valid file descriptor on success or a negative errno-style error
- code.
+ sd_journal_get_fd() returns
+ a valid file descriptor on success or a negative
+ errno-style error code.
+
+ sd_journal_get_events()
+ returns a combination of POLLIN,
+ POLLOUT and suchlike on success or
+ a negative errno-style error code.
+
+ sd_journal_reliable_fd()
+ returns a positive integer if the file descriptor
+ returned by sd_journal_get_fd()
+ will generate wake-ups immediately for all journal
+ changes. Returns 0 if there might be a latency
+ involved.
sd_journal_process() and
sd_journal_wait() return one of
- SD_JOURNAL_NOP,
- SD_JOURNAL_APPEND or
- SD_JOURNAL_INVALIDATE on success or
+ SD_JOURNAL_NOP,
+ SD_JOURNAL_APPEND or
+ SD_JOURNAL_INVALIDATE on success or
a negative errno-style error code. If
- SD_JOURNAL_NOP is returned the
- journal didn't change since the last invocation. If
- SD_JOURNAL_APPEND is returned new
+ SD_JOURNAL_NOP is returned, the
+ journal did not change since the last invocation. If
+ SD_JOURNAL_APPEND is returned, new
entries have been appended to the end of the
- journal. If SD_JOURNAL_INVALIDATE
+ journal. If SD_JOURNAL_INVALIDATE,
journal files were added or removed (possibly due to
- rotation). In the latter event live-view UIs should
- probably refresh their entire display while in the
- case of SD_JOURNAL_APPEND it is
+ rotation). In the latter event, live-view UIs should
+ probably refresh their entire display, while in the
+ case of SD_JOURNAL_APPEND, it is
sufficient to simply continue reading at the previous
end of the journal.
@@ -137,15 +249,90 @@
Notes
The sd_journal_get_fd(),
+ sd_journal_get_events(),
+ sd_journal_reliable_fd(),
sd_journal_process() and
sd_journal_wait() interfaces are
- available as shared library, which can be compiled and
+ available as a shared library, which can be compiled and
linked to with the
- libsystemd-journal
- pkg-config1
+ libsystemd pkg-config1
file.
+
+ Examples
+
+ Iterating through the journal, in a live view tracking all changes:
+
+ #include <stdio.h>
+#include <string.h>
+#include <systemd/sd-journal.h>
+
+int main(int argc, char *argv[]) {
+ int r;
+ sd_journal *j;
+ r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
+ if (r < 0) {
+ fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
+ return 1;
+ }
+ for (;;) {
+ const void *d;
+ size_t l;
+ r = sd_journal_next(j);
+ if (r < 0) {
+ fprintf(stderr, "Failed to iterate to next entry: %s\n", strerror(-r));
+ break;
+ }
+ if (r == 0) {
+ /* Reached the end, let's wait for changes, and try again */
+ r = sd_journal_wait(j, (uint64_t) -1);
+ if (r < 0) {
+ fprintf(stderr, "Failed to wait for changes: %s\n", strerror(-r));
+ break;
+ }
+ continue;
+ }
+ r = sd_journal_get_data(j, "MESSAGE", &d, &l);
+ if (r < 0) {
+ fprintf(stderr, "Failed to read message field: %s\n", strerror(-r));
+ continue;
+ }
+ printf("%.*s\n", (int) l, (const char*) d);
+ }
+ sd_journal_close(j);
+ return 0;
+}
+
+ Waiting with poll() (this
+ example lacks all error checking for the sake of
+ simplicity):
+
+ #include <sys/poll.h>
+#include <systemd/sd-journal.h>
+
+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, msec);
+ return sd_journal_process(j);
+}
+
+
See Also
@@ -153,7 +340,9 @@
systemd1,
sd-journal3,
sd_journal_open3,
- sd_journal_next3
+ sd_journal_next3,
+ poll2,
+ clock_gettime2