[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [WIP PATCH 09/16] WIP: tools/xl: Implement generalized output formatting for `xl list`
Implement a generalized output formatting function for the `xl list` subcommands. Notably `xl list` and `xl vm-list` could make use of alternative output list formats. Signed-off-by: Elliott Mitchell <ehem+xen@xxxxxxx> --- I'm a bit unsure of #include <xen-tools/libs.h>. When looking for an implementation of ARRAY_SIZE(), that was the header I found. I can readily write it myself, but rather than inlining, I looked for a copy in a header and found that. --- tools/xl/xl_list.c | 285 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 285 insertions(+) diff --git a/tools/xl/xl_list.c b/tools/xl/xl_list.c index e30536fd9a..1c04f2126b 100644 --- a/tools/xl/xl_list.c +++ b/tools/xl/xl_list.c @@ -14,10 +14,14 @@ #define _GNU_SOURCE +#include <ctype.h> #include <inttypes.h> #include <stdlib.h> +#include <stddef.h> #include <unistd.h> +#include <xen-tools/libs.h> + #include <libxl.h> #include <libxl_utils.h> @@ -25,6 +29,287 @@ #include "xl_utils.h" +struct format_entry; + +typedef void (format_function_t)(const struct format_entry *, + const void *, const char *, size_t); + +typedef struct format_entry { + char *const header; + char formatc[3]; + format_function_t *formatf; + ptrdiff_t offset; + union { + int i; + unsigned long lu; + float f; + void *v; + char *(*xlfunc)(libxl_ctx *, uint32_t); + } extra; +} format_table_t['z' - 'A' + 1]; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + +static void format_normal(const struct format_entry *entry, + const void *info, const char *format, + size_t len) +{ + char *buf = alloca(len + 3); + memcpy(buf, format, len); + if (info) { + const char *str; + int i; + unsigned long lu; + float f; + strcpy(buf + len, entry->formatc); + switch (entry->formatc[0]) { + case 's': + str = ((char **)info)[entry->offset]; + if (!str) str = "-"; + printf(buf, str); + break; + case 'f': + f = ((float *)info)[entry->offset]; + if (entry->extra.f != 0) f /= entry->extra.f; + printf(buf, f); + break; + case 'l': + lu = ((unsigned long *)info)[entry->offset]; + if (entry->extra.lu) lu /= entry->extra.lu; + printf(buf, lu); + break; + case 'd': + default: + i = ((int *)info)[entry->offset]; + if (entry->extra.i) i /= entry->extra.i; + printf(buf, i); + break; + } + } else { + if (entry->formatc[0] == 'f') { + char *tmp; + buf[len] = '\0'; + if ((tmp = rindex(buf, '.'))) + len = tmp - buf - 1; + } + strcpy(buf + len, "s"); + printf(buf, entry->header); + } +} + +static void format_allocstr(const struct format_entry *entry, + const void *info, const char *format, + size_t len) +{ + char *fmt = alloca(len + 2); + char *outbuf; + memcpy(fmt, format, len); + strcpy(fmt + len, "s"); + + if (info) { + outbuf = entry->extra.xlfunc(ctx, ((uint32_t *)info)[entry->offset]); + printf(fmt, outbuf); + free(outbuf); + } else printf(fmt, entry->header); +} + +static void format_uuid(const struct format_entry *entry, + const void *info, const char *format, + size_t len) +{ + if (info) printf(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(*(libxl_uuid *)((char *)info + entry->offset))); + else fputs(entry->header, stdout); +} + +static void format_time(const struct format_entry *entry, + const void *_info, const char *format, + size_t len) +{ + const libxl_dominfo *info = _info; + char *fmt = alloca(len + 2); + memcpy(fmt, format, len); + + if (info) { + strcpy(fmt + len, "f"); + printf(fmt, ((float)info->cpu_time / 1e9)); + } else { + char *tmp; + if (!(tmp = index(fmt, '.'))) tmp = fmt + len; + strcpy(tmp, "s"); + printf(fmt, entry->header); + } +} + +static void format_state(const struct format_entry *entry, + const void *_info, const char *format, + size_t len) +{ + const libxl_dominfo *info = _info; + if (info) { + const char shutdown_reason_letters[] = "-rscwS"; + libxl_shutdown_reason shutdown_reason; + static const char letters[] = "rbps"; + int i; + const bool *flags; + + flags = &info->running; + for (i = 0; i < strlen(letters); ++i) + putchar(flags[i] ? letters[i] : '-'); + + shutdown_reason = info->shutdown ? info->shutdown_reason : 0; + putchar((shutdown_reason >= 0 && + shutdown_reason < sizeof(shutdown_reason_letters)-1 + ? shutdown_reason_letters[shutdown_reason] : '?')); + + putchar(info->dying ? 'd' : '-'); + } else printf("%6s", entry->header); +} + +static void format_reason(const struct format_entry *entry, + const void *_info, const char *format, + size_t len) +{ + const libxl_dominfo *info = _info; + const char *output = entry->header; + if (info) { + if (info->shutdown) { + printf("%8x", info->shutdown_reason); + return; + } + output = "-"; + } + printf("%8s", output); +} + +static void format_memory(const struct format_entry *entry, + const void *_info, const char *format, + size_t len) +{ + const libxl_dominfo *info = _info; + char *fmt = alloca(len + 3); + memcpy(fmt, format, len); + if (info) { + strcpy(fmt + len, entry->formatc); + printf(fmt, (info->current_memkb + info->outstanding_memkb) >> 10); + } else { + strcpy(fmt + len, "s"); + printf(fmt, "Mem"); + } +} + +static void format_node(const struct format_entry *entry, + const void *_info, const char *format, + size_t len) +{ + const libxl_dominfo *info = _info; + static bool need_init = true; + static libxl_bitmap nodemap; + static libxl_physinfo physinfo; + + if (need_init) { + libxl_bitmap_init(&nodemap); + libxl_physinfo_init(&physinfo); + need_init = false; + + if (libxl_node_bitmap_alloc(ctx, &nodemap, 0)) { + fprintf(stderr, "libxl_node_bitmap_alloc_failed.\n"); + exit(EXIT_FAILURE); + } + if (libxl_get_physinfo(ctx, &physinfo) != 0) { + fprintf(stderr, "libxl_physinfo failed.\n"); + libxl_bitmap_dispose(&nodemap); + exit(EXIT_FAILURE); + } + } + + if (info) { + libxl_domain_get_nodeaffinity(ctx, info->domid, &nodemap); + + putchar(' '); + print_bitmap(nodemap.map, physinfo.nr_nodes, stdout); + } else fputs(entry->header, stdout); + +#if 0 + /* unfortunately these get leaked on exit */ + libxl_bitmap_dispose(&nodemap); + libxl_physinfo_dispose(&physinfo); +#endif +} + +#pragma GCC diagnostic pop + +static bool isfmtchar(int c) +{ + const bool opts[] = { + ['0'] = true, + ['1'] = true, + ['2'] = true, + ['3'] = true, + ['4'] = true, + ['5'] = true, + ['6'] = true, + ['7'] = true, + ['8'] = true, + ['9'] = true, + ['.'] = true, + ['#'] = true, + ['-'] = true, + ['+'] = true, + [' '] = true, + ['\''] = true, + }; + if ((unsigned int)c < ARRAY_SIZE(opts) && opts[c]) return true; + else return false; +} + +static void format(const format_table_t fmttab, const char *fmt, + const void *info) +{ + while (fmt[0]) { + if (fmt[0] == '\\') { + switch (fmt[1]) { + case 0: + /* Uhm... */ + return; + case '0': + putchar(0); + break; + case 'n': + fputs("\n", stdout); + break; + case 't': + putchar('\t'); + break; + default: + putchar(fmt[1]); + } + fmt+=2; + } else if (fmt[0] == '%') { + size_t len=1; + unsigned char entryn; + + while (isfmtchar(fmt[len])) ++len; + + entryn = fmt[len] - 'A'; + if (entryn < sizeof(format_table_t) / sizeof(fmttab[0]) && + fmttab[entryn].formatf) + fmttab[entryn].formatf(fmttab + entryn, info, fmt, len); + else { + fprintf(stderr, "Invalid conversion character \'%c\'\n", + entryn); + exit(EXIT_FAILURE); + } + + fmt += len + 1; + } else { + putchar(*fmt); + ++fmt; + } + } +} + + static void list_vm(void) { libxl_vminfo *info; -- -- (\___(\___(\______ --=> 8-) EHM <=-- ______/)___/)___/) \BS ( | ehem+sigmsg@xxxxxxx PGP 87145445 | ) / \_CS\ | _____ -O #include <stddisclaimer.h> O- _____ | / _/ 8A19\___\_|_/58D2 7E3D DDF4 7BA6 <-PGP-> 41D1 B375 37D0 8714\_|_/___/5445
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |