odyssey/sources/console.c

1037 lines
29 KiB
C
Raw Normal View History

/*
2018-03-12 14:03:15 +00:00
* Odyssey.
*
2018-04-04 13:19:58 +00:00
* Scalable PostgreSQL connection pooler.
*/
#include <stdlib.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <inttypes.h>
#include <assert.h>
#include <machinarium.h>
#include <kiwi.h>
#include <odyssey.h>
enum
{
OD_LKILL_CLIENT,
OD_LSHOW,
OD_LSTATS,
2017-08-17 15:38:28 +00:00
OD_LSERVERS,
OD_LCLIENTS,
OD_LLISTS,
2018-12-21 10:08:53 +00:00
OD_LSET,
OD_LPOOLS,
OD_LDATABASES
};
static od_keyword_t
od_console_keywords[] =
{
od_keyword("kill_client", OD_LKILL_CLIENT),
od_keyword("show", OD_LSHOW),
od_keyword("stats", OD_LSTATS),
od_keyword("servers", OD_LSERVERS),
od_keyword("clients", OD_LCLIENTS),
od_keyword("lists", OD_LLISTS),
od_keyword("set", OD_LSET),
2018-12-21 10:08:53 +00:00
od_keyword("pools", OD_LPOOLS),
od_keyword("databases", OD_LDATABASES),
{ 0, 0, 0 }
};
static inline int
od_console_show_stats_add(machine_msg_t *stream,
char *database,
int database_len,
2018-08-02 13:38:36 +00:00
od_stat_t *total,
od_stat_t *avg)
{
int offset;
machine_msg_t *msg;
msg = kiwi_be_write_data_row(stream, &offset);
if (msg == NULL)
return -1;
int rc;
rc = kiwi_be_write_data_row_add(stream, offset, database, database_len);
if (rc == -1)
return -1;
char data[64];
int data_len;
/* total_xact_count */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, total->count_tx);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* total_query_count */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, total->count_query);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* total_received */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, total->recv_client);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* total_sent */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, total->recv_server);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* total_xact_time */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, total->tx_time);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* total_query_time */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, total->query_time);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-04 15:10:49 +00:00
if (rc == -1)
return -1;
/* total_wait_time */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* avg_xact_count */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, avg->count_tx);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* avg_query_count */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, avg->count_query);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-04 15:10:49 +00:00
if (rc == -1)
return -1;
/* avg_recv */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, avg->recv_client);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-04 15:10:49 +00:00
if (rc == -1)
return -1;
/* avg_sent */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, avg->recv_server);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-04 15:10:49 +00:00
if (rc == -1)
return -1;
/* avg_xact_time */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, avg->tx_time);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* avg_query_time */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, avg->query_time);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* avg_wait_time */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
return 0;
}
static int
od_console_show_stats_cb(char *database,
int database_len,
od_stat_t *total,
od_stat_t *avg, void **argv)
{
machine_msg_t *stream = argv[0];
return od_console_show_stats_add(stream, database, database_len,
total, avg);
}
static inline int
od_console_show_stats(od_client_t *client, machine_msg_t *stream)
{
2018-03-13 13:17:27 +00:00
od_router_t *router = client->global->router;
od_cron_t *cron = client->global->cron;
machine_msg_t *msg;
msg = kiwi_be_write_row_descriptionf(stream,
"sllllllllllllll",
"database",
"total_xact_count",
"total_query_count",
"total_received",
"total_sent",
"total_xact_time",
"total_query_time",
"total_wait_time",
"avg_xact_count",
"avg_query_count",
"avg_recv",
"avg_sent",
"avg_xact_time",
"avg_query_time",
"avg_wait_time");
if (msg == NULL)
return -1;
void *argv[] = { stream };
od_route_pool_stat_database(&router->route_pool,
od_console_show_stats_cb,
cron->stat_time_us,
argv);
msg = kiwi_be_write_complete(stream, "SHOW", 5);
if (msg == NULL)
return -1;
return 0;
}
2018-12-21 10:08:53 +00:00
static inline int
od_console_show_pools_add_cb(od_route_t *route, void **argv)
{
int offset;
machine_msg_t *stream = argv[0];
2018-12-21 10:08:53 +00:00
machine_msg_t *msg;
msg = kiwi_be_write_data_row(stream, &offset);
2018-12-21 10:08:53 +00:00
if (msg == NULL)
return -1;
od_route_lock(route);
int rc;
rc = kiwi_be_write_data_row_add(stream, offset, route->id.database,
route->id.database_len - 1);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
rc = kiwi_be_write_data_row_add(stream, offset, route->id.user,
route->id.user_len - 1);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
char data[64];
int data_len;
/* cl_active */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, route->client_pool.count_active);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* cl_waiting */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, route->client_pool.count_pending);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* sv_active */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, route->server_pool.count_active);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* sv_idle */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, route->server_pool.count_idle);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* sv_used */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* sv_tested */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* sv_login */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* maxwait */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* maxwait_us */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
/* pool_mode */
rc = -1;
if (route->rule->pool == OD_RULE_POOL_SESSION)
rc = kiwi_be_write_data_row_add(stream, offset, "session", 7);
2018-12-21 10:08:53 +00:00
if (route->rule->pool == OD_RULE_POOL_TRANSACTION)
rc = kiwi_be_write_data_row_add(stream, offset, "transaction", 11);
2018-12-21 10:08:53 +00:00
if (rc == -1)
goto error;
od_route_unlock(route);
return 0;
error:
od_route_unlock(route);
return -1;
}
static inline int
od_console_show_databases_add_cb(od_route_t *route, void **argv)
{
int offset;
machine_msg_t *stream = argv[0];
machine_msg_t *msg;
msg = kiwi_be_write_data_row(stream, &offset);
if (msg == NULL)
return -1;
od_route_lock(route);
int rc;
rc = kiwi_be_write_data_row_add(stream, offset, route->id.database,
route->id.database_len - 1);
if (rc == -1)
goto error;
od_rule_t *rule = route->rule;
od_rule_storage_t *storage = rule->storage;
char *host = storage->host;
if (!host)
host = "";
rc = kiwi_be_write_data_row_add(stream, offset, host,
strlen(host));
if (rc == -1)
goto error;
char data[64];
int data_len;
/* port */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, storage->port);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
goto error;
/* database */
rc = kiwi_be_write_data_row_add(stream, offset, rule->db_name,
rule->db_name_len);
if (rc == -1)
goto error;
/* force_user */
rc = kiwi_be_write_data_row_add(stream, offset, "", 0);
if (rc == -1)
goto error;
/* pool_size */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, rule->pool_size);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
goto error;
/* reserve_pool */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
goto error;
/* pool_mode */
rc = -1;
if (rule->pool == OD_RULE_POOL_SESSION)
rc = kiwi_be_write_data_row_add(stream, offset, "session", 7);
if (rule->pool == OD_RULE_POOL_TRANSACTION)
rc = kiwi_be_write_data_row_add(stream, offset, "transaction", 11);
if (rc == -1)
goto error;
/* max_connections */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, rule->client_max);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
goto error;
/* current_connections */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, route->client_pool.count_active
+ route->client_pool.count_pending
+ route->client_pool.count_queue);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
goto error;
/* paused */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
goto error;
/* disabled */
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
goto error;
od_route_unlock(route);
return 0;
error:
od_route_unlock(route);
return -1;
}
static inline int
od_console_show_databases(od_client_t *client, machine_msg_t *stream)
{
od_router_t *router = client->global->router;
machine_msg_t *msg;
msg = kiwi_be_write_row_descriptionf(stream,
"sslssllsllll",
"name",
"host",
"port",
"database",
"force_user",
"pool_size",
"reserve_pool",
"pool_mode",
"max_connections",
"current_connections",
"paused",
"disabled");
if (msg == NULL)
return -1;
void *argv[] = { stream };
int rc;
rc = od_router_foreach(router, od_console_show_databases_add_cb, argv);
if (rc == -1)
return -1;
msg = kiwi_be_write_complete(stream, "SHOW", 5);
if (msg == NULL)
return -1;
return 0;
}
2018-12-21 10:08:53 +00:00
static inline int
od_console_show_pools(od_client_t *client, machine_msg_t *stream)
2018-12-21 10:08:53 +00:00
{
od_router_t *router = client->global->router;
machine_msg_t *msg;
msg = kiwi_be_write_row_descriptionf(stream,
"ssllllllllls",
2018-12-21 10:08:53 +00:00
"database",
"user",
"cl_active",
"cl_waiting",
"sv_active",
"sv_idle",
"sv_used",
"sv_tested",
"sv_login",
"maxwait",
"maxwait_us",
"pool_mode");
if (msg == NULL)
return -1;
void *argv[] = { stream };
int rc;
2018-12-21 10:08:53 +00:00
rc = od_router_foreach(router, od_console_show_pools_add_cb, argv);
if (rc == -1)
return -1;
msg = kiwi_be_write_complete(stream, "SHOW", 5);
2018-12-21 10:08:53 +00:00
if (msg == NULL)
return -1;
2018-12-21 10:08:53 +00:00
return 0;
}
2017-08-17 15:16:16 +00:00
static inline int
od_console_show_servers_server_cb(od_server_t *server, void **argv)
2017-08-17 15:16:16 +00:00
{
od_route_t *route = server->route;
int offset;
machine_msg_t *stream = argv[0];
machine_msg_t *msg;
msg = kiwi_be_write_data_row(stream, &offset);
if (msg == NULL)
return -1;
/* type */
2017-08-17 15:16:16 +00:00
char data[64];
int data_len;
data_len = od_snprintf(data, sizeof(data), "S");
2017-08-17 15:16:16 +00:00
int rc;
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* user */
rc = kiwi_be_write_data_row_add(stream, offset,
route->id.user,
route->id.user_len - 1);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* database */
rc = kiwi_be_write_data_row_add(stream, offset,
route->id.database,
route->id.database_len - 1);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* state */
char *state = "";
if (server->state == OD_SERVER_IDLE)
2017-08-17 15:16:16 +00:00
state = "idle";
else
if (server->state == OD_SERVER_ACTIVE)
2017-08-17 15:16:16 +00:00
state = "active";
rc = kiwi_be_write_data_row_add(stream, offset, state, strlen(state));
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* addr */
od_getpeername(server->io.io, data, sizeof(data), 1, 0);
2017-08-17 15:16:16 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* port */
od_getpeername(server->io.io, data, sizeof(data), 0, 1);
2017-08-17 15:16:16 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* local_addr */
od_getsockname(server->io.io, data, sizeof(data), 1, 0);
2017-08-17 15:16:16 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* local_port */
od_getsockname(server->io.io, data, sizeof(data), 0, 1);
2017-08-17 15:16:16 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* connect_time */
rc = kiwi_be_write_data_row_add(msg, offset, NULL, -1);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* request_time */
rc = kiwi_be_write_data_row_add(msg, offset, NULL, -1);
if (rc == -1)
return -1;
/* wait */
data_len = od_snprintf(data, sizeof(data), "0");
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* wait_us */
data_len = od_snprintf(data, sizeof(data), "0");
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* ptr */
data_len = od_snprintf(data, sizeof(data), "%s%.*s",
server->id.id_prefix,
(signed)sizeof(server->id.id), server->id.id);
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* link */
data_len = od_snprintf(data, sizeof(data), "%s", "");
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* remote_pid */
data_len = od_snprintf(data, sizeof(data), "0");
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
2017-08-17 15:16:16 +00:00
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
/* tls */
data_len = od_snprintf(data, sizeof(data), "%s", "");
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
if (rc == -1)
return -1;
2017-08-17 15:16:16 +00:00
return 0;
}
static inline int
od_console_show_servers_cb(od_route_t *route, void **argv)
{
od_route_lock(route);
od_server_pool_foreach(&route->server_pool,
OD_SERVER_ACTIVE,
od_console_show_servers_server_cb,
argv);
od_server_pool_foreach(&route->server_pool,
OD_SERVER_IDLE,
od_console_show_servers_server_cb,
argv);
od_route_unlock(route);
return 0;
}
static inline int
od_console_show_servers(od_client_t *client, machine_msg_t *stream)
{
2018-03-13 13:17:27 +00:00
od_router_t *router = client->global->router;
machine_msg_t *msg;
msg = kiwi_be_write_row_descriptionf(stream,
"sssssdsdssddssds",
"type",
"user",
"database",
"state",
"addr",
"port",
"local_addr",
"local_port",
"connect_time",
"request_time",
"wait",
"wait_us",
"ptr",
"link",
"remote_pid",
"tls");
if (msg == NULL)
return -1;
2017-08-17 15:38:28 +00:00
void *argv[] = { stream };
2018-12-07 12:28:32 +00:00
od_router_foreach(router, od_console_show_servers_cb, argv);
2017-08-17 15:38:28 +00:00
msg = kiwi_be_write_complete(stream, "SHOW", 5);
if (msg == NULL)
2017-08-17 15:38:28 +00:00
return -1;
2017-08-17 15:38:28 +00:00
return 0;
}
static inline int
od_console_show_clients_callback(od_client_t *client, void **argv)
2017-08-17 15:38:28 +00:00
{
int offset;
machine_msg_t *stream = argv[0];
machine_msg_t *msg;
msg = kiwi_be_write_data_row(stream, &offset);
if (msg == NULL)
return -1;
2017-08-17 15:38:28 +00:00
char data[64];
int data_len;
/* type */
data_len = od_snprintf(data, sizeof(data), "C");
2017-08-17 15:38:28 +00:00
int rc;
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* user */
rc = kiwi_be_write_data_row_add(stream, offset, client->startup.user.value,
client->startup.user.value_len - 1);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* database */
rc = kiwi_be_write_data_row_add(stream, offset, client->startup.database.value,
client->startup.database.value_len - 1);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* state */
char *state = "";
if (client->state == OD_CLIENT_ACTIVE)
2017-08-17 15:38:28 +00:00
state = "active";
else
if (client->state == OD_CLIENT_PENDING)
2017-08-17 15:38:28 +00:00
state = "pending";
else
if (client->state == OD_CLIENT_QUEUE)
2017-08-17 15:38:28 +00:00
state = "queue";
rc = kiwi_be_write_data_row_add(stream, offset, state, strlen(state));
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* addr */
od_getpeername(client->io.io, data, sizeof(data), 1, 0);
2017-08-17 15:38:28 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* port */
od_getpeername(client->io.io, data, sizeof(data), 0, 1);
2017-08-17 15:38:28 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* local_addr */
od_getsockname(client->io.io, data, sizeof(data), 1, 0);
2017-08-17 15:38:28 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* local_port */
od_getsockname(client->io.io, data, sizeof(data), 0, 1);
2017-08-17 15:38:28 +00:00
data_len = strlen(data);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* connect_time */
rc = kiwi_be_write_data_row_add(stream, offset, NULL, -1);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* request_time */
rc = kiwi_be_write_data_row_add(stream, offset, NULL, -1);
if (rc == -1)
return -1;
/* wait */
data_len = od_snprintf(data, sizeof(data), "0");
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
/* wait_us */
data_len = od_snprintf(data, sizeof(data), "0");
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* ptr */
data_len = od_snprintf(data, sizeof(data), "%s%.*s",
client->id.id_prefix,
(signed)sizeof(client->id.id), client->id.id);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* link */
data_len = od_snprintf(data, sizeof(data), "%s", "");
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* remote_pid */
data_len = od_snprintf(data, sizeof(data), "0");
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
2017-08-17 15:38:28 +00:00
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
/* tls */
data_len = od_snprintf(data, sizeof(data), "%s", "");
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
2017-08-17 15:38:28 +00:00
return 0;
}
static inline int
od_console_show_clients_cb(od_route_t *route, void **argv)
{
od_route_lock(route);
od_client_pool_foreach(&route->client_pool,
OD_CLIENT_ACTIVE,
od_console_show_clients_callback,
argv);
od_client_pool_foreach(&route->client_pool,
OD_CLIENT_PENDING,
od_console_show_clients_callback,
argv);
od_client_pool_foreach(&route->client_pool,
OD_CLIENT_QUEUE,
od_console_show_clients_callback,
argv);
od_route_unlock(route);
return 0;
}
static inline int
od_console_show_clients(od_client_t *client, machine_msg_t *stream)
2017-08-17 15:38:28 +00:00
{
2018-03-13 13:17:27 +00:00
od_router_t *router = client->global->router;
machine_msg_t *msg;
msg = kiwi_be_write_row_descriptionf(stream,
"sssssdsdssddssds",
"type",
"user",
"database",
"state",
"addr",
"port",
"local_addr",
"local_port",
"connect_time",
"request_time",
"wait",
"wait_us",
"ptr",
"link",
"remote_pid",
"tls");
if (msg == NULL)
2017-08-17 15:38:28 +00:00
return -1;
2017-08-17 15:16:16 +00:00
void *argv[] = { stream };
od_router_foreach(router, od_console_show_clients_cb, argv);
msg = kiwi_be_write_complete(stream, "SHOW", 5);
if (msg == NULL)
return -1;
return 0;
}
static inline int
od_console_show_lists_add(machine_msg_t *stream, char *list, int items)
{
int offset;
machine_msg_t *msg;
msg = kiwi_be_write_data_row(stream, &offset);
if (msg == NULL)
return -1;
/* list */
int rc;
rc = kiwi_be_write_data_row_add(stream, offset, list, strlen(list));
if (rc == -1)
return -1;
/* items */
char data[64];
int data_len;
data_len = od_snprintf(data, sizeof(data), "%d", items);
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
if (rc == -1)
return -1;
return 0;
}
static inline int
od_console_show_lists_cb(od_route_t *route, void **argv)
{
od_route_lock(route);
int *used_servers = argv[0];
(*used_servers) += route->server_pool.count_active;
(*used_servers) += route->server_pool.count_idle;
od_route_unlock(route);
return 0;
}
static inline int
od_console_show_lists(od_client_t *client, machine_msg_t *stream)
{
2018-03-13 13:17:27 +00:00
od_router_t *router = client->global->router;
/* Gather router information.
router_used_servers can be inconsistent here, since it depends on
separate route locks.
*/
od_router_lock(router);
int router_used_servers = 0;
int router_pools = router->route_pool.count;
int router_clients = od_atomic_u32_of(&router->clients);
void *argv[] = { &router_used_servers };
od_route_pool_foreach(&router->route_pool, od_console_show_lists_cb, argv);
od_router_unlock(router);
machine_msg_t *msg;
msg = kiwi_be_write_row_descriptionf(stream, "sd", "list", "items");
if (msg == NULL)
return -1;
int rc;
/* databases */
rc = od_console_show_lists_add(stream, "databases", 0);
if (rc == -1)
return -1;
/* users */
rc = od_console_show_lists_add(stream, "users", 0);
if (rc == -1)
return -1;
/* pools */
rc = od_console_show_lists_add(stream, "pools", router_pools);
if (rc == -1)
return -1;
/* free_clients */
rc = od_console_show_lists_add(stream, "free_clients", 0);
if (rc == -1)
return -1;
/* used_clients */
rc = od_console_show_lists_add(stream, "used_clients", router_clients);
if (rc == -1)
return -1;
/* login_clients */
rc = od_console_show_lists_add(stream, "login_clients", 0);
if (rc == -1)
return -1;
/* free_servers */
rc = od_console_show_lists_add(stream, "free_servers", 0);
if (rc == -1)
return -1;
/* used_servers */
rc = od_console_show_lists_add(stream, "used_servers", router_used_servers);
if (rc == -1)
return -1;
/* dns_names */
rc = od_console_show_lists_add(stream, "dns_names", 0);
if (rc == -1)
return -1;
/* dns_zones */
rc = od_console_show_lists_add(stream, "dns_zones", 0);
if (rc == -1)
return -1;
/* dns_queries */
rc = od_console_show_lists_add(stream, "dns_queries", 0);
if (rc == -1)
return -1;
/* dns_pending */
rc = od_console_show_lists_add(stream, "dns_pending", 0);
if (rc == -1)
return -1;
msg = kiwi_be_write_complete(stream, "SHOW", 5);
if (msg == NULL)
return -1;
return 0;
}
static inline int
od_console_show(od_client_t *client, machine_msg_t *stream, od_parser_t *parser)
{
od_token_t token;
int rc;
rc = od_parser_next(parser, &token);
switch (rc) {
case OD_PARSER_KEYWORD:
break;
case OD_PARSER_EOF:
default:
return -1;
}
od_keyword_t *keyword;
keyword = od_keyword_match(od_console_keywords, &token);
if (keyword == NULL)
return -1;
switch (keyword->id) {
case OD_LSTATS:
return od_console_show_stats(client, stream);
case OD_LPOOLS:
return od_console_show_pools(client, stream);
case OD_LDATABASES:
return od_console_show_databases(client, stream);
case OD_LSERVERS:
return od_console_show_servers(client, stream);
2017-08-17 15:38:28 +00:00
case OD_LCLIENTS:
return od_console_show_clients(client, stream);
case OD_LLISTS:
return od_console_show_lists(client, stream);
}
return -1;
}
static inline int
od_console_kill_client(od_client_t *client, machine_msg_t *stream, od_parser_t *parser)
{
(void)stream;
od_token_t token;
int rc;
rc = od_parser_next(parser, &token);
if (rc != OD_PARSER_KEYWORD)
return -1;
od_id_t id;
if (token.value.string.size != (sizeof(id.id) + 1))
return -1;
memcpy(id.id, token.value.string.pointer + 1, sizeof(id.id));
od_router_kill(client->global->router, &id);
return 0;
}
static inline int
od_console_set(od_client_t *client, machine_msg_t *stream)
{
(void)client;
/* reply success */
machine_msg_t *msg;
msg = kiwi_be_write_complete(stream, "SET", 4);
if (msg == NULL)
return -1;
return 0;
}
int
od_console_query(od_client_t *client, machine_msg_t *stream,
char *query_data,
uint32_t query_data_size)
{
od_instance_t *instance = client->global->instance;
uint32_t query_len;
char *query;
2018-08-29 13:34:38 +00:00
machine_msg_t *msg;
int rc;
rc = kiwi_be_read_query(query_data, query_data_size, &query, &query_len);
2018-08-29 13:34:38 +00:00
if (rc == -1) {
od_error(&instance->logger, "console", client, NULL,
"bad console command");
msg = od_frontend_errorf(client, stream, KIWI_SYNTAX_ERROR,
"bad console command");
if (msg == NULL)
return -1;
return 0;
2018-08-29 13:34:38 +00:00
}
2018-08-29 13:34:38 +00:00
if (instance->config.log_query)
od_debug(&instance->logger, "console", client, NULL,
"%.*s", query_len, query);
od_parser_t parser;
od_parser_init(&parser, query, query_len);
od_token_t token;
rc = od_parser_next(&parser, &token);
switch (rc) {
case OD_PARSER_KEYWORD:
break;
case OD_PARSER_EOF:
default:
goto bad_query;
}
od_keyword_t *keyword;
keyword = od_keyword_match(od_console_keywords, &token);
if (keyword == NULL)
goto bad_query;
switch (keyword->id) {
case OD_LSHOW:
rc = od_console_show(client, stream, &parser);
if (rc == -1)
goto bad_query;
break;
case OD_LKILL_CLIENT:
rc = od_console_kill_client(client, stream, &parser);
if (rc == -1)
goto bad_query;
break;
case OD_LSET:
rc = od_console_set(client, stream);
if (rc == -1)
goto bad_query;
break;
default:
goto bad_query;
}
return 0;
bad_query:
od_error(&instance->logger, "console", client, NULL,
2018-08-29 13:34:38 +00:00
"console command error: %.*s", query_len, query);
msg = od_frontend_errorf(client, stream, KIWI_SYNTAX_ERROR,
"console command error: %.*s",
query_len, query);
if (msg == NULL)
return -1;
2018-08-29 13:34:38 +00:00
return 0;
}