mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 10:13:34 +08:00
sd-journal: add an API to enumerate known field names of the journal
This adds two new calls to get the list of all journal fields names currently in use. This is the low-level support to implement the feature requested in #2176 in a more optimized way.
This commit is contained in:
parent
b72190e90f
commit
eb86030ec0
@ -72,6 +72,7 @@ MANPAGES += \
|
||||
man/sd_id128_to_string.3 \
|
||||
man/sd_is_fifo.3 \
|
||||
man/sd_journal_add_match.3 \
|
||||
man/sd_journal_enumerate_fields.3 \
|
||||
man/sd_journal_get_catalog.3 \
|
||||
man/sd_journal_get_cursor.3 \
|
||||
man/sd_journal_get_cutoff_realtime_usec.3 \
|
||||
@ -237,6 +238,7 @@ MANPAGES_ALIAS += \
|
||||
man/SD_JOURNAL_FOREACH.3 \
|
||||
man/SD_JOURNAL_FOREACH_BACKWARDS.3 \
|
||||
man/SD_JOURNAL_FOREACH_DATA.3 \
|
||||
man/SD_JOURNAL_FOREACH_FIELD.3 \
|
||||
man/SD_JOURNAL_FOREACH_UNIQUE.3 \
|
||||
man/SD_JOURNAL_INVALIDATE.3 \
|
||||
man/SD_JOURNAL_LOCAL_ONLY.3 \
|
||||
@ -397,6 +399,7 @@ MANPAGES_ALIAS += \
|
||||
man/sd_journal_process.3 \
|
||||
man/sd_journal_reliable_fd.3 \
|
||||
man/sd_journal_restart_data.3 \
|
||||
man/sd_journal_restart_fields.3 \
|
||||
man/sd_journal_restart_unique.3 \
|
||||
man/sd_journal_seek_cursor.3 \
|
||||
man/sd_journal_seek_monotonic_usec.3 \
|
||||
@ -565,6 +568,7 @@ man/SD_JOURNAL_CURRENT_USER.3: man/sd_journal_open.3
|
||||
man/SD_JOURNAL_FOREACH.3: man/sd_journal_next.3
|
||||
man/SD_JOURNAL_FOREACH_BACKWARDS.3: man/sd_journal_next.3
|
||||
man/SD_JOURNAL_FOREACH_DATA.3: man/sd_journal_get_data.3
|
||||
man/SD_JOURNAL_FOREACH_FIELD.3: man/sd_journal_enumerate_fields.3
|
||||
man/SD_JOURNAL_FOREACH_UNIQUE.3: man/sd_journal_query_unique.3
|
||||
man/SD_JOURNAL_INVALIDATE.3: man/sd_journal_get_fd.3
|
||||
man/SD_JOURNAL_LOCAL_ONLY.3: man/sd_journal_open.3
|
||||
@ -725,6 +729,7 @@ man/sd_journal_printv.3: man/sd_journal_print.3
|
||||
man/sd_journal_process.3: man/sd_journal_get_fd.3
|
||||
man/sd_journal_reliable_fd.3: man/sd_journal_get_fd.3
|
||||
man/sd_journal_restart_data.3: man/sd_journal_get_data.3
|
||||
man/sd_journal_restart_fields.3: man/sd_journal_enumerate_fields.3
|
||||
man/sd_journal_restart_unique.3: man/sd_journal_query_unique.3
|
||||
man/sd_journal_seek_cursor.3: man/sd_journal_seek_head.3
|
||||
man/sd_journal_seek_monotonic_usec.3: man/sd_journal_seek_head.3
|
||||
@ -1017,6 +1022,9 @@ man/SD_JOURNAL_FOREACH_BACKWARDS.html: man/sd_journal_next.html
|
||||
man/SD_JOURNAL_FOREACH_DATA.html: man/sd_journal_get_data.html
|
||||
$(html-alias)
|
||||
|
||||
man/SD_JOURNAL_FOREACH_FIELD.html: man/sd_journal_enumerate_fields.html
|
||||
$(html-alias)
|
||||
|
||||
man/SD_JOURNAL_FOREACH_UNIQUE.html: man/sd_journal_query_unique.html
|
||||
$(html-alias)
|
||||
|
||||
@ -1497,6 +1505,9 @@ man/sd_journal_reliable_fd.html: man/sd_journal_get_fd.html
|
||||
man/sd_journal_restart_data.html: man/sd_journal_get_data.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_restart_fields.html: man/sd_journal_enumerate_fields.html
|
||||
$(html-alias)
|
||||
|
||||
man/sd_journal_restart_unique.html: man/sd_journal_query_unique.html
|
||||
$(html-alias)
|
||||
|
||||
@ -2534,6 +2545,7 @@ EXTRA_DIST += \
|
||||
man/sd_id128_to_string.xml \
|
||||
man/sd_is_fifo.xml \
|
||||
man/sd_journal_add_match.xml \
|
||||
man/sd_journal_enumerate_fields.xml \
|
||||
man/sd_journal_get_catalog.xml \
|
||||
man/sd_journal_get_cursor.xml \
|
||||
man/sd_journal_get_cutoff_realtime_usec.xml \
|
||||
|
@ -77,6 +77,8 @@
|
||||
<citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_cutoff_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
@ -111,6 +113,8 @@
|
||||
<citerefentry><refentrytitle>sd_journal_get_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_seek_head</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_query_enumerate</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_cursor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_cutoff_realtime_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_cutoff_monotonic_usec</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
|
161
man/sd_journal_enumerate_fields.xml
Normal file
161
man/sd_journal_enumerate_fields.xml
Normal file
@ -0,0 +1,161 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<!--
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2016 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/>.
|
||||
-->
|
||||
|
||||
<refentry id="sd_journal_enumerate_fields">
|
||||
|
||||
<refentryinfo>
|
||||
<title>sd_journal_enumerate_fields</title>
|
||||
<productname>systemd</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Lennart</firstname>
|
||||
<surname>Poettering</surname>
|
||||
<email>lennart@poettering.net</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>sd_journal_enumerate_fields</refentrytitle>
|
||||
<manvolnum>3</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>sd_journal_enumerate_fields</refname>
|
||||
<refname>sd_journal_restart_fields</refname>
|
||||
<refname>SD_JOURNAL_FOREACH_FIELD</refname>
|
||||
<refpurpose>Read used field names from the journal</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<funcsynopsis>
|
||||
<funcsynopsisinfo>#include <systemd/sd-journal.h></funcsynopsisinfo>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_journal_enumerate_fields</function></funcdef>
|
||||
<paramdef>sd_journal *<parameter>j</parameter></paramdef>
|
||||
<paramdef>const char **<parameter>field</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>void <function>sd_journal_restart_fields</function></funcdef>
|
||||
<paramdef>sd_journal *<parameter>j</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef><function>SD_JOURNAL_FOREACH_FIELD</function></funcdef>
|
||||
<paramdef>sd_journal *<parameter>j</parameter></paramdef>
|
||||
<paramdef>const char *<parameter>field</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><function>sd_journal_enumerate_fields()</function> may be used to iterate through all field names used in the
|
||||
opened journal files. On each invocation the next field name is returned. The order of the returned field names is
|
||||
not defined. It takes two arguments: the journal context object, plus a pointer to a constant string pointer where
|
||||
the field name is stored in. The returned data is in a read-only memory map and is only valid until the next
|
||||
invocation of <function>sd_journal_enumerate_fields()</function>. 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_fields()</function> resets the field name enumeration index to the beginning of
|
||||
the list. The next invocation of <function>sd_journal_enumerate_fields()</function> will return the first field
|
||||
name again.</para>
|
||||
|
||||
<para>The <function>SD_JOURNAL_FOREACH_FIELD()</function> macro may be used as a handy wrapper around
|
||||
<function>sd_journal_restart_fields()</function> and <function>sd_journal_enumerate_fields()</function>.</para>
|
||||
|
||||
<para>These functions currently are not influenced by matches set with <function>sd_journal_add_match()</function>
|
||||
but this might change in a later version of this software.</para>
|
||||
|
||||
<para>To retrieve the possible values a specific field can take use
|
||||
<citerefentry><refentrytitle>sd_journal_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Return Value</title>
|
||||
|
||||
<para><function>sd_journal_enumerate_fields()</function> returns a
|
||||
positive integer if the next field name has been read, 0 when no
|
||||
more field names are known, or a negative errno-style error code.
|
||||
<function>sd_journal_restart_fields()</function> returns
|
||||
nothing.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Notes</title>
|
||||
|
||||
<para>The <function>sd_journal_enumerate_fields()</function> and <function>sd_journal_restart_fields()</function>
|
||||
interfaces are available as a shared library, which can be compiled and linked to with the
|
||||
<constant>libsystemd</constant> <citerefentry
|
||||
project='die-net'><refentrytitle>pkg-config</refentrytitle><manvolnum>1</manvolnum></citerefentry> file.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
|
||||
<para>Use the <function>SD_JOURNAL_FOREACH_FIELD</function> macro to iterate through all field names in use in the
|
||||
current journal.</para>
|
||||
|
||||
<programlisting>#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <systemd/sd-journal.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sd_journal *j;
|
||||
const char *field;
|
||||
int r;
|
||||
|
||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
SD_JOURNAL_FOREACH_FIELD(j, field)
|
||||
printf("%s\n", field);
|
||||
sd_journal_close(j);
|
||||
return 0;
|
||||
}</programlisting>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See Also</title>
|
||||
|
||||
<para>
|
||||
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</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_query_unique</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_data</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
@ -128,6 +128,11 @@
|
||||
<para>Note that these functions currently are not influenced by
|
||||
matches set with <function>sd_journal_add_match()</function> but
|
||||
this might change in a later version of this software.</para>
|
||||
|
||||
<para>To enumerate all field names currently in use (and thus all suitable field parameters for
|
||||
<function>sd_journal_query_unique()</function>), use the
|
||||
<citerefentry><refentrytitle>sd_journal_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
call.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -167,25 +172,25 @@
|
||||
#include <systemd/sd-journal.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
sd_journal *j;
|
||||
const void *d;
|
||||
size_t l;
|
||||
int r;
|
||||
sd_journal *j;
|
||||
const void *d;
|
||||
size_t l;
|
||||
int r;
|
||||
|
||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
r = sd_journal_query_unique(j, "_SYSTEMD_UNIT");
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to query journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
SD_JOURNAL_FOREACH_UNIQUE(j, d, l)
|
||||
printf("%.*s\n", (int) l, (const char*) d);
|
||||
sd_journal_close(j);
|
||||
return 0;
|
||||
r = sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY);
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to open journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
r = sd_journal_query_unique(j, "_SYSTEMD_UNIT");
|
||||
if (r < 0) {
|
||||
fprintf(stderr, "Failed to query journal: %s\n", strerror(-r));
|
||||
return 1;
|
||||
}
|
||||
SD_JOURNAL_FOREACH_UNIQUE(j, d, l)
|
||||
printf("%.*s\n", (int) l, (const char*) d);
|
||||
sd_journal_close(j);
|
||||
return 0;
|
||||
}</programlisting>
|
||||
|
||||
</refsect1>
|
||||
@ -198,6 +203,7 @@ int main(int argc, char *argv[]) {
|
||||
<citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</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_enumerate_fields</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_get_data</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>sd_journal_add_match</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
|
@ -103,18 +103,27 @@ struct sd_journal {
|
||||
unsigned current_invalidate_counter, last_invalidate_counter;
|
||||
usec_t last_process_usec;
|
||||
|
||||
/* Iterating through unique fields and their data values */
|
||||
char *unique_field;
|
||||
JournalFile *unique_file;
|
||||
uint64_t unique_offset;
|
||||
|
||||
/* Iterating through known fields */
|
||||
JournalFile *fields_file;
|
||||
uint64_t fields_offset;
|
||||
uint64_t fields_hash_table_index;
|
||||
char *fields_buffer;
|
||||
size_t fields_buffer_allocated;
|
||||
|
||||
int flags;
|
||||
|
||||
bool on_network;
|
||||
bool no_new_files;
|
||||
bool unique_file_lost; /* File we were iterating over got
|
||||
removed, and there were no more
|
||||
files, so sd_j_enumerate_unique
|
||||
will return a value equal to 0. */
|
||||
bool on_network:1;
|
||||
bool no_new_files:1;
|
||||
bool unique_file_lost:1; /* File we were iterating over got
|
||||
removed, and there were no more
|
||||
files, so sd_j_enumerate_unique
|
||||
will return a value equal to 0. */
|
||||
bool fields_file_lost:1;
|
||||
bool has_runtime_files:1;
|
||||
bool has_persistent_files:1;
|
||||
|
||||
|
@ -1338,6 +1338,13 @@ static void remove_file_real(sd_journal *j, JournalFile *f) {
|
||||
j->unique_file_lost = true;
|
||||
}
|
||||
|
||||
if (j->fields_file == f) {
|
||||
j->fields_file = ordered_hashmap_next(j->files, j->fields_file->path);
|
||||
j->fields_offset = 0;
|
||||
if (!j->fields_file)
|
||||
j->fields_file_lost = true;
|
||||
}
|
||||
|
||||
journal_file_close(f);
|
||||
|
||||
j->current_invalidate_counter ++;
|
||||
@ -1806,6 +1813,7 @@ _public_ void sd_journal_close(sd_journal *j) {
|
||||
free(j->path);
|
||||
free(j->prefix);
|
||||
free(j->unique_field);
|
||||
free(j->fields_buffer);
|
||||
free(j);
|
||||
}
|
||||
|
||||
@ -2552,6 +2560,154 @@ _public_ void sd_journal_restart_unique(sd_journal *j) {
|
||||
j->unique_file_lost = false;
|
||||
}
|
||||
|
||||
_public_ int sd_journal_enumerate_fields(sd_journal *j, const char **field) {
|
||||
int r;
|
||||
|
||||
assert_return(j, -EINVAL);
|
||||
assert_return(!journal_pid_changed(j), -ECHILD);
|
||||
assert_return(field, -EINVAL);
|
||||
|
||||
if (!j->fields_file) {
|
||||
if (j->fields_file_lost)
|
||||
return 0;
|
||||
|
||||
j->fields_file = ordered_hashmap_first(j->files);
|
||||
if (!j->fields_file)
|
||||
return 0;
|
||||
|
||||
j->fields_hash_table_index = 0;
|
||||
j->fields_offset = 0;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
JournalFile *f, *of;
|
||||
Iterator i;
|
||||
uint64_t m;
|
||||
Object *o;
|
||||
size_t sz;
|
||||
bool found;
|
||||
|
||||
f = j->fields_file;
|
||||
|
||||
if (j->fields_offset == 0) {
|
||||
bool eof = false;
|
||||
|
||||
/* We are not yet positioned at any field. Let's pick the first one */
|
||||
r = journal_file_map_field_hash_table(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
m = le64toh(f->header->field_hash_table_size) / sizeof(HashItem);
|
||||
for (;;) {
|
||||
if (j->fields_hash_table_index >= m) {
|
||||
/* Reached the end of the hash table, go to the next file. */
|
||||
eof = true;
|
||||
break;
|
||||
}
|
||||
|
||||
j->fields_offset = le64toh(f->field_hash_table[j->fields_hash_table_index].head_hash_offset);
|
||||
|
||||
if (j->fields_offset != 0)
|
||||
break;
|
||||
|
||||
/* Empty hash table bucket, go to next one */
|
||||
j->fields_hash_table_index++;
|
||||
}
|
||||
|
||||
if (eof) {
|
||||
/* Proceed with next file */
|
||||
j->fields_file = ordered_hashmap_next(j->files, f->path);
|
||||
if (!j->fields_file) {
|
||||
*field = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
j->fields_offset = 0;
|
||||
j->fields_hash_table_index = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* We are already positioned at a field. If so, let's figure out the next field from it */
|
||||
|
||||
r = journal_file_move_to_object(f, OBJECT_FIELD, j->fields_offset, &o);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
j->fields_offset = le64toh(o->field.next_hash_offset);
|
||||
if (j->fields_offset == 0) {
|
||||
/* Reached the end of the hash table chain */
|
||||
j->fields_hash_table_index++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* We use OBJECT_UNUSED here, so that the iteator below doesn't remove our mmap window */
|
||||
r = journal_file_move_to_object(f, OBJECT_UNUSED, j->fields_offset, &o);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Because we used OBJECT_UNUSED above, we need to do our type check manually */
|
||||
if (o->object.type != OBJECT_FIELD) {
|
||||
log_debug("%s:offset " OFSfmt ": object has type %i, expected %i", f->path, j->fields_offset, o->object.type, OBJECT_FIELD);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
sz = le64toh(o->object.size) - offsetof(Object, field.payload);
|
||||
|
||||
/* Let's see if we already returned this field name before. */
|
||||
found = false;
|
||||
ORDERED_HASHMAP_FOREACH(of, j->files, i) {
|
||||
if (of == f)
|
||||
break;
|
||||
|
||||
/* Skip this file it didn't have any fields indexed */
|
||||
if (JOURNAL_HEADER_CONTAINS(of->header, n_fields) && le64toh(of->header->n_fields) <= 0)
|
||||
continue;
|
||||
|
||||
r = journal_file_find_field_object_with_hash(of, o->field.payload, sz, le64toh(o->field.hash), NULL, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/* Check if this is really a valid string containing no NUL byte */
|
||||
if (memchr(o->field.payload, 0, sz))
|
||||
return -EBADMSG;
|
||||
|
||||
if (sz > j->data_threshold)
|
||||
sz = j->data_threshold;
|
||||
|
||||
if (!GREEDY_REALLOC(j->fields_buffer, j->fields_buffer_allocated, sz + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(j->fields_buffer, o->field.payload, sz);
|
||||
j->fields_buffer[sz] = 0;
|
||||
|
||||
if (!field_is_valid(j->fields_buffer))
|
||||
return -EBADMSG;
|
||||
|
||||
*field = j->fields_buffer;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
_public_ void sd_journal_restart_fields(sd_journal *j) {
|
||||
if (!j)
|
||||
return;
|
||||
|
||||
j->fields_file = NULL;
|
||||
j->fields_hash_table_index = 0;
|
||||
j->fields_offset = 0;
|
||||
j->fields_file_lost = false;
|
||||
}
|
||||
|
||||
_public_ int sd_journal_reliable_fd(sd_journal *j) {
|
||||
assert_return(j, -EINVAL);
|
||||
assert_return(!journal_pid_changed(j), -ECHILD);
|
||||
|
@ -481,3 +481,9 @@ global:
|
||||
sd_bus_path_encode_many;
|
||||
sd_listen_fds_with_names;
|
||||
} LIBSYSTEMD_226;
|
||||
|
||||
LIBSYSTEMD_229 {
|
||||
global:
|
||||
sd_journal_enumerate_fields;
|
||||
sd_journal_restart_fields;
|
||||
} LIBSYSTEMD_227;
|
||||
|
@ -129,6 +129,9 @@ int sd_journal_query_unique(sd_journal *j, const char *field);
|
||||
int sd_journal_enumerate_unique(sd_journal *j, const void **data, size_t *l);
|
||||
void sd_journal_restart_unique(sd_journal *j);
|
||||
|
||||
int sd_journal_enumerate_fields(sd_journal *j, const char **field);
|
||||
void sd_journal_restart_fields(sd_journal *j);
|
||||
|
||||
int sd_journal_get_fd(sd_journal *j);
|
||||
int sd_journal_get_events(sd_journal *j);
|
||||
int sd_journal_get_timeout(sd_journal *j, uint64_t *timeout_usec);
|
||||
@ -142,22 +145,28 @@ int sd_journal_get_catalog_for_message_id(sd_id128_t id, char **text);
|
||||
int sd_journal_has_runtime_files(sd_journal *j);
|
||||
int sd_journal_has_persistent_files(sd_journal *j);
|
||||
|
||||
/* the inverse condition avoids ambiguity of danling 'else' after the macro */
|
||||
/* The inverse condition avoids ambiguity of dangling 'else' after the macro */
|
||||
#define SD_JOURNAL_FOREACH(j) \
|
||||
if (sd_journal_seek_head(j) < 0) { } \
|
||||
else while (sd_journal_next(j) > 0)
|
||||
|
||||
/* the inverse condition avoids ambiguity of danling 'else' after the macro */
|
||||
/* The inverse condition avoids ambiguity of dangling 'else' after the macro */
|
||||
#define SD_JOURNAL_FOREACH_BACKWARDS(j) \
|
||||
if (sd_journal_seek_tail(j) < 0) { } \
|
||||
else while (sd_journal_previous(j) > 0)
|
||||
|
||||
/* Iterate through the data fields of the current journal entry */
|
||||
#define SD_JOURNAL_FOREACH_DATA(j, data, l) \
|
||||
for (sd_journal_restart_data(j); sd_journal_enumerate_data((j), &(data), &(l)) > 0; )
|
||||
|
||||
/* Iterate through the all known values of a specific field */
|
||||
#define SD_JOURNAL_FOREACH_UNIQUE(j, data, l) \
|
||||
for (sd_journal_restart_unique(j); sd_journal_enumerate_unique((j), &(data), &(l)) > 0; )
|
||||
|
||||
/* Iterate through all known field names */
|
||||
#define SD_JOURNAL_FOREACH_FIELD(j, field) \
|
||||
for (sd_journal_restart_fields(j); sd_journal_enumerate_fields((j), &(field)) > 0; )
|
||||
|
||||
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_journal, sd_journal_close);
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
Loading…
Reference in New Issue
Block a user