journal: make the compression threshold tunable

Allow a user to set a number of bytes as Compress to use as the compression
threshold.
This commit is contained in:
Alex Gartrell 2018-02-27 09:37:23 -08:00
parent 57850536d5
commit 1b7cf0e587
6 changed files with 135 additions and 10 deletions

View file

@ -107,10 +107,13 @@
<varlistentry> <varlistentry>
<term><varname>Compress=</varname></term> <term><varname>Compress=</varname></term>
<listitem><para>Takes a boolean value. If enabled (the <listitem><para>Can take a boolean value. If enabled (the
default), data objects that shall be stored in the journal and default), data objects that shall be stored in the journal
are larger than a certain threshold are compressed before they and are larger than the default threshold of 512 bytes are
are written to the file system.</para></listitem> compressed before they are written to the file system. It
can also be set to a number of bytes to specify the
compression threshold directly. Suffixes like K, M, and G
can be used to specify larger units.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>

View file

@ -19,7 +19,7 @@ struct ConfigPerfItem;
%includes %includes
%% %%
Journal.Storage, config_parse_storage, 0, offsetof(Server, storage) Journal.Storage, config_parse_storage, 0, offsetof(Server, storage)
Journal.Compress, config_parse_bool, 0, offsetof(Server, compress) Journal.Compress, config_parse_compress, 0, offsetof(Server, compress)
Journal.Seal, config_parse_bool, 0, offsetof(Server, seal) Journal.Seal, config_parse_bool, 0, offsetof(Server, seal)
Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg) Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg)
Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec) Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec)

View file

@ -280,9 +280,12 @@ static int open_journal(
assert(ret); assert(ret);
if (reliably) if (reliably)
r = journal_file_open_reliably(fname, flags, 0640, s->compress, (uint64_t) -1, seal, metrics, s->mmap, s->deferred_closes, NULL, &f); r = journal_file_open_reliably(fname, flags, 0640, s->compress.enabled, s->compress.threshold_bytes,
seal, metrics, s->mmap, s->deferred_closes, NULL, &f);
else else
r = journal_file_open(-1, fname, flags, 0640, s->compress, (uint64_t) -1, seal, metrics, s->mmap, s->deferred_closes, NULL, &f); r = journal_file_open(-1, fname, flags, 0640, s->compress.enabled, s->compress.threshold_bytes, seal,
metrics, s->mmap, s->deferred_closes, NULL, &f);
if (r < 0) if (r < 0)
return r; return r;
@ -463,7 +466,7 @@ static int do_rotate(
if (!*f) if (!*f)
return -EINVAL; return -EINVAL;
r = journal_file_rotate(f, s->compress, (uint64_t) -1, seal, s->deferred_closes); r = journal_file_rotate(f, s->compress.enabled, s->compress.threshold_bytes, seal, s->deferred_closes);
if (r < 0) { if (r < 0) {
if (*f) if (*f)
return log_error_errno(r, "Failed to rotate %s: %m", (*f)->path); return log_error_errno(r, "Failed to rotate %s: %m", (*f)->path);
@ -1695,7 +1698,8 @@ int server_init(Server *s) {
zero(*s); zero(*s);
s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1; s->syslog_fd = s->native_fd = s->stdout_fd = s->dev_kmsg_fd = s->audit_fd = s->hostname_fd = s->notify_fd = -1;
s->compress = true; s->compress.enabled = true;
s->compress.threshold_bytes = (uint64_t) -1;
s->seal = true; s->seal = true;
s->read_kmsg = true; s->read_kmsg = true;
@ -2038,3 +2042,37 @@ int config_parse_line_max(
return 0; return 0;
} }
int config_parse_compress(const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
JournalCompressOptions* compress = data;
int r;
if (streq(rvalue, "1")) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Compress= ambiguously specified as 1, enabling compression with default threshold");
compress->enabled = true;
} else if (streq(rvalue, "0")) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"Compress= ambiguously specified as 0, disabling compression");
compress->enabled = false;
} else if ((r = parse_boolean(rvalue)) >= 0)
compress->enabled = r;
else if (parse_size(rvalue, 1024, &compress->threshold_bytes) == 0)
compress->enabled = true;
else if (isempty(rvalue)) {
compress->enabled = true;
compress->threshold_bytes = (uint64_t) -1;
} else
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse Compress= value, ignoring: %s", rvalue);
return 0;
}

View file

@ -52,6 +52,11 @@ typedef enum SplitMode {
_SPLIT_INVALID = -1 _SPLIT_INVALID = -1
} SplitMode; } SplitMode;
typedef struct JournalCompressOptions {
bool enabled;
uint64_t threshold_bytes;
} JournalCompressOptions;
typedef struct JournalStorageSpace { typedef struct JournalStorageSpace {
usec_t timestamp; usec_t timestamp;
@ -113,7 +118,7 @@ struct Server {
JournalStorage runtime_storage; JournalStorage runtime_storage;
JournalStorage system_storage; JournalStorage system_storage;
bool compress; JournalCompressOptions compress;
bool seal; bool seal;
bool read_kmsg; bool read_kmsg;
@ -205,6 +210,7 @@ const struct ConfigPerfItem* journald_gperf_lookup(const char *key, GPERF_LEN_TY
int config_parse_storage(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_storage(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_line_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); int config_parse_line_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_compress(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
const char *storage_to_string(Storage s) _const_; const char *storage_to_string(Storage s) _const_;
Storage storage_from_string(const char *s) _pure_; Storage storage_from_string(const char *s) _pure_;

View file

@ -0,0 +1,71 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
Copyright 2011 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <stdbool.h>
#include "journald-server.h"
#define _COMPRESS_PARSE_CHECK(str, enab, thresh, varname) \
do { \
JournalCompressOptions varname = {true, 111}; \
config_parse_compress("", "", 0, "", 0, "", 0, str, \
&varname, NULL); \
assert_se((enab) == varname.enabled); \
if (varname.enabled) \
assert_se((thresh) == varname.threshold_bytes); \
} while (0)
#define COMPRESS_PARSE_CHECK(str, enabled, threshold) \
_COMPRESS_PARSE_CHECK(str, enabled, threshold, conf##__COUNTER__)
static void test_config_compress(void) {
COMPRESS_PARSE_CHECK("yes", true, 111);
COMPRESS_PARSE_CHECK("no", false, 111);
COMPRESS_PARSE_CHECK("y", true, 111);
COMPRESS_PARSE_CHECK("n", false, 111);
COMPRESS_PARSE_CHECK("true", true, 111);
COMPRESS_PARSE_CHECK("false", false, 111);
COMPRESS_PARSE_CHECK("t", true, 111);
COMPRESS_PARSE_CHECK("f", false, 111);
COMPRESS_PARSE_CHECK("on", true, 111);
COMPRESS_PARSE_CHECK("off", false, 111);
/* Weird size/bool overlapping case. We preserve backward compatibility instead of assuming these are byte
* counts. */
COMPRESS_PARSE_CHECK("1", true, 111);
COMPRESS_PARSE_CHECK("0", false, 111);
/* IEC sizing */
COMPRESS_PARSE_CHECK("1B", true, 1);
COMPRESS_PARSE_CHECK("1K", true, 1024);
COMPRESS_PARSE_CHECK("1M", true, 1024 * 1024);
COMPRESS_PARSE_CHECK("1G", true, 1024 * 1024 * 1024);
/* Invalid Case */
COMPRESS_PARSE_CHECK("-1", true, 111);
COMPRESS_PARSE_CHECK("blah blah", true, 111);
COMPRESS_PARSE_CHECK("", true, (uint64_t)-1);
}
int main(int argc, char *argv[]) {
test_config_compress();
return 0;
}

View file

@ -725,6 +725,13 @@ tests += [
libxz, libxz,
liblz4]], liblz4]],
[['src/journal/test-journal-config.c'],
[libjournal_core,
libshared],
[libxz,
liblz4,
libselinux]],
[['src/journal/test-journal-verify.c'], [['src/journal/test-journal-verify.c'],
[libjournal_core, [libjournal_core,
libshared], libshared],