mirror of
https://github.com/netdata/netdata.git
synced 2025-04-26 13:54:48 +00:00
Remove netdatacli response size limitation (#14906)
* Dump config * Add charcat and rawcat * Build incoming response in an buffer * Allocate a buffer to hold the command response so that we dont have a 4K char limit * Add a dumpconfig command to output the current netdata.conf * Remove -W dumpconfig for now * Fix typo * Improve help message
This commit is contained in:
parent
0d2c327ae5
commit
1fa6037330
4 changed files with 77 additions and 40 deletions
49
cli/cli.c
49
cli/cli.c
|
@ -10,9 +10,6 @@ static uv_shutdown_t shutdown_req;
|
|||
static char command_string[MAX_COMMAND_LENGTH];
|
||||
static unsigned command_string_size;
|
||||
|
||||
static char response_string[MAX_COMMAND_LENGTH];
|
||||
static unsigned response_string_size;
|
||||
|
||||
static int exit_status;
|
||||
|
||||
struct command_context {
|
||||
|
@ -24,8 +21,10 @@ struct command_context {
|
|||
cmd_status_t status;
|
||||
};
|
||||
|
||||
static void parse_command_reply(void)
|
||||
static void parse_command_reply(BUFFER *buf)
|
||||
{
|
||||
char *response_string = (char *) buffer_tostring(buf);
|
||||
unsigned response_string_size = buffer_strlen(buf);
|
||||
FILE *stream = NULL;
|
||||
char *pos;
|
||||
int syntax_error = 0;
|
||||
|
@ -64,28 +63,21 @@ static void parse_command_reply(void)
|
|||
|
||||
static void pipe_read_cb(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf)
|
||||
{
|
||||
if (0 == nread) {
|
||||
BUFFER *response = client->data;
|
||||
|
||||
if (0 == nread)
|
||||
fprintf(stderr, "%s: Zero bytes read by command pipe.\n", __func__);
|
||||
} else if (UV_EOF == nread) {
|
||||
// fprintf(stderr, "EOF found in command pipe.\n");
|
||||
parse_command_reply();
|
||||
} else if (nread < 0) {
|
||||
fprintf(stderr, "%s: %s\n", __func__, uv_strerror(nread));
|
||||
else if (UV_EOF == nread)
|
||||
parse_command_reply(response);
|
||||
else if (nread < 0) {
|
||||
fprintf(stderr, "%s: %s\n", __func__, uv_strerror(nread));
|
||||
(void)uv_read_stop((uv_stream_t *)client);
|
||||
}
|
||||
else
|
||||
buffer_fast_rawcat(response, buf->base, nread);
|
||||
|
||||
if (nread < 0) { /* stop stream due to EOF or error */
|
||||
(void)uv_read_stop((uv_stream_t *)client);
|
||||
} else if (nread) {
|
||||
size_t to_copy;
|
||||
|
||||
to_copy = MIN((unsigned int) nread, MAX_COMMAND_LENGTH - 1 - response_string_size);
|
||||
memcpy(response_string + response_string_size, buf->base, to_copy);
|
||||
response_string_size += to_copy;
|
||||
response_string[response_string_size] = '\0';
|
||||
}
|
||||
if (buf && buf->len) {
|
||||
if (buf && buf->len)
|
||||
free(buf->base);
|
||||
}
|
||||
}
|
||||
|
||||
static void alloc_cb(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
|
||||
|
@ -104,8 +96,7 @@ static void shutdown_cb(uv_shutdown_t* req, int status)
|
|||
(void)status;
|
||||
|
||||
/* receive reply */
|
||||
response_string_size = 0;
|
||||
response_string[0] = '\0';
|
||||
client_pipe.data = req->data;
|
||||
|
||||
ret = uv_read_start((uv_stream_t *)&client_pipe, alloc_cb, pipe_read_cb);
|
||||
if (ret) {
|
||||
|
@ -113,16 +104,17 @@ static void shutdown_cb(uv_shutdown_t* req, int status)
|
|||
uv_close((uv_handle_t *)&client_pipe, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void pipe_write_cb(uv_write_t* req, int status)
|
||||
{
|
||||
int ret;
|
||||
|
||||
(void)req;
|
||||
(void)status;
|
||||
|
||||
uv_pipe_t *clientp = req->data;
|
||||
shutdown_req.data = clientp->data;
|
||||
|
||||
ret = uv_shutdown(&shutdown_req, (uv_stream_t *)&client_pipe, shutdown_cb);
|
||||
if (ret) {
|
||||
fprintf(stderr, "uv_shutdown(): %s\n", uv_strerror(ret));
|
||||
|
@ -144,10 +136,11 @@ static void connect_cb(uv_connect_t* req, int status)
|
|||
exit(-1);
|
||||
}
|
||||
if (0 == command_string_size) {
|
||||
s = fgets(command_string, MAX_COMMAND_LENGTH, stdin);
|
||||
s = fgets(command_string, MAX_COMMAND_LENGTH - 1, stdin);
|
||||
}
|
||||
(void)s; /* We don't need input to communicate with the server */
|
||||
command_string_size = strlen(command_string);
|
||||
client_pipe.data = req->data;
|
||||
|
||||
write_req.data = &client_pipe;
|
||||
write_buf.base = command_string;
|
||||
|
@ -191,11 +184,13 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
req.data = buffer_create(128, NULL);
|
||||
uv_pipe_connect(&req, &client_pipe, PIPENAME, connect_cb);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
|
||||
uv_close((uv_handle_t *)&client_pipe, NULL);
|
||||
buffer_free(client_pipe.data);
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ static cmd_status_t cmd_write_config_execute(char *args, char **message);
|
|||
static cmd_status_t cmd_ping_execute(char *args, char **message);
|
||||
static cmd_status_t cmd_aclk_state(char *args, char **message);
|
||||
static cmd_status_t cmd_version(char *args, char **message);
|
||||
static cmd_status_t cmd_dumpconfig(char *args, char **message);
|
||||
|
||||
static command_info_t command_info_array[] = {
|
||||
{"help", cmd_help_execute, CMD_TYPE_HIGH_PRIORITY}, // show help menu
|
||||
|
@ -61,7 +62,8 @@ static command_info_t command_info_array[] = {
|
|||
{"write-config", cmd_write_config_execute, CMD_TYPE_ORTHOGONAL},
|
||||
{"ping", cmd_ping_execute, CMD_TYPE_ORTHOGONAL},
|
||||
{"aclk-state", cmd_aclk_state, CMD_TYPE_ORTHOGONAL},
|
||||
{"version", cmd_version, CMD_TYPE_ORTHOGONAL}
|
||||
{"version", cmd_version, CMD_TYPE_ORTHOGONAL},
|
||||
{"dumpconfig", cmd_dumpconfig, CMD_TYPE_ORTHOGONAL}
|
||||
};
|
||||
|
||||
/* Mutexes for commands of type CMD_TYPE_ORTHOGONAL */
|
||||
|
@ -127,6 +129,8 @@ static cmd_status_t cmd_help_execute(char *args, char **message)
|
|||
" Return with 'pong' if agent is alive.\n"
|
||||
"aclk-state [json]\n"
|
||||
" Returns current state of ACLK and Cloud connection. (optionally in json).\n"
|
||||
"dumpconfig\n"
|
||||
" Returns the current netdata.conf on stdout.\n"
|
||||
"version\n"
|
||||
" Returns the netdata version.\n",
|
||||
MAX_COMMAND_LENGTH - 1);
|
||||
|
@ -330,6 +334,17 @@ static cmd_status_t cmd_version(char *args, char **message)
|
|||
return CMD_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cmd_status_t cmd_dumpconfig(char *args, char **message)
|
||||
{
|
||||
(void)args;
|
||||
|
||||
BUFFER *wb = buffer_create(1024, NULL);
|
||||
config_generate(wb, 0);
|
||||
*message = strdupz(buffer_tostring(wb));
|
||||
buffer_free(wb);
|
||||
return CMD_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void cmd_lock_exclusive(unsigned index)
|
||||
{
|
||||
(void)index;
|
||||
|
@ -393,32 +408,30 @@ static void pipe_write_cb(uv_write_t* req, int status)
|
|||
|
||||
uv_close((uv_handle_t *)client, pipe_close_cb);
|
||||
--clients;
|
||||
freez(client->data);
|
||||
buffer_free(client->data);
|
||||
info("Command Clients = %u\n", clients);
|
||||
}
|
||||
|
||||
static inline void add_char_to_command_reply(char *reply_string, unsigned *reply_string_size, char character)
|
||||
static inline void add_char_to_command_reply(BUFFER *reply_string, unsigned *reply_string_size, char character)
|
||||
{
|
||||
reply_string[(*reply_string_size)++] = character;
|
||||
buffer_fast_charcat(reply_string, character);
|
||||
*reply_string_size +=1;
|
||||
}
|
||||
|
||||
static inline void add_string_to_command_reply(char *reply_string, unsigned *reply_string_size, char *str)
|
||||
static inline void add_string_to_command_reply(BUFFER *reply_string, unsigned *reply_string_size, char *str)
|
||||
{
|
||||
unsigned len;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
if (MAX_COMMAND_LENGTH - 1 < len + *reply_string_size)
|
||||
len = MAX_COMMAND_LENGTH - *reply_string_size - 1;
|
||||
|
||||
strncpyz(reply_string + *reply_string_size, str, len);
|
||||
buffer_fast_strcat(reply_string, str, len);
|
||||
*reply_string_size += len;
|
||||
}
|
||||
|
||||
static void send_command_reply(struct command_context *cmd_ctx, cmd_status_t status, char *message)
|
||||
{
|
||||
int ret;
|
||||
char *reply_string = mallocz(MAX_COMMAND_LENGTH);
|
||||
BUFFER *reply_string = buffer_create(128, NULL);
|
||||
|
||||
char exit_status_string[MAX_EXIT_STATUS_LENGTH + 1] = {'\0', };
|
||||
unsigned reply_string_size = 0;
|
||||
uv_buf_t write_buf;
|
||||
|
@ -436,13 +449,12 @@ static void send_command_reply(struct command_context *cmd_ctx, cmd_status_t sta
|
|||
|
||||
cmd_ctx->write_req.data = client;
|
||||
client->data = reply_string;
|
||||
write_buf.base = reply_string;
|
||||
write_buf.base = reply_string->buffer;
|
||||
write_buf.len = reply_string_size;
|
||||
ret = uv_write(&cmd_ctx->write_req, (uv_stream_t *)client, &write_buf, 1, pipe_write_cb);
|
||||
if (ret) {
|
||||
error("uv_write(): %s", uv_strerror(ret));
|
||||
}
|
||||
info("COMMAND: Sending reply: \"%s\"", reply_string);
|
||||
}
|
||||
|
||||
cmd_status_t execute_command(cmd_t idx, char *args, char **message)
|
||||
|
|
|
@ -26,6 +26,7 @@ typedef enum cmd {
|
|||
CMD_PING,
|
||||
CMD_ACLK_STATE,
|
||||
CMD_VERSION,
|
||||
CMD_DUMPCONFIG,
|
||||
CMD_TOTAL_COMMANDS
|
||||
} cmd_t;
|
||||
|
||||
|
|
|
@ -152,6 +152,35 @@ static inline void _buffer_json_depth_pop(BUFFER *wb) {
|
|||
wb->json.depth--;
|
||||
}
|
||||
|
||||
static inline void buffer_fast_charcat(BUFFER *wb, const char c) {
|
||||
|
||||
buffer_need_bytes(wb, 2);
|
||||
*(&wb->buffer[wb->len]) = c;
|
||||
wb->len += 1;
|
||||
wb->buffer[wb->len] = '\0';
|
||||
|
||||
buffer_overflow_check(wb);
|
||||
}
|
||||
|
||||
static inline void buffer_fast_rawcat(BUFFER *wb, const char *txt, size_t len) {
|
||||
if(unlikely(!txt || !*txt || !len)) return;
|
||||
|
||||
buffer_need_bytes(wb, len + 1);
|
||||
|
||||
const char *t = txt;
|
||||
const char *e = &txt[len];
|
||||
|
||||
char *d = &wb->buffer[wb->len];
|
||||
|
||||
while(t != e)
|
||||
*d++ = *t++;
|
||||
|
||||
wb->len += len;
|
||||
wb->buffer[wb->len] = '\0';
|
||||
|
||||
buffer_overflow_check(wb);
|
||||
}
|
||||
|
||||
static inline void buffer_fast_strcat(BUFFER *wb, const char *txt, size_t len) {
|
||||
if(unlikely(!txt || !*txt || !len)) return;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue