diff options
author | Lennart Poettering <lennart@poettering.net> | 2012-11-21 00:28:00 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2012-11-21 00:28:00 +0100 |
commit | 93b73b064c663d6248bebfbbbd82989b5ca10fc5 (patch) | |
tree | 464aea01e7952ddcf7088a594e0bfdf2e4647a0a | |
parent | f2cf0403c99e8fa44c14b0ef70af90801f8681f0 (diff) | |
download | systemd-93b73b064c663d6248bebfbbbd82989b5ca10fc5.tar.gz |
journal: by default do not decompress dat objects larger than 64K
This introduces a new data threshold setting for sd_journal objects
which controls the maximum size of objects to decompress. This is
relieves the library from having to decompress full data objects even
if a client program is only interested in the initial part of them.
This speeds up "systemd-coredumpctl" drastically when invoked without
parameters.
-rw-r--r-- | man/sd_journal_get_data.xml | 58 | ||||
-rw-r--r-- | man/sd_journal_query_unique.xml | 4 | ||||
-rw-r--r-- | src/journal/compress.c | 20 | ||||
-rw-r--r-- | src/journal/compress.h | 2 | ||||
-rw-r--r-- | src/journal/coredumpctl.c | 10 | ||||
-rw-r--r-- | src/journal/journal-file.c | 5 | ||||
-rw-r--r-- | src/journal/journal-internal.h | 2 | ||||
-rw-r--r-- | src/journal/journal-verify.c | 2 | ||||
-rw-r--r-- | src/journal/journald-server.c | 2 | ||||
-rw-r--r-- | src/journal/libsystemd-journal.sym | 2 | ||||
-rw-r--r-- | src/journal/sd-journal.c | 36 | ||||
-rw-r--r-- | src/shared/logs-show.c | 14 | ||||
-rw-r--r-- | src/systemd/sd-journal.h | 3 |
13 files changed, 135 insertions, 25 deletions
diff --git a/man/sd_journal_get_data.xml b/man/sd_journal_get_data.xml index 6470f19cc6..1259b0cdbe 100644 --- a/man/sd_journal_get_data.xml +++ b/man/sd_journal_get_data.xml @@ -47,6 +47,8 @@ <refname>sd_journal_enumerate_data</refname> <refname>sd_journal_restart_data</refname> <refname>SD_JOURNAL_FOREACH_DATA</refname> + <refname>sd_journal_set_data_threshold</refname> + <refname>sd_journal_get_data_threshold</refname> <refpurpose>Read data fields from the current journal entry</refpurpose> </refnamediv> @@ -81,6 +83,17 @@ <paramdef>size_t <parameter>length</parameter></paramdef> </funcprototype> + <funcprototype> + <funcdef>int <function>sd_journal_set_data_threshold</function></funcdef> + <paramdef>sd_journal* <parameter>j</parameter></paramdef> + <paramdef>size_t <parameter>sz</parameter></paramdef> + </funcprototype> + + <funcprototype> + <funcdef>int <function>sd_journal_get_data_threshold</function></funcdef> + <paramdef>sd_journal* <parameter>j</parameter></paramdef> + <paramdef>size_t* <parameter>sz</parameter></paramdef> + </funcprototype> </funcsynopsis> </refsynopsisdiv> @@ -102,7 +115,11 @@ <function>sd_journal_enumerate_data()</function>, or the read pointer is altered. Note that the data returned will be prefixed with the field name and - '='.</para> + '='. Also note that by default data fields larger than + 64K might get truncated to 64K. This threshold may be + changed and turned off with + <function>sd_journal_set_data_threshold()</function> (see + below).</para> <para><function>sd_journal_enumerate_data()</function> may be used to iterate through all fields of the @@ -128,6 +145,32 @@ <citerefentry><refentrytitle>sd_journal_next</refentrytitle><manvolnum>3</manvolnum></citerefentry> (or related call) has been called at least once, in order to position the read pointer at a valid entry.</para> + + <para><function>sd_journal_set_data_threshold()</function> + may be used to change the data field size threshold + for data returned by + <function>sd_journal_get_data()</function>, + <function>sd_journal_enumerate_data()</function> and + <function>sd_journal_enumerate_unique()</function>. This + threshold is a hint only: it indicates that the client + program is interested only in the initial parts of the + data fields, up to the threshold in size -- but the + library might still return larger data objects. That + means applications should not rely exclusively on this + setting to limit the size of the data fields returned, + but need to apply a explicit size limit on the + returned data as well. This threshold defaults to 64K + by default. To retrieve the complete data fields this + threshold should be turned off by setting it to 0, so + that the library always returns the complete data + objects. It is recommended to set this threshold as + low as possible since this relieves the library from + having to decompress large compressed data objects in + full.</para> + + <para><function>sd_journal_get_data_threshold()</function> + returns the currently configured data field size + threshold.</para> </refsect1> <refsect1> @@ -144,15 +187,22 @@ read, 0 when no more fields are known, or a negative errno-style error code. <function>sd_journal_restart_data()</function> - returns nothing.</para> + returns + nothing. <function>sd_journal_set_data_threshold()</function> + and <function>sd_journal_get_threshold()</function> + return 0 on success or a negative errno-style error + code.</para> </refsect1> <refsect1> <title>Notes</title> <para>The <function>sd_journal_get_data()</function>, - <function>sd_journal_enumerate_data()</function> and - <function>sd_journal_restart_data()</function> + <function>sd_journal_enumerate_data()</function>, + <function>sd_journal_restart_data()</function>, + <function>sd_journal_set_data_threshold()</function> + and + <function>sd_journal_get_data_threshold()</function> interfaces are available as shared library, which can be compiled and linked to with the <literal>libsystemd-journal</literal> diff --git a/man/sd_journal_query_unique.xml b/man/sd_journal_query_unique.xml index f2f8af0eb5..502a7e08c2 100644 --- a/man/sd_journal_query_unique.xml +++ b/man/sd_journal_query_unique.xml @@ -113,7 +113,9 @@ invocation of <function>sd_journal_enumerate_unique()</function>. Note that the data returned will be prefixed with the field - name and '='.</para> + name and '='. Note that this call is subject to the + data field size threshold as controlled by + <function>sd_journal_set_data_threshold()</function>.</para> <para><function>sd_journal_restart_unique()</function> resets the data enumeration index to the beginning of diff --git a/src/journal/compress.c b/src/journal/compress.c index 75e70c5ffa..a4427be75a 100644 --- a/src/journal/compress.c +++ b/src/journal/compress.c @@ -24,6 +24,7 @@ #include <string.h> #include <lzma.h> +#include "macro.h" #include "compress.h" bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size) { @@ -66,10 +67,11 @@ fail: } bool uncompress_blob(const void *src, uint64_t src_size, - void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size) { + void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size, uint64_t dst_max) { lzma_stream s = LZMA_STREAM_INIT; lzma_ret ret; + uint64_t space; bool b = false; assert(src); @@ -98,7 +100,8 @@ bool uncompress_blob(const void *src, uint64_t src_size, s.avail_in = src_size; s.next_out = *dst; - s.avail_out = *dst_alloc_size; + space = dst_max > 0 ? MIN(*dst_alloc_size, dst_max) : *dst_alloc_size; + s.avail_out = space; for (;;) { void *p; @@ -111,18 +114,23 @@ bool uncompress_blob(const void *src, uint64_t src_size, if (ret != LZMA_OK) goto fail; - p = realloc(*dst, *dst_alloc_size*2); + if (dst_max > 0 && (space - s.avail_out) >= dst_max) + break; + + p = realloc(*dst, space*2); if (!p) goto fail; s.next_out = (uint8_t*) p + ((uint8_t*) s.next_out - (uint8_t*) *dst); - s.avail_out += *dst_alloc_size; + s.avail_out += space; + + space *= 2; *dst = p; - *dst_alloc_size *= 2; + *dst_alloc_size = space; } - *dst_size = *dst_alloc_size - s.avail_out; + *dst_size = space - s.avail_out; b = true; fail: diff --git a/src/journal/compress.h b/src/journal/compress.h index b6f1aa0ed7..2b87e73a26 100644 --- a/src/journal/compress.h +++ b/src/journal/compress.h @@ -27,7 +27,7 @@ bool compress_blob(const void *src, uint64_t src_size, void *dst, uint64_t *dst_size); bool uncompress_blob(const void *src, uint64_t src_size, - void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size); + void **dst, uint64_t *dst_alloc_size, uint64_t* dst_size, uint64_t dst_max); bool uncompress_startswith(const void *src, uint64_t src_size, void **buffer, uint64_t *buffer_size, diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index 4adc9236f1..f9cebb7a42 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -342,6 +342,11 @@ static int dump_list(sd_journal *j) { assert(j); + /* The coredumps are likely to compressed, and for just + * listing them we don#t need to decompress them, so let's + * pick a fairly low data threshold here */ + sd_journal_set_data_threshold(j, 4096); + SD_JOURNAL_FOREACH(j) { if (field) print_field(stdout, j); @@ -381,6 +386,9 @@ static int dump_core(sd_journal* j) { assert(j); + /* We want full data, nothing truncated. */ + sd_journal_set_data_threshold(j, 0); + r = focus(j); if (r < 0) return r; @@ -428,6 +436,8 @@ static int run_gdb(sd_journal *j) { assert(j); + sd_journal_set_data_threshold(j, 0); + r = focus(j); if (r < 0) return r; diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index 3df099dbd2..13fc8edea9 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -780,7 +780,7 @@ int journal_file_find_data_object_with_hash( l -= offsetof(Object, data.payload); - if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize)) + if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize, 0)) return -EBADMSG; if (rsize == size && @@ -2591,7 +2591,6 @@ int journal_file_open_reliably( metrics, mmap_cache, template, ret); } - int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint64_t p, uint64_t *seqnum, Object **ret, uint64_t *offset) { uint64_t i, n; uint64_t q, xor_hash = 0; @@ -2645,7 +2644,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6 #ifdef HAVE_XZ uint64_t rsize; - if (!uncompress_blob(o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize)) + if (!uncompress_blob(o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize, 0)) return -EBADMSG; data = from->compress_buffer; diff --git a/src/journal/journal-internal.h b/src/journal/journal-internal.h index 75a4129e5b..97de0e75ff 100644 --- a/src/journal/journal-internal.h +++ b/src/journal/journal-internal.h @@ -121,6 +121,8 @@ struct sd_journal { uint64_t unique_offset; bool on_network; + + size_t data_threshold; }; char *journal_make_match_string(sd_journal *j); diff --git a/src/journal/journal-verify.c b/src/journal/journal-verify.c index 1a67d5a04b..ed28b45737 100644 --- a/src/journal/journal-verify.c +++ b/src/journal/journal-verify.c @@ -69,7 +69,7 @@ static int journal_file_object_verify(JournalFile *f, Object *o) { if (!uncompress_blob(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload), - &b, &alloc, &b_size)) + &b, &alloc, &b_size, 0)) return -EBADMSG; h2 = hash64(b, b_size); diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 3eaf0d3ee2..43ffe75560 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -934,6 +934,8 @@ int server_flush_to_var(Server *s) { return r; } + sd_journal_set_data_threshold(j, 0); + SD_JOURNAL_FOREACH(j) { Object *o = NULL; JournalFile *f; diff --git a/src/journal/libsystemd-journal.sym b/src/journal/libsystemd-journal.sym index 17b5bf80d9..7b602f59cb 100644 --- a/src/journal/libsystemd-journal.sym +++ b/src/journal/libsystemd-journal.sym @@ -86,4 +86,6 @@ global: sd_journal_fd_reliable; sd_journal_get_catalog; sd_journal_get_catalog_for_message_id; + sd_journal_set_data_threshold; + sd_journal_get_data_threshold; } LIBSYSTEMD_JOURNAL_195; diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c index fe0478f166..095fbb249c 100644 --- a/src/journal/sd-journal.c +++ b/src/journal/sd-journal.c @@ -47,6 +47,8 @@ #define REPLACE_VAR_MAX 256 +#define DEFAULT_DATA_THRESHOLD (64*1024) + static void detach_location(sd_journal *j) { Iterator i; JournalFile *f; @@ -1560,6 +1562,7 @@ static sd_journal *journal_new(int flags, const char *path) { j->inotify_fd = -1; j->flags = flags; + j->data_threshold = DEFAULT_DATA_THRESHOLD; if (path) { j->path = strdup(path); @@ -1838,7 +1841,8 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** uint64_t rsize; if (!uncompress_blob(o->data.payload, l, - &f->compress_buffer, &f->compress_buffer_size, &rsize)) + &f->compress_buffer, &f->compress_buffer_size, &rsize, + j->data_threshold)) return -EBADMSG; *data = f->compress_buffer; @@ -1862,7 +1866,7 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** *data = o->data.payload; *size = t; - return 0; + return 1; } r = journal_file_move_to_object(f, OBJECT_ENTRY, f->current_offset, &o); @@ -1873,7 +1877,7 @@ _public_ int sd_journal_get_data(sd_journal *j, const char *field, const void ** return -ENOENT; } -static int return_data(JournalFile *f, Object *o, const void **data, size_t *size) { +static int return_data(sd_journal *j, JournalFile *f, Object *o, const void **data, size_t *size) { size_t t; uint64_t l; @@ -1888,7 +1892,7 @@ static int return_data(JournalFile *f, Object *o, const void **data, size_t *siz #ifdef HAVE_XZ uint64_t rsize; - if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize)) + if (!uncompress_blob(o->data.payload, l, &f->compress_buffer, &f->compress_buffer_size, &rsize, j->data_threshold)) return -EBADMSG; *data = f->compress_buffer; @@ -1942,7 +1946,7 @@ _public_ int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t if (le_hash != o->data.hash) return -EBADMSG; - r = return_data(f, o, data, size); + r = return_data(j, f, o, data, size); if (r < 0) return r; @@ -2339,7 +2343,7 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ if (o->object.type != OBJECT_DATA) return -EBADMSG; - r = return_data(j->unique_file, o, &odata, &ol); + r = return_data(j, j->unique_file, o, &odata, &ol); if (r < 0) return r; @@ -2371,7 +2375,7 @@ _public_ int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_ if (found) continue; - r = return_data(j->unique_file, o, data, l); + r = return_data(j, j->unique_file, o, data, l); if (r < 0) return r; @@ -2456,3 +2460,21 @@ _public_ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **ret) { return catalog_get(id, ret); } + +_public_ int sd_journal_set_data_threshold(sd_journal *j, size_t sz) { + if (!j) + return -EINVAL; + + j->data_threshold = sz; + return 0; +} + +_public_ int sd_journal_get_data_threshold(sd_journal *j, size_t *sz) { + if (!j) + return -EINVAL; + if (!sz) + return -EINVAL; + + *sz = j->data_threshold; + return 0; +} diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index cb93761bd1..ca5ad43b63 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -91,7 +91,7 @@ static bool shall_print(const char *p, size_t l, OutputFlags flags) { if (flags & OUTPUT_SHOW_ALL) return true; - if (l > PRINT_THRESHOLD) + if (l >= PRINT_THRESHOLD) return false; if (!utf8_is_printable_n(p, l)) @@ -119,6 +119,8 @@ static int output_short( assert(f); assert(j); + sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : PRINT_THRESHOLD); + SD_JOURNAL_FOREACH_DATA(j, data, length) { r = parse_field(data, length, "PRIORITY=", &priority, &priority_len); @@ -308,6 +310,8 @@ static int output_verbose( assert(f); assert(j); + sd_journal_set_data_threshold(j, 0); + r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) { log_error("Failed to get realtime timestamp: %s", strerror(-r)); @@ -368,6 +372,8 @@ static int output_export( assert(j); + sd_journal_set_data_threshold(j, 0); + r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) { log_error("Failed to get realtime timestamp: %s", strerror(-r)); @@ -441,7 +447,7 @@ void json_escape( assert(f); assert(p); - if (!(flags & OUTPUT_SHOW_ALL) && l > JSON_THRESHOLD) + if (!(flags & OUTPUT_SHOW_ALL) && l >= JSON_THRESHOLD) fputs("null", f); @@ -502,6 +508,8 @@ static int output_json( assert(j); + sd_journal_set_data_threshold(j, flags & OUTPUT_SHOW_ALL ? 0 : JSON_THRESHOLD); + r = sd_journal_get_realtime_usec(j, &realtime); if (r < 0) { log_error("Failed to get realtime timestamp: %s", strerror(-r)); @@ -714,6 +722,8 @@ static int output_cat( assert(j); assert(f); + sd_journal_set_data_threshold(j, 0); + r = sd_journal_get_data(j, "MESSAGE", &data, &l); if (r < 0) { /* An entry without MESSAGE=? */ diff --git a/src/systemd/sd-journal.h b/src/systemd/sd-journal.h index fd9c0f5620..2e8d2d882f 100644 --- a/src/systemd/sd-journal.h +++ b/src/systemd/sd-journal.h @@ -97,6 +97,9 @@ int sd_journal_next_skip(sd_journal *j, uint64_t skip); int sd_journal_get_realtime_usec(sd_journal *j, uint64_t *ret); int sd_journal_get_monotonic_usec(sd_journal *j, uint64_t *ret, sd_id128_t *ret_boot_id); +int sd_journal_set_data_threshold(sd_journal *j, size_t sz); +int sd_journal_get_data_threshold(sd_journal *j, size_t *sz); + int sd_journal_get_data(sd_journal *j, const char *field, const void **data, size_t *l); int sd_journal_enumerate_data(sd_journal *j, const void **data, size_t *l); void sd_journal_restart_data(sd_journal *j); |