Skip to content

Commit

Permalink
cmd/flux-kvs: handle non-JSON values in "dir" cmd
Browse files Browse the repository at this point in the history
Problem: the KVS allows non-JSON values to be stored, but
flux kvs dir -R exits with an error if it encounters one.

For each value, if it decodes as JSON, format it like before.
But if it doesn't print it directly instead of exiting.

Truncate output at 79 colummns, or at first newline if value
contains them.  Indicate truncated values by appending "...".

Fixes flux-framework#1158
  • Loading branch information
garlick committed Oct 25, 2017
1 parent f93f776 commit 3166be1
Showing 1 changed file with 68 additions and 25 deletions.
93 changes: 68 additions & 25 deletions src/cmd/flux-kvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,37 +304,73 @@ int main (int argc, char *argv[])
return (exitval);
}

static void output_key_json_object (const char *key, json_t *o)
static void kv_printf (const char *key, int maxcol, const char *fmt, ...)
{
va_list ap;
int rc;
char *val, *kv, *p;
bool overflow = false;

assert (maxcol == 0 || maxcol > 3);

va_start (ap, fmt);
rc = vasprintf (&val, fmt, ap);
va_end (ap);

if (rc < 0)
log_err_exit ("%s", __FUNCTION__);

if (asprintf (&kv, "%s%s%s", key ? key : "",
key ? " = " : "",
val) < 0)
log_err_exit ("%s", __FUNCTION__);

if (maxcol != 0) { // perform truncation
if ((p = strchr (kv, '\n'))) {
*p = '\0';
overflow = true;
}
if (strlen (kv) > maxcol - 3) {
kv[maxcol - 3] = '\0';
overflow = true;
}
}
printf ("%s%s\n", kv,
overflow ? "..." : "");

free (val);
free (kv);
}

static void output_key_json_object (const char *key, json_t *o, int maxcol)
{
char *s;
if (key)
printf ("%s = ", key);

switch (json_typeof (o)) {
case JSON_NULL:
printf ("nil\n");
kv_printf (key, maxcol, "nil");
break;
case JSON_TRUE:
printf ("true\n");
kv_printf (key, maxcol, "true");
break;
case JSON_FALSE:
printf ("false\n");
kv_printf (key, maxcol, "false");
break;
case JSON_REAL:
printf ("%f\n", json_real_value (o));
kv_printf (key, maxcol, "%f", json_real_value (o));
break;
case JSON_INTEGER:
printf ("%lld\n", (long long)json_integer_value (o));
kv_printf (key, maxcol, "%lld", (long long)json_integer_value (o));
break;
case JSON_STRING:
printf ("%s\n", json_string_value (o));
kv_printf (key, maxcol, "%s", json_string_value (o));
break;
case JSON_ARRAY:
case JSON_OBJECT:
default:
if (!(s = json_dumps (o, JSON_SORT_KEYS)))
log_msg_exit ("json_dumps failed");
printf ("%s\n", s);
kv_printf (key, maxcol, "%s", s);
free (s);
break;
}
Expand All @@ -352,7 +388,7 @@ static void output_key_json_str (const char *key,
if (!(o = json_loads (json_str, JSON_DECODE_ANY, &error)))
log_msg_exit ("%s: %s (line %d column %d)",
arg, error.text, error.line, error.column);
output_key_json_object (key, o);
output_key_json_object (key, o, 0);
json_decref (o);
}

Expand Down Expand Up @@ -802,20 +838,20 @@ int cmd_dropcache (optparse_t *p, int argc, char **argv)
return (0);
}

static void dump_kvs_val (const char *key, const char *json_str)
static void dump_kvs_val (const char *key, int maxcol, const char *value)
{
json_t *o;
json_error_t error;

if (!json_str)
json_str = "null";
if (!(o = json_loads (json_str, JSON_DECODE_ANY, &error))) {
printf ("%s: %s (line %d column %d)\n",
key, error.text, error.line, error.column);
return;
if (!value) {
kv_printf (key, maxcol, "");
}
else if ((o = json_loads (value, JSON_DECODE_ANY, NULL))) {
output_key_json_object (key, o, maxcol);
json_decref (o);
}
else {
kv_printf (key, maxcol, value);
}
output_key_json_object (key, o);
json_decref (o);
}

static void dump_kvs_dir (const flux_kvsdir_t *dir, bool Ropt, bool dopt)
Expand All @@ -826,6 +862,7 @@ static void dump_kvs_dir (const flux_kvsdir_t *dir, bool Ropt, bool dopt)
flux_kvsitr_t *itr;
const char *name;
char *key;
const int maxcol = 79;

itr = flux_kvsitr_create (dir);
while ((name = flux_kvsitr_next (itr))) {
Expand All @@ -850,11 +887,17 @@ static void dump_kvs_dir (const flux_kvsdir_t *dir, bool Ropt, bool dopt)
printf ("%s.\n", key);
} else {
if (!dopt) {
const char *json_str;
if (!(f = flux_kvs_lookupat (h, 0, key, rootref))
|| flux_kvs_lookup_get (f, &json_str) < 0)
const char *value;
const void *buf;
int len;
if (!(f = flux_kvs_lookupat (h, 0, key, rootref)))
log_err_exit ("%s", key);
if (flux_kvs_lookup_get (f, &value) == 0) // null terminated
dump_kvs_val (key, maxcol, value);
else if (flux_kvs_lookup_get_raw (f, &buf, &len) == 0)
kv_printf (key, maxcol, "%.*s", len, buf);
else
log_err_exit ("%s", key);
dump_kvs_val (key, json_str);
flux_future_destroy (f);
}
else
Expand Down

0 comments on commit 3166be1

Please sign in to comment.