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
|
#ifndef JEMALLOC_INTERNAL_EMITTER_H
|
||||||
#define JEMALLOC_INTERNAL_EMITTER_H
|
#define JEMALLOC_INTERNAL_EMITTER_H
|
||||||
|
|
||||||
|
#include "jemalloc/internal/ql.h"
|
||||||
|
|
||||||
typedef enum emitter_output_e emitter_output_t;
|
typedef enum emitter_output_e emitter_output_t;
|
||||||
enum emitter_output_e {
|
enum emitter_output_e {
|
||||||
emitter_output_json,
|
emitter_output_json,
|
||||||
@ -25,8 +27,50 @@ enum emitter_type_e {
|
|||||||
emitter_type_size,
|
emitter_type_size,
|
||||||
emitter_type_ssize,
|
emitter_type_ssize,
|
||||||
emitter_type_string,
|
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;
|
typedef struct emitter_s emitter_t;
|
||||||
struct emitter_s {
|
struct emitter_s {
|
||||||
emitter_output_t output;
|
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.
|
* anywhere near the fmt size.
|
||||||
*/
|
*/
|
||||||
assert(str_written < BUF_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_gen_fmt(fmt, FMT_SIZE, "s", justify, width);
|
||||||
emitter_printf(emitter, fmt, buf);
|
emitter_printf(emitter, fmt, buf);
|
||||||
break;
|
break;
|
||||||
@ -156,6 +194,9 @@ emitter_print_value(emitter_t *emitter, emitter_justify_t justify, int width,
|
|||||||
case emitter_type_uint64:
|
case emitter_type_uint64:
|
||||||
EMIT_SIMPLE(uint64_t, FMTu64)
|
EMIT_SIMPLE(uint64_t, FMTu64)
|
||||||
break;
|
break;
|
||||||
|
case emitter_type_title:
|
||||||
|
EMIT_SIMPLE(char *const, "s");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
unreachable();
|
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 */
|
#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, "k6", "K6", emitter_type_string, &str);
|
||||||
emitter_kv(emitter, "k7", "K7", emitter_type_uint32, &u32);
|
emitter_kv(emitter, "k7", "K7", emitter_type_uint32, &u32);
|
||||||
emitter_kv(emitter, "k8", "K8", emitter_type_uint64, &u64);
|
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);
|
emitter_end(emitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,6 +343,63 @@ TEST_BEGIN(test_json_arr) {
|
|||||||
}
|
}
|
||||||
TEST_END
|
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
|
int
|
||||||
main(void) {
|
main(void) {
|
||||||
return test_no_reentrancy(
|
return test_no_reentrancy(
|
||||||
@ -347,5 +408,6 @@ main(void) {
|
|||||||
test_nested_dict,
|
test_nested_dict,
|
||||||
test_types,
|
test_types,
|
||||||
test_modal,
|
test_modal,
|
||||||
test_json_arr);
|
test_json_arr,
|
||||||
|
test_table_row);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user