Emitter: Add support for row-based output in table mode.
This is needed for things like mutex stats in table mode.
This commit is contained in:
parent
9e1846b004
commit
ebe0b5f828
@ -1,6 +1,8 @@
|
||||
#ifndef JEMALLOC_INTERNAL_EMITTER_H
|
||||
#define JEMALLOC_INTERNAL_EMITTER_H
|
||||
|
||||
#include "jemalloc/internal/ql.h"
|
||||
|
||||
typedef enum emitter_output_e emitter_output_t;
|
||||
enum emitter_output_e {
|
||||
emitter_output_json,
|
||||
@ -25,8 +27,50 @@ enum emitter_type_e {
|
||||
emitter_type_size,
|
||||
emitter_type_ssize,
|
||||
emitter_type_string,
|
||||
/*
|
||||
* A title is a column title in a table; it's just a string, but it's
|
||||
* not quoted.
|
||||
*/
|
||||
emitter_type_title,
|
||||
};
|
||||
|
||||
typedef struct emitter_col_s emitter_col_t;
|
||||
struct emitter_col_s {
|
||||
/* Filled in by the user. */
|
||||
emitter_justify_t justify;
|
||||
int width;
|
||||
emitter_type_t type;
|
||||
union {
|
||||
bool bool_val;
|
||||
int int_val;
|
||||
unsigned unsigned_val;
|
||||
uint32_t uint32_val;
|
||||
uint64_t uint64_val;
|
||||
size_t size_val;
|
||||
ssize_t ssize_val;
|
||||
const char *str_val;
|
||||
};
|
||||
|
||||
/* Filled in by initialization. */
|
||||
ql_elm(emitter_col_t) link;
|
||||
};
|
||||
|
||||
typedef struct emitter_row_s emitter_row_t;
|
||||
struct emitter_row_s {
|
||||
ql_head(emitter_col_t) cols;
|
||||
};
|
||||
|
||||
static inline void
|
||||
emitter_row_init(emitter_row_t *row) {
|
||||
ql_new(&row->cols);
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_col_init(emitter_col_t *col, emitter_row_t *row) {
|
||||
ql_elm_new(col, link);
|
||||
ql_tail_insert(&row->cols, col, link);
|
||||
}
|
||||
|
||||
typedef struct emitter_s emitter_t;
|
||||
struct emitter_s {
|
||||
emitter_output_t output;
|
||||
@ -141,12 +185,6 @@ emitter_print_value(emitter_t *emitter, emitter_justify_t justify, int width,
|
||||
* anywhere near the fmt size.
|
||||
*/
|
||||
assert(str_written < BUF_SIZE);
|
||||
|
||||
/*
|
||||
* We don't support justified quoted string primitive values for
|
||||
* now. Fortunately, we don't want to emit them.
|
||||
*/
|
||||
|
||||
emitter_gen_fmt(fmt, FMT_SIZE, "s", justify, width);
|
||||
emitter_printf(emitter, fmt, buf);
|
||||
break;
|
||||
@ -156,6 +194,9 @@ emitter_print_value(emitter_t *emitter, emitter_justify_t justify, int width,
|
||||
case emitter_type_uint64:
|
||||
EMIT_SIMPLE(uint64_t, FMTu64)
|
||||
break;
|
||||
case emitter_type_title:
|
||||
EMIT_SIMPLE(char *const, "s");
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
@ -378,4 +419,17 @@ emitter_json_arr_value(emitter_t *emitter, emitter_type_t value_type,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
emitter_table_row(emitter_t *emitter, emitter_row_t *row) {
|
||||
if (emitter->output != emitter_output_table) {
|
||||
return;
|
||||
}
|
||||
emitter_col_t *col;
|
||||
ql_foreach(col, &row->cols, link) {
|
||||
emitter_print_value(emitter, col->justify, col->width,
|
||||
col->type, (const void *)&col->bool_val);
|
||||
}
|
||||
emitter_table_printf(emitter, "\n");
|
||||
}
|
||||
|
||||
#endif /* JEMALLOC_INTERNAL_EMITTER_H */
|
||||
|
@ -217,6 +217,10 @@ emit_types(emitter_t *emitter) {
|
||||
emitter_kv(emitter, "k6", "K6", emitter_type_string, &str);
|
||||
emitter_kv(emitter, "k7", "K7", emitter_type_uint32, &u32);
|
||||
emitter_kv(emitter, "k8", "K8", emitter_type_uint64, &u64);
|
||||
/*
|
||||
* We don't test the title type, since it's only used for tables. It's
|
||||
* tested in the emitter_table_row tests.
|
||||
*/
|
||||
emitter_end(emitter);
|
||||
}
|
||||
|
||||
@ -339,6 +343,63 @@ TEST_BEGIN(test_json_arr) {
|
||||
}
|
||||
TEST_END
|
||||
|
||||
static void
|
||||
emit_table_row(emitter_t *emitter) {
|
||||
emitter_begin(emitter);
|
||||
emitter_row_t row;
|
||||
emitter_col_t abc = {emitter_justify_left, 10, emitter_type_title};
|
||||
abc.str_val = "ABC title";
|
||||
emitter_col_t def = {emitter_justify_right, 15, emitter_type_title};
|
||||
def.str_val = "DEF title";
|
||||
emitter_col_t ghi = {emitter_justify_right, 5, emitter_type_title};
|
||||
ghi.str_val = "GHI";
|
||||
|
||||
emitter_row_init(&row);
|
||||
emitter_col_init(&abc, &row);
|
||||
emitter_col_init(&def, &row);
|
||||
emitter_col_init(&ghi, &row);
|
||||
|
||||
emitter_table_row(emitter, &row);
|
||||
|
||||
abc.type = emitter_type_int;
|
||||
def.type = emitter_type_bool;
|
||||
ghi.type = emitter_type_int;
|
||||
|
||||
abc.int_val = 123;
|
||||
def.bool_val = true;
|
||||
ghi.int_val = 456;
|
||||
emitter_table_row(emitter, &row);
|
||||
|
||||
abc.int_val = 789;
|
||||
def.bool_val = false;
|
||||
ghi.int_val = 1011;
|
||||
emitter_table_row(emitter, &row);
|
||||
|
||||
abc.type = emitter_type_string;
|
||||
abc.str_val = "a string";
|
||||
def.bool_val = false;
|
||||
ghi.type = emitter_type_title;
|
||||
ghi.str_val = "ghi";
|
||||
emitter_table_row(emitter, &row);
|
||||
|
||||
emitter_end(emitter);
|
||||
}
|
||||
|
||||
static const char *table_row_json =
|
||||
"{\n"
|
||||
"}\n";
|
||||
|
||||
static const char *table_row_table =
|
||||
"ABC title DEF title GHI\n"
|
||||
"123 true 456\n"
|
||||
"789 false 1011\n"
|
||||
"\"a string\" false ghi\n";
|
||||
|
||||
TEST_BEGIN(test_table_row) {
|
||||
assert_emit_output(&emit_table_row, table_row_json, table_row_table);
|
||||
}
|
||||
TEST_END
|
||||
|
||||
int
|
||||
main(void) {
|
||||
return test_no_reentrancy(
|
||||
@ -347,5 +408,6 @@ main(void) {
|
||||
test_nested_dict,
|
||||
test_types,
|
||||
test_modal,
|
||||
test_json_arr);
|
||||
test_json_arr,
|
||||
test_table_row);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user