[systemd-commits] 2 commits - TODO man/journalctl.xml src/journal src/shared
Lennart Poettering
lennart at kemper.freedesktop.org
Wed Oct 24 18:00:39 PDT 2012
TODO | 5 -
man/journalctl.xml | 5 +
src/journal/test-journal-send.c | 10 ++
src/shared/hashmap.c | 40 +++++++++-
src/shared/hashmap.h | 2
src/shared/logs-show.c | 155 +++++++++++++++++++++++++++++++++++-----
6 files changed, 194 insertions(+), 23 deletions(-)
New commits:
commit a73d88fa024b5668ed7dde681e99547d41e6a864
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Oct 25 01:20:18 2012 +0200
update TODO
diff --git a/TODO b/TODO
index 4f32c52..d12308e 100644
--- a/TODO
+++ b/TODO
@@ -19,6 +19,8 @@ F18:
Features:
+* link up selected blog stories from man pages?
+
* journactl: support negative filtering, i.e. FOOBAR!="waldo"
* drop header/footer from systemctl --failed output if there are no entries shown, print nice message instead, and hook that into ExecStartPre of rescue.service/emergency.service
@@ -475,13 +477,12 @@ Features:
- remote access
- how to pass throw-away units to systemd, or dynamically change properties of existing units
- how to integrate cgconfig and suchlike with systemd
- - resource control in systemd
- testing with Harald's awesome test kit
- auto-restart
- - journalctl advanced usage
- how to make use of the journal submission APIs
- same for journal browsing
- the journal HTTP iface
+ - non-cgroup resource management
* allow port=0 in .socket units
commit d99ae53a7327e1520ea4b9a3408c2d7f938c4b37
Author: Lennart Poettering <lennart at poettering.net>
Date: Thu Oct 25 01:19:24 2012 +0200
journal: properly serialize fields with multiple values into JSON
This now matches the JSON serialization spec from:
http://www.freedesktop.org/wiki/Software/systemd/json
diff --git a/man/journalctl.xml b/man/journalctl.xml
index 9bc0153..026bb22 100644
--- a/man/journalctl.xml
+++ b/man/journalctl.xml
@@ -212,7 +212,10 @@
information). <literal>json</literal>
formats entries as JSON data
structures, one per
- line. <literal>json-pretty</literal>
+ line (see <ulink
+ url="http://www.freedesktop.org/wiki/Software/systemd/json">Journal
+ JSON Format</ulink> for more
+ information). <literal>json-pretty</literal>
also formats entries as JSON data
structures, but formats them in
multiple lines in order to make them
diff --git a/src/journal/test-journal-send.c b/src/journal/test-journal-send.c
index 168c843..9bf42f9 100644
--- a/src/journal/test-journal-send.c
+++ b/src/journal/test-journal-send.c
@@ -47,5 +47,15 @@ int main(int argc, char *argv[]) {
huge,
NULL);
+ sd_journal_send("MESSAGE=uiui",
+ "VALUE=A",
+ "VALUE=B",
+ "VALUE=C",
+ "SINGLETON=1",
+ "OTHERVALUE=X",
+ "OTHERVALUE=Y",
+ "WITH_BINARY=this is a binary value \a",
+ NULL);
+
return 0;
}
diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c
index 26a4eff..ef78070 100644
--- a/src/shared/hashmap.c
+++ b/src/shared/hashmap.c
@@ -328,7 +328,8 @@ int hashmap_put(Hashmap *h, const void *key, void *value) {
hash = h->hash_func(key) % NBUCKETS;
- if ((e = hash_scan(h, hash, key))) {
+ e = hash_scan(h, hash, key);
+ if (e) {
if (e->value == value)
return 0;
@@ -359,8 +360,8 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) {
assert(h);
hash = h->hash_func(key) % NBUCKETS;
-
- if ((e = hash_scan(h, hash, key))) {
+ e = hash_scan(h, hash, key);
+ if (e) {
e->key = key;
e->value = value;
return 0;
@@ -369,6 +370,21 @@ int hashmap_replace(Hashmap *h, const void *key, void *value) {
return hashmap_put(h, key, value);
}
+int hashmap_update(Hashmap *h, const void *key, void *value) {
+ struct hashmap_entry *e;
+ unsigned hash;
+
+ assert(h);
+
+ hash = h->hash_func(key) % NBUCKETS;
+ e = hash_scan(h, hash, key);
+ if (!e)
+ return -ENOENT;
+
+ e->value = value;
+ return 0;
+}
+
void* hashmap_get(Hashmap *h, const void *key) {
unsigned hash;
struct hashmap_entry *e;
@@ -384,6 +400,24 @@ void* hashmap_get(Hashmap *h, const void *key) {
return e->value;
}
+void* hashmap_get2(Hashmap *h, const void *key, void **key2) {
+ unsigned hash;
+ struct hashmap_entry *e;
+
+ if (!h)
+ return NULL;
+
+ hash = h->hash_func(key) % NBUCKETS;
+ e = hash_scan(h, hash, key);
+ if (!e)
+ return NULL;
+
+ if (key2)
+ *key2 = (void*) e->key;
+
+ return e->value;
+}
+
bool hashmap_contains(Hashmap *h, const void *key) {
unsigned hash;
diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h
index ed41817..55dea0a 100644
--- a/src/shared/hashmap.h
+++ b/src/shared/hashmap.h
@@ -51,8 +51,10 @@ Hashmap *hashmap_copy(Hashmap *h);
int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func);
int hashmap_put(Hashmap *h, const void *key, void *value);
+int hashmap_update(Hashmap *h, const void *key, void *value);
int hashmap_replace(Hashmap *h, const void *key, void *value);
void* hashmap_get(Hashmap *h, const void *key);
+void* hashmap_get2(Hashmap *h, const void *key, void **rkey);
bool hashmap_contains(Hashmap *h, const void *key);
void* hashmap_remove(Hashmap *h, const void *key);
void* hashmap_remove_value(Hashmap *h, const void *key, void *value);
diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c
index 63a48e4..36cce73 100644
--- a/src/shared/logs-show.c
+++ b/src/shared/logs-show.c
@@ -29,6 +29,7 @@
#include "log.h"
#include "util.h"
#include "utf8.h"
+#include "hashmap.h"
#define PRINT_THRESHOLD 128
#define JSON_THRESHOLD 4096
@@ -464,12 +465,14 @@ static int output_json(
OutputFlags flags) {
uint64_t realtime, monotonic;
- char *cursor;
+ char *cursor, *k;
const void *data;
size_t length;
sd_id128_t boot_id;
char sid[33];
int r;
+ Hashmap *h = NULL;
+ bool done, separator;
assert(j);
@@ -518,31 +521,141 @@ static int output_json(
}
free(cursor);
+ h = hashmap_new(string_hash_func, string_compare_func);
+ if (!h)
+ return -ENOMEM;
+
+ /* First round, iterate through the entry and count how often each field appears */
SD_JOURNAL_FOREACH_DATA(j, data, length) {
- const char *c;
+ const char *eq;
+ char *n;
+ unsigned u;
- /* We already printed the boot id, from the data in
- * the header, hence let's suppress it here */
if (length >= 9 &&
memcmp(data, "_BOOT_ID=", 9) == 0)
continue;
- c = memchr(data, '=', length);
- if (!c) {
- log_error("Invalid field.");
- return -EINVAL;
- }
+ eq = memchr(data, '=', length);
+ if (!eq)
+ continue;
- if (mode == OUTPUT_JSON_PRETTY)
- fputs(",\n\t", f);
- else
- fputs(", ", f);
+ n = strndup(data, eq - (const char*) data);
+ if (!n) {
+ r = -ENOMEM;
+ goto finish;
+ }
- json_escape(f, data, c - (const char*) data, flags);
- fputs(" : ", f);
- json_escape(f, c + 1, length - (c - (const char*) data) - 1, flags);
+ u = PTR_TO_UINT(hashmap_get(h, n));
+ if (u == 0) {
+ r = hashmap_put(h, n, UINT_TO_PTR(1));
+ if (r < 0) {
+ free(n);
+ goto finish;
+ }
+ } else {
+ r = hashmap_update(h, n, UINT_TO_PTR(u + 1));
+ free(n);
+ if (r < 0)
+ goto finish;
+ }
}
+ separator = true;
+ do {
+ done = true;
+
+ SD_JOURNAL_FOREACH_DATA(j, data, length) {
+ const char *eq;
+ char *kk, *n;
+ size_t m;
+ unsigned u;
+
+ /* We already printed the boot id, from the data in
+ * the header, hence let's suppress it here */
+ if (length >= 9 &&
+ memcmp(data, "_BOOT_ID=", 9) == 0)
+ continue;
+
+ eq = memchr(data, '=', length);
+ if (!eq)
+ continue;
+
+ if (separator) {
+ if (mode == OUTPUT_JSON_PRETTY)
+ fputs(",\n\t", f);
+ else
+ fputs(", ", f);
+ }
+
+ m = eq - (const char*) data;
+
+ n = strndup(data, m);
+ if (!n) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ u = PTR_TO_UINT(hashmap_get2(h, n, (void**) &kk));
+ if (u == 0) {
+ /* We already printed this, let's jump to the next */
+ free(n);
+ separator = false;
+
+ continue;
+ } else if (u == 1) {
+ /* Field only appears once, output it directly */
+
+ json_escape(f, data, m, flags);
+ fputs(" : ", f);
+
+ json_escape(f, eq + 1, length - m - 1, flags);
+
+ hashmap_remove(h, n);
+ free(kk);
+ free(n);
+
+ separator = true;
+
+ continue;
+
+ } else {
+ /* Field appears multiple times, output it as array */
+ json_escape(f, data, m, flags);
+ fputs(" : [ ", f);
+ json_escape(f, eq + 1, length - m - 1, flags);
+
+ /* Iterate through the end of the list */
+
+ while (sd_journal_enumerate_data(j, &data, &length) > 0) {
+ if (length < m + 1)
+ continue;
+
+ if (memcmp(data, n, m) != 0)
+ continue;
+
+ if (((const char*) data)[m] != '=')
+ continue;
+
+ fputs(", ", f);
+ json_escape(f, (const char*) data + m + 1, length - m - 1, flags);
+ }
+
+ fputs(" ]", f);
+
+ hashmap_remove(h, n);
+ free(kk);
+ free(n);
+
+ /* Iterate data fields form the beginning */
+ done = false;
+ separator = true;
+
+ break;
+ }
+ }
+
+ } while (!done);
+
if (mode == OUTPUT_JSON_PRETTY)
fputs("\n}\n", f);
else if (mode == OUTPUT_JSON_SSE)
@@ -550,7 +663,15 @@ static int output_json(
else
fputs(" }\n", f);
- return 0;
+ r = 0;
+
+finish:
+ while ((k = hashmap_steal_first_key(h)))
+ free(k);
+
+ hashmap_free(h);
+
+ return r;
}
static int output_cat(
More information about the systemd-commits
mailing list