mirror of https://github.com/yandex/odyssey.git
2073 lines
55 KiB
C
2073 lines
55 KiB
C
|
|
/*
|
|
* Odyssey.
|
|
*
|
|
* Scalable PostgreSQL connection pooler.
|
|
*/
|
|
|
|
#include <kiwi.h>
|
|
#include <machinarium.h>
|
|
#include <odyssey.h>
|
|
|
|
typedef enum {
|
|
OD_LKILL_CLIENT,
|
|
OD_LRELOAD,
|
|
OD_LSHOW,
|
|
OD_LSTATS,
|
|
OD_LSERVERS,
|
|
OD_LSERVER_PREP_STMTS,
|
|
OD_LCLIENTS,
|
|
OD_LLISTS,
|
|
OD_LSET,
|
|
OD_LCREATE,
|
|
OD_LDROP,
|
|
OD_LPOOLS,
|
|
OD_LPOOLS_EXTENDED,
|
|
OD_LDATABASES,
|
|
OD_LMODULE,
|
|
OD_LERRORS,
|
|
OD_LERRORS_PER_ROUTE,
|
|
OD_LFRONTEND,
|
|
OD_LROUTER,
|
|
OD_LVERSION,
|
|
OD_LLISTEN,
|
|
OD_LSTORAGES,
|
|
} od_console_keywords_t;
|
|
|
|
static od_keyword_t od_console_keywords[] = {
|
|
od_keyword("kill_client", OD_LKILL_CLIENT),
|
|
od_keyword("reload", OD_LRELOAD),
|
|
od_keyword("show", OD_LSHOW),
|
|
od_keyword("stats", OD_LSTATS),
|
|
od_keyword("servers", OD_LSERVERS),
|
|
od_keyword("server_prep_stmts", OD_LSERVER_PREP_STMTS),
|
|
od_keyword("clients", OD_LCLIENTS),
|
|
od_keyword("lists", OD_LLISTS),
|
|
od_keyword("set", OD_LSET),
|
|
od_keyword("pools", OD_LPOOLS),
|
|
od_keyword("pools_extended", OD_LPOOLS_EXTENDED),
|
|
od_keyword("databases", OD_LDATABASES),
|
|
od_keyword("create", OD_LCREATE),
|
|
od_keyword("module", OD_LMODULE),
|
|
od_keyword("errors", OD_LERRORS),
|
|
od_keyword("errors_per_route", OD_LERRORS_PER_ROUTE),
|
|
od_keyword("frontend", OD_LFRONTEND),
|
|
od_keyword("router", OD_LROUTER),
|
|
od_keyword("drop", OD_LDROP),
|
|
od_keyword("version", OD_LVERSION),
|
|
od_keyword("listen", OD_LLISTEN),
|
|
od_keyword("storages", OD_LSTORAGES),
|
|
{ 0, 0, 0 }
|
|
};
|
|
|
|
static inline int od_console_show_stats_add(machine_msg_t *stream,
|
|
char *database, int database_len,
|
|
od_stat_t *total, od_stat_t *avg)
|
|
{
|
|
assert(stream);
|
|
int offset;
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
int rc;
|
|
rc = kiwi_be_write_data_row_add(stream, offset, database, database_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* total_wait_time */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* avg_wait_time */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* count of backend parse msgs */
|
|
data_len =
|
|
od_snprintf(data, sizeof(data), "%" PRIu64, total->count_parse);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* count of backend parse msgs reuse */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
total->count_parse_reuse);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
return 0;
|
|
}
|
|
|
|
static inline od_retcode_t
|
|
od_console_show_frontend_stats_err_add(machine_msg_t *stream,
|
|
od_route_pool_t *route_pool)
|
|
{
|
|
assert(stream);
|
|
|
|
for (size_t i = 0; i < OD_FRONTEND_STATUS_ERRORS_TYPES_COUNT; ++i) {
|
|
int offset;
|
|
int rc;
|
|
machine_msg_t *msg;
|
|
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
size_t total_count = od_err_logger_get_aggr_errors_count(
|
|
route_pool->err_logger, od_frontend_status_errs[i]);
|
|
|
|
char *err_type =
|
|
od_frontend_status_to_str(od_frontend_status_errs[i]);
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, err_type,
|
|
strlen(err_type));
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
char data[64];
|
|
int data_len;
|
|
/* error_type */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
total_count);
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
static inline int
|
|
od_console_show_router_stats_err_add(machine_msg_t *stream,
|
|
od_error_logger_t *err_logger)
|
|
{
|
|
assert(stream);
|
|
|
|
for (size_t i = 0; i < OD_ROUTER_STATUS_ERRORS_TYPES_COUNT; ++i) {
|
|
int offset;
|
|
int rc;
|
|
machine_msg_t *msg;
|
|
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
char *err_type =
|
|
od_router_status_to_str(od_router_status_errs[i]);
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, err_type,
|
|
strlen(err_type));
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* error_type */
|
|
char data[64];
|
|
int data_len;
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
od_err_logger_get_aggr_errors_count(
|
|
err_logger,
|
|
od_router_status_errs[i]));
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
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 int od_console_show_err_frontend_stats_cb(od_route_pool_t *pool,
|
|
void **argv)
|
|
{
|
|
machine_msg_t *stream = argv[0];
|
|
return od_console_show_frontend_stats_err_add(stream, pool);
|
|
}
|
|
|
|
static int od_console_show_err_router_stats_cb(od_error_logger_t *l,
|
|
void **argv)
|
|
{
|
|
machine_msg_t *stream = argv[0];
|
|
return od_console_show_router_stats_err_add(stream, l);
|
|
}
|
|
|
|
static inline int od_console_show_stats(od_client_t *client,
|
|
machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
od_cron_t *cron = client->global->cron;
|
|
|
|
if (kiwi_be_write_row_descriptionf(
|
|
stream, "sllllllllllllllll", "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",
|
|
"total_parse_count", "total_parse_count_reuse") == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
void *argv[] = { stream };
|
|
od_route_pool_stat_database(&router->route_pool,
|
|
od_console_show_stats_cb,
|
|
cron->stat_time_us, argv);
|
|
|
|
int rc = kiwi_be_write_complete(stream, "SHOW", 5);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
static inline od_retcode_t od_console_show_errors(od_client_t *client,
|
|
machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
|
|
void *argv[] = { stream };
|
|
|
|
if (kiwi_be_write_row_descriptionf(stream, "sl", "error_type",
|
|
"count") == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
int rc;
|
|
rc = od_route_pool_stat_err_router(
|
|
router, od_console_show_err_router_stats_cb, argv);
|
|
|
|
if (rc != OK_RESPONSE)
|
|
return rc;
|
|
|
|
rc = od_route_pool_stat_err_frontend(
|
|
&router->route_pool, od_console_show_err_frontend_stats_cb,
|
|
argv);
|
|
|
|
if (rc != OK_RESPONSE)
|
|
return rc;
|
|
|
|
rc = kiwi_be_write_complete(stream, "SHOW", 5);
|
|
return rc;
|
|
}
|
|
|
|
static inline int od_console_show_errors_per_route_cb(od_route_t *route,
|
|
void **argv)
|
|
{
|
|
machine_msg_t *stream = argv[0];
|
|
assert(stream);
|
|
|
|
if (!route || !route->extra_logging_enabled) {
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
for (size_t i = 0; i < OD_FRONTEND_STATUS_ERRORS_TYPES_COUNT; ++i) {
|
|
int offset;
|
|
int rc;
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL) {
|
|
/* message was not successfully allocated */
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
size_t total_count = od_err_logger_get_aggr_errors_count(
|
|
route->err_logger, od_frontend_status_errs[i]);
|
|
|
|
char *err_type =
|
|
od_frontend_status_to_str(od_frontend_status_errs[i]);
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, err_type,
|
|
strlen(err_type));
|
|
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* route user */
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
route->rule->user_name,
|
|
strlen(route->rule->user_name));
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* route database */
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
route->rule->db_name,
|
|
strlen(route->rule->db_name));
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* error_type */
|
|
|
|
char data[64];
|
|
int data_len;
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
total_count);
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
for (size_t i = 0; i < OD_ROUTER_ROUTE_STATUS_ERRORS_TYPES_COUNT; ++i) {
|
|
int offset;
|
|
int rc;
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
size_t total_count = od_err_logger_get_aggr_errors_count(
|
|
route->err_logger, od_router_route_status_errs[i]);
|
|
|
|
char *err_type =
|
|
od_router_status_to_str(od_router_route_status_errs[i]);
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, err_type,
|
|
strlen(err_type));
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* route user */
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
route->rule->user_name,
|
|
strlen(route->rule->user_name));
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* route database */
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
route->rule->db_name,
|
|
strlen(route->rule->db_name));
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* error_type */
|
|
|
|
char data[64];
|
|
int data_len;
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
total_count);
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
static inline od_retcode_t
|
|
od_console_show_errors_per_route(od_client_t *client, machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
|
|
void *argv[] = { stream };
|
|
|
|
if (kiwi_be_write_row_descriptionf(stream, "sssl", "error_type", "user",
|
|
"database", "count") == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
od_router_foreach(router, od_console_show_errors_per_route_cb, argv);
|
|
|
|
od_retcode_t rc = kiwi_be_write_complete(stream, "SHOW", 5);
|
|
return rc;
|
|
}
|
|
|
|
static inline int od_console_show_version(machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
|
|
if (kiwi_be_write_row_descriptionf(stream, "s", "version") == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
int offset;
|
|
if (kiwi_be_write_data_row(stream, &offset) == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
char data[128];
|
|
int data_len;
|
|
/* current version and build */
|
|
data_len =
|
|
od_snprintf(data, sizeof(data), "%s-%s-%s", OD_VERSION_NUMBER,
|
|
OD_VERSION_GIT, OD_VERSION_BUILD);
|
|
|
|
int rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc != OK_RESPONSE)
|
|
return rc;
|
|
|
|
rc = kiwi_be_write_complete(stream, "SHOW", 5);
|
|
return rc;
|
|
}
|
|
|
|
static inline od_retcode_t
|
|
od_console_show_quantiles(machine_msg_t *stream, int offset,
|
|
const int quantiles_count, const double *quantiles,
|
|
td_histogram_t *transactions_hgram,
|
|
td_histogram_t *queries_hgram)
|
|
{
|
|
char data[64];
|
|
int data_len;
|
|
int rc = OK_RESPONSE;
|
|
for (int i = 0; i < quantiles_count; i++) {
|
|
double q = quantiles[i];
|
|
/* query quantile */
|
|
double query_quantile = td_value_at(queries_hgram, q);
|
|
double transaction_quantile =
|
|
td_value_at(transactions_hgram, q);
|
|
if (isnan(query_quantile)) {
|
|
query_quantile = 0;
|
|
}
|
|
if (isnan(transaction_quantile)) {
|
|
transaction_quantile = 0;
|
|
}
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
(uint64_t)query_quantile);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return rc;
|
|
/* transaction quantile */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
(uint64_t)transaction_quantile);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return rc;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
static inline int od_console_show_pools_add_cb(od_route_t *route, void **argv)
|
|
{
|
|
int offset;
|
|
machine_msg_t *stream = argv[0];
|
|
bool *extended = argv[1];
|
|
double *quantiles = argv[2];
|
|
int *quantiles_count = argv[3];
|
|
td_histogram_t *common_transactions_hgram = argv[4];
|
|
td_histogram_t *common_queries_hgram = argv[5];
|
|
|
|
machine_msg_t *msg;
|
|
td_histogram_t *transactions_hgram = NULL;
|
|
td_histogram_t *queries_hgram = NULL;
|
|
td_histogram_t *freeze_hgram = NULL;
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
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 == NOT_OK_RESPONSE)
|
|
goto error;
|
|
rc = kiwi_be_write_data_row_add(stream, offset, route->id.user,
|
|
route->id.user_len - 1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
char data[64];
|
|
int data_len;
|
|
|
|
/* cl_active */
|
|
data_len = od_snprintf(data, sizeof(data), "%d",
|
|
route->client_pool.count_active);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* cl_waiting */
|
|
data_len = od_snprintf(data, sizeof(data), "%d",
|
|
route->client_pool.count_pending);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* sv_active */
|
|
data_len = od_snprintf(data, sizeof(data), "%d",
|
|
route->server_pool.count_active);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* sv_idle */
|
|
data_len = od_snprintf(data, sizeof(data), "%d",
|
|
route->server_pool.count_idle);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* sv_used */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* sv_tested */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* sv_login */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* maxwait */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* maxwait_us */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* pool_mode */
|
|
rc = NOT_OK_RESPONSE;
|
|
|
|
switch (route->rule->pool->pool) {
|
|
case OD_RULE_POOL_SESSION:
|
|
rc = kiwi_be_write_data_row_add(stream, offset, "session", 7);
|
|
break;
|
|
case OD_RULE_POOL_TRANSACTION:
|
|
rc = kiwi_be_write_data_row_add(stream, offset, "transaction",
|
|
11);
|
|
break;
|
|
case OD_RULE_POOL_STATEMENT:
|
|
rc = kiwi_be_write_data_row_add(stream, offset, "statement", 9);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
if (*extended) {
|
|
/* bytes recived */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
route->stats.recv_client);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
/* bytes sent */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
route->stats.recv_server);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* tcp conn rate */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64,
|
|
route->tcp_connections);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
transactions_hgram = td_new(QUANTILES_COMPRESSION);
|
|
queries_hgram = td_new(QUANTILES_COMPRESSION);
|
|
freeze_hgram = td_new(QUANTILES_COMPRESSION);
|
|
if (route->stats.enable_quantiles) {
|
|
for (size_t i = 0; i < QUANTILES_WINDOW; ++i) {
|
|
td_copy(freeze_hgram,
|
|
route->stats.transaction_hgram[i]);
|
|
td_merge(transactions_hgram, freeze_hgram);
|
|
td_copy(freeze_hgram,
|
|
route->stats.query_hgram[i]);
|
|
td_merge(queries_hgram, freeze_hgram);
|
|
}
|
|
td_merge(common_transactions_hgram, transactions_hgram);
|
|
td_merge(common_queries_hgram, queries_hgram);
|
|
}
|
|
rc = od_console_show_quantiles(stream, offset, *quantiles_count,
|
|
quantiles, transactions_hgram,
|
|
queries_hgram);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
}
|
|
td_safe_free(transactions_hgram);
|
|
td_safe_free(queries_hgram);
|
|
td_safe_free(freeze_hgram);
|
|
od_route_unlock(route);
|
|
return 0;
|
|
error:
|
|
td_safe_free(transactions_hgram);
|
|
td_safe_free(queries_hgram);
|
|
td_safe_free(freeze_hgram);
|
|
od_route_unlock(route);
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
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 NOT_OK_RESPONSE;
|
|
|
|
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 == NOT_OK_RESPONSE)
|
|
goto error;
|
|
od_rule_t *rule = route->rule;
|
|
od_rule_storage_t *storage = rule->storage;
|
|
|
|
/* host */
|
|
char *host = storage->host;
|
|
if (!host) {
|
|
host = "";
|
|
}
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, host, strlen(host));
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
char data[64];
|
|
int data_len;
|
|
|
|
/* port */
|
|
data_len = od_snprintf(data, sizeof(data), "%d", storage->port);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* database */
|
|
rc = kiwi_be_write_data_row_add(stream, offset, rule->db_name,
|
|
rule->db_name_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* force_user */
|
|
rc = kiwi_be_write_data_row_add(stream, offset, rule->user_name,
|
|
rule->user_name_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* pool size */
|
|
data_len = od_snprintf(data, sizeof(data), "%d", rule->pool->size);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* reserve_pool */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* pool mode */
|
|
rc = NOT_OK_RESPONSE;
|
|
if (rule->pool->pool == OD_RULE_POOL_SESSION)
|
|
rc = kiwi_be_write_data_row_add(stream, offset, "session", 7);
|
|
if (rule->pool->pool == OD_RULE_POOL_TRANSACTION)
|
|
rc = kiwi_be_write_data_row_add(stream, offset, "transaction",
|
|
11);
|
|
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
/* max_connections */
|
|
data_len = od_snprintf(data, sizeof(data), "%d", rule->client_max);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* current_connections */
|
|
data_len = od_snprintf(data, sizeof(data), "%d",
|
|
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 == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* paused */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
/* disabled */
|
|
data_len = od_snprintf(data, sizeof(data), "%" PRIu64, 0UL);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
|
|
od_route_unlock(route);
|
|
return 0;
|
|
error:
|
|
od_route_unlock(route);
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
static inline int od_console_show_databases(od_client_t *client,
|
|
machine_msg_t *stream)
|
|
{
|
|
assert(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 NOT_OK_RESPONSE;
|
|
|
|
void *argv[] = { stream };
|
|
int rc;
|
|
rc = od_router_foreach(router, od_console_show_databases_add_cb, argv);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
}
|
|
|
|
static inline int od_console_show_pools(od_client_t *client,
|
|
machine_msg_t *stream, bool extended)
|
|
{
|
|
assert(stream);
|
|
int rc;
|
|
od_router_t *router = client->global->router;
|
|
od_route_t *route = client->route;
|
|
double *quantiles = route->rule->quantiles;
|
|
int quantiles_count = route->rule->quantiles_count;
|
|
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_row_descriptionf(stream, "ssllllllllls", "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 NOT_OK_RESPONSE;
|
|
|
|
if (extended) {
|
|
char *bytes_rcv = "bytes_recieved";
|
|
rc = kiwi_be_write_row_description_add(msg, 0, bytes_rcv,
|
|
strlen(bytes_rcv), 0, 0,
|
|
23 /* INT4OID */, 4, 0,
|
|
0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
char *bytes_sent = "bytes_sent";
|
|
rc = kiwi_be_write_row_description_add(msg, 0, bytes_sent,
|
|
strlen(bytes_sent), 0, 0,
|
|
23 /* INT4OID */, 4, 0,
|
|
0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
char *tcp_conn_rate = "tcp_conn_count";
|
|
rc = kiwi_be_write_row_description_add(msg, 0, tcp_conn_rate,
|
|
strlen(tcp_conn_rate), 0,
|
|
0, 23 /* INT4OID */, 4,
|
|
0, 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
for (int i = 0; i < quantiles_count; i++) {
|
|
char caption[KIWI_MAX_VAR_SIZE];
|
|
int caption_len;
|
|
caption_len = od_snprintf(caption, sizeof(caption),
|
|
"query_%.6g", quantiles[i]);
|
|
rc = kiwi_be_write_row_description_add(
|
|
msg, 0, caption, caption_len, 0, 0,
|
|
23 /* INT4OID */, 4, 0, 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
caption_len =
|
|
od_snprintf(caption, sizeof(caption),
|
|
"transaction_%.6g", quantiles[i]);
|
|
rc = kiwi_be_write_row_description_add(
|
|
msg, 0, caption, caption_len, 0, 0,
|
|
23 /* INT4OID */, 4, 0, 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
}
|
|
|
|
td_histogram_t *transactions_hgram = NULL;
|
|
td_histogram_t *queries_hgram = NULL;
|
|
if (extended) {
|
|
transactions_hgram = td_new(QUANTILES_COMPRESSION);
|
|
queries_hgram = td_new(QUANTILES_COMPRESSION);
|
|
}
|
|
void *argv[] = { stream, &extended, quantiles,
|
|
&quantiles_count, transactions_hgram, queries_hgram };
|
|
rc = od_router_foreach(router, od_console_show_pools_add_cb, argv);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto error;
|
|
if (extended) {
|
|
int offset;
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL)
|
|
goto error;
|
|
char *aggregated_name = "aggregated";
|
|
rc = kiwi_be_write_data_row_add(stream, offset, aggregated_name,
|
|
strlen(aggregated_name));
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
rc = kiwi_be_write_data_row_add(stream, offset, aggregated_name,
|
|
strlen(aggregated_name));
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
const size_t rest_columns_count = 13;
|
|
for (size_t i = 0; i < rest_columns_count; ++i) {
|
|
rc = kiwi_be_write_data_row_add(stream, offset, NULL,
|
|
NULL_MSG_LEN);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
}
|
|
rc = od_console_show_quantiles(stream, offset, quantiles_count,
|
|
quantiles, transactions_hgram,
|
|
queries_hgram);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
}
|
|
td_safe_free(transactions_hgram);
|
|
td_safe_free(queries_hgram);
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
error:
|
|
td_safe_free(transactions_hgram);
|
|
td_safe_free(queries_hgram);
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
static inline int od_console_show_servers_server_cb(od_server_t *server,
|
|
void **argv)
|
|
{
|
|
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 NOT_OK_RESPONSE;
|
|
/* type */
|
|
char data[64];
|
|
size_t data_len;
|
|
data_len = od_snprintf(data, sizeof(data), "S");
|
|
int rc;
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* user */
|
|
rc = kiwi_be_write_data_row_add(stream, offset, route->id.user,
|
|
route->id.user_len - 1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* database */
|
|
rc = kiwi_be_write_data_row_add(stream, offset, route->id.database,
|
|
route->id.database_len - 1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* state */
|
|
char *state = "";
|
|
if (server->state == OD_SERVER_IDLE)
|
|
state = "idle";
|
|
else if (server->state == OD_SERVER_ACTIVE)
|
|
state = "active";
|
|
rc = kiwi_be_write_data_row_add(stream, offset, state, strlen(state));
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* addr */
|
|
od_getpeername(server->io.io, data, sizeof(data), 1, 0);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* port */
|
|
od_getpeername(server->io.io, data, sizeof(data), 0, 1);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* local_addr */
|
|
od_getsockname(server->io.io, data, sizeof(data), 1, 0);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* local_port */
|
|
od_getsockname(server->io.io, data, sizeof(data), 0, 1);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* connect_time */
|
|
rc = kiwi_be_write_data_row_add(msg, offset, NULL, -1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* request_time */
|
|
rc = kiwi_be_write_data_row_add(msg, offset, NULL, -1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* wait */
|
|
data_len = od_snprintf(data, sizeof(data), "0");
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* wait_us */
|
|
data_len = od_snprintf(data, sizeof(data), "0");
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* link */
|
|
data_len = od_snprintf(data, sizeof(data), "%s", "");
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* remote_pid */
|
|
data_len = od_snprintf(data, sizeof(data), "0");
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* tls */
|
|
data_len = od_snprintf(data, sizeof(data), "%s",
|
|
route->rule->storage->tls_opts->tls);
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* offline */
|
|
data_len = od_snprintf(data, sizeof(data), "%d", server->offline);
|
|
rc = kiwi_be_write_data_row_add(msg, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
return 0;
|
|
}
|
|
|
|
static inline int od_console_show_server_prep_stmt_cb(od_server_t *server,
|
|
void **argv)
|
|
{
|
|
od_route_t *route = server->route;
|
|
od_hashmap_t *hm = server->prep_stmts;
|
|
|
|
for (size_t i = 0; i < hm->size; ++i) {
|
|
od_hashmap_bucket_t *bucket = hm->buckets[i];
|
|
pthread_mutex_lock(&bucket->mu);
|
|
|
|
od_list_t *i;
|
|
od_list_foreach(&(bucket->nodes->link), i)
|
|
{
|
|
int offset;
|
|
machine_msg_t *stream = argv[0];
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL) {
|
|
goto error;
|
|
}
|
|
|
|
/* type */
|
|
char data[64];
|
|
size_t data_len;
|
|
data_len = od_snprintf(data, sizeof(data), "S");
|
|
|
|
int rc;
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data,
|
|
data_len);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
/* user */
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
route->id.user,
|
|
route->id.user_len - 1);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
/* database */
|
|
rc = kiwi_be_write_data_row_add(
|
|
stream, offset, route->id.database,
|
|
route->id.database_len - 1);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
/* sid */
|
|
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);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
od_hashmap_list_item_t *item;
|
|
item = od_container_of(i, od_hashmap_list_item_t, link);
|
|
od_hashmap_elt_t *prep_stmt = &item->key;
|
|
od_hashmap_elt_t *prep_stmt_desc = &item->value;
|
|
|
|
// description
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
prep_stmt->data,
|
|
prep_stmt->len);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
//refcount
|
|
data_len = od_snprintf(data, sizeof(data), "%d",
|
|
prep_stmt_desc->data);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data,
|
|
data_len);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
pthread_mutex_unlock(&bucket->mu);
|
|
continue;
|
|
error:
|
|
pthread_mutex_unlock(&bucket->mu);
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
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_server_prep_stmts_cb(od_route_t *route,
|
|
void **argv)
|
|
{
|
|
od_route_lock(route);
|
|
|
|
od_server_pool_foreach(&route->server_pool, OD_SERVER_ACTIVE,
|
|
od_console_show_server_prep_stmt_cb, argv);
|
|
|
|
od_server_pool_foreach(&route->server_pool, OD_SERVER_IDLE,
|
|
od_console_show_server_prep_stmt_cb, argv);
|
|
|
|
od_route_unlock(route);
|
|
return 0;
|
|
}
|
|
|
|
static inline int od_console_show_servers(od_client_t *client,
|
|
machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_row_descriptionf(
|
|
stream, "sssssdsdssddssdss", "type", "user", "database",
|
|
"state", "addr", "port", "local_addr", "local_port",
|
|
"connect_time", "request_time", "wait", "wait_us", "ptr",
|
|
"link", "remote_pid", "tls", "offline");
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
void *argv[] = { stream };
|
|
od_router_foreach(router, od_console_show_servers_cb, argv);
|
|
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
}
|
|
|
|
static inline int od_console_show_server_prep_stmts(od_client_t *client,
|
|
machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_row_descriptionf(stream, "ssssss", "type", "user",
|
|
"database", "sid", "definition",
|
|
"refcount");
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
void *argv[] = { stream };
|
|
od_router_foreach(router, od_console_show_server_prep_stmts_cb, argv);
|
|
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
}
|
|
|
|
static inline int od_console_show_clients_callback(od_client_t *client,
|
|
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 NOT_OK_RESPONSE;
|
|
char data[64];
|
|
size_t data_len;
|
|
/* type */
|
|
data_len = od_snprintf(data, sizeof(data), "C");
|
|
int rc;
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* user */
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
client->startup.user.value,
|
|
client->startup.user.value_len - 1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* database */
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
client->startup.database.value,
|
|
client->startup.database.value_len - 1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* state */
|
|
char *state = "";
|
|
if (client->state == OD_CLIENT_ACTIVE)
|
|
state = "active";
|
|
else if (client->state == OD_CLIENT_PENDING)
|
|
state = "pending";
|
|
else if (client->state == OD_CLIENT_QUEUE)
|
|
state = "queue";
|
|
rc = kiwi_be_write_data_row_add(stream, offset, state, strlen(state));
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* storage_user */
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
client->rule->storage_user,
|
|
client->rule->storage_user_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* addr */
|
|
od_getpeername(client->io.io, data, sizeof(data), 1, 0);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* port */
|
|
od_getpeername(client->io.io, data, sizeof(data), 0, 1);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* local_addr */
|
|
od_getsockname(client->io.io, data, sizeof(data), 1, 0);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* local_port */
|
|
od_getsockname(client->io.io, data, sizeof(data), 0, 1);
|
|
data_len = strlen(data);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* connect_time */
|
|
rc = kiwi_be_write_data_row_add(stream, offset, NULL, -1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* request_time */
|
|
rc = kiwi_be_write_data_row_add(stream, offset, NULL, -1);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* wait */
|
|
data_len = od_snprintf(data, sizeof(data), "0");
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* wait_us */
|
|
data_len = od_snprintf(data, sizeof(data), "0");
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* link */
|
|
data_len = od_snprintf(data, sizeof(data), "%s", "");
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* remote_pid */
|
|
data_len = od_snprintf(data, sizeof(data), "0");
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* tls */
|
|
data_len = od_snprintf(data, sizeof(data), "%s", "");
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
return 0;
|
|
}
|
|
|
|
static inline od_retcode_t 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)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_row_descriptionf(
|
|
stream, "ssssssdsdssddssds", "type", "user", "database",
|
|
"state", "storage_user", "addr", "port", "local_addr",
|
|
"local_port", "connect_time", "request_time", "wait", "wait_us",
|
|
"ptr", "link", "remote_pid", "tls");
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
void *argv[] = { stream };
|
|
od_router_foreach(router, od_console_show_clients_cb, argv);
|
|
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
}
|
|
|
|
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 NOT_OK_RESPONSE;
|
|
/* list */
|
|
int rc;
|
|
rc = kiwi_be_write_data_row_add(stream, offset, list, strlen(list));
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* 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 == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
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];
|
|
int *free_servers = argv[1];
|
|
(*used_servers) += route->server_pool.count_active;
|
|
(*free_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)
|
|
{
|
|
assert(stream);
|
|
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_free_servers = 0;
|
|
int router_pools = router->route_pool.count;
|
|
int router_clients = od_atomic_u32_of(&router->clients);
|
|
|
|
void *argv[] = { &router_used_servers, &router_free_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 NOT_OK_RESPONSE;
|
|
int rc;
|
|
/* databases */
|
|
rc = od_console_show_lists_add(stream, "databases", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* users */
|
|
rc = od_console_show_lists_add(stream, "users", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* pools */
|
|
rc = od_console_show_lists_add(stream, "pools", router_pools);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* free_clients */
|
|
rc = od_console_show_lists_add(stream, "free_clients", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* used_clients */
|
|
rc = od_console_show_lists_add(stream, "used_clients", router_clients);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* login_clients */
|
|
rc = od_console_show_lists_add(stream, "login_clients", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* free_servers */
|
|
rc = od_console_show_lists_add(stream, "free_servers",
|
|
router_free_servers);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* used_servers */
|
|
rc = od_console_show_lists_add(stream, "used_servers",
|
|
router_used_servers);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* dns_names */
|
|
rc = od_console_show_lists_add(stream, "dns_names", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* dns_zones */
|
|
rc = od_console_show_lists_add(stream, "dns_zones", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* dns_queries */
|
|
rc = od_console_show_lists_add(stream, "dns_queries", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
/* dns_pending */
|
|
rc = od_console_show_lists_add(stream, "dns_pending", 0);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
return NOT_OK_RESPONSE;
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
}
|
|
|
|
static inline int od_console_write_nullable_str(machine_msg_t *stream,
|
|
int offset, char *str)
|
|
{
|
|
char data[64];
|
|
int data_len;
|
|
|
|
if (str == NULL) {
|
|
data_len = od_snprintf(data, sizeof(data), "(None)");
|
|
return kiwi_be_write_data_row_add(stream, offset, data,
|
|
data_len);
|
|
}
|
|
|
|
return kiwi_be_write_data_row_add(stream, offset, str, strlen(str));
|
|
}
|
|
|
|
static inline int od_console_show_tls_options(od_tls_opts_t *tls_opts,
|
|
int offset, machine_msg_t *stream)
|
|
{
|
|
char *tls = od_config_tls_to_str(tls_opts->tls_mode);
|
|
|
|
od_retcode_t rc;
|
|
|
|
/* tls */
|
|
rc = od_console_write_nullable_str(stream, offset, tls);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* tls_cert_file */
|
|
rc = od_console_write_nullable_str(stream, offset,
|
|
tls_opts->tls_cert_file);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* tls_key_file */
|
|
rc = od_console_write_nullable_str(stream, offset,
|
|
tls_opts->tls_key_file);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* tls_ca_file */
|
|
rc = od_console_write_nullable_str(stream, offset,
|
|
tls_opts->tls_ca_file);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* tls_protocols */
|
|
rc = od_console_write_nullable_str(stream, offset,
|
|
tls_opts->tls_protocols);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
static inline int od_console_show_listen(od_client_t *client,
|
|
machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_row_descriptionf(stream, "sdsssss", "host", "port",
|
|
"tls", "tls_cert_file",
|
|
"tls_key_file", "tls_ca_file",
|
|
"tls_protocols");
|
|
|
|
if (msg == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
od_instance_t *instance = router->global->instance;
|
|
od_config_t *config = &instance->config;
|
|
|
|
char data[64];
|
|
int data_len;
|
|
int rc;
|
|
int offset;
|
|
|
|
od_list_t *i;
|
|
od_list_foreach(&config->listen, i)
|
|
{
|
|
od_config_listen_t *listen_config;
|
|
listen_config = od_container_of(i, od_config_listen_t, link);
|
|
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
/* host */
|
|
|
|
rc = od_console_write_nullable_str(stream, offset,
|
|
listen_config->host);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
/* port */
|
|
data_len = od_snprintf(data, sizeof(data), "%d",
|
|
listen_config->port);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
|
|
rc = od_console_show_tls_options(listen_config->tls_opts,
|
|
offset, stream);
|
|
if (rc != OK_RESPONSE) {
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
}
|
|
|
|
static inline int od_console_show_storages(od_client_t *client,
|
|
machine_msg_t *stream)
|
|
{
|
|
assert(stream);
|
|
od_router_t *router = client->global->router;
|
|
|
|
machine_msg_t *msg;
|
|
msg = kiwi_be_write_row_descriptionf(stream, "ssdsssss", "type", "host",
|
|
"port", "tls", "tls_cert_file",
|
|
"tls_key_file", "tls_ca_file",
|
|
"tls_protocols");
|
|
|
|
if (msg == NULL) {
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
od_rules_t *rules = &router->rules;
|
|
|
|
int rc;
|
|
int offset;
|
|
|
|
pthread_mutex_lock(&rules->mu);
|
|
|
|
od_list_t *i;
|
|
od_list_foreach(&rules->storages, i)
|
|
{
|
|
od_rule_storage_t *storage;
|
|
storage = od_container_of(i, od_rule_storage_t, link);
|
|
|
|
msg = kiwi_be_write_data_row(stream, &offset);
|
|
if (msg == NULL) {
|
|
rc = NOT_OK_RESPONSE;
|
|
goto error;
|
|
}
|
|
|
|
if (storage->storage_type == OD_RULE_STORAGE_REMOTE) {
|
|
rc = kiwi_be_write_data_row_add(stream, offset,
|
|
"remote", 6 + 1);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
} else {
|
|
rc = kiwi_be_write_data_row_add(stream, offset, "local",
|
|
5 + 1);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
char *host = storage->host;
|
|
if (!host) {
|
|
host = "";
|
|
}
|
|
|
|
rc = kiwi_be_write_data_row_add(stream, offset, host,
|
|
strlen(host));
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
char data[64];
|
|
int data_len;
|
|
|
|
/* port */
|
|
data_len = od_snprintf(data, sizeof(data), "%d", storage->port);
|
|
rc = kiwi_be_write_data_row_add(stream, offset, data, data_len);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
|
|
rc = od_console_show_tls_options(storage->tls_opts, offset,
|
|
stream);
|
|
if (rc != OK_RESPONSE) {
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
pthread_mutex_unlock(&rules->mu);
|
|
return kiwi_be_write_complete(stream, "SHOW", 5);
|
|
error:
|
|
pthread_mutex_unlock(&rules->mu);
|
|
return rc;
|
|
}
|
|
|
|
static inline int od_console_show(od_client_t *client, machine_msg_t *stream,
|
|
od_parser_t *parser)
|
|
{
|
|
assert(stream);
|
|
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 NOT_OK_RESPONSE;
|
|
}
|
|
od_keyword_t *keyword;
|
|
keyword = od_keyword_match(od_console_keywords, &token);
|
|
if (keyword == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
switch (keyword->id) {
|
|
case OD_LSTATS:
|
|
return od_console_show_stats(client, stream);
|
|
case OD_LPOOLS:
|
|
return od_console_show_pools(client, stream, false);
|
|
case OD_LPOOLS_EXTENDED:
|
|
return od_console_show_pools(client, stream, true);
|
|
case OD_LDATABASES:
|
|
return od_console_show_databases(client, stream);
|
|
case OD_LSERVER_PREP_STMTS:
|
|
return od_console_show_server_prep_stmts(client, stream);
|
|
case OD_LSERVERS:
|
|
return od_console_show_servers(client, stream);
|
|
case OD_LCLIENTS:
|
|
return od_console_show_clients(client, stream);
|
|
case OD_LLISTS:
|
|
return od_console_show_lists(client, stream);
|
|
case OD_LERRORS:
|
|
return od_console_show_errors(client, stream);
|
|
case OD_LERRORS_PER_ROUTE:
|
|
return od_console_show_errors_per_route(client, stream);
|
|
case OD_LVERSION:
|
|
return od_console_show_version(stream);
|
|
case OD_LLISTEN:
|
|
return od_console_show_listen(client, stream);
|
|
case OD_LSTORAGES:
|
|
return od_console_show_storages(client, stream);
|
|
}
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
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 NOT_OK_RESPONSE;
|
|
od_id_t id;
|
|
if (token.value.string.size != (sizeof(id.id) + 1))
|
|
return NOT_OK_RESPONSE;
|
|
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_reload(od_client_t *client, machine_msg_t *stream)
|
|
{
|
|
od_instance_t *instance = client->global->instance;
|
|
|
|
od_log(&instance->logger, "console", NULL, NULL,
|
|
"RELOAD command received");
|
|
od_system_config_reload(client->global->system);
|
|
return kiwi_be_write_complete(stream, "RELOAD", 7);
|
|
}
|
|
|
|
static inline int od_console_set(od_client_t *client, machine_msg_t *stream)
|
|
{
|
|
(void)client;
|
|
/* reply success */
|
|
return kiwi_be_write_complete(stream, "SET", 4);
|
|
}
|
|
|
|
static inline int od_console_add_module(od_client_t *client,
|
|
machine_msg_t *stream,
|
|
od_parser_t *parser)
|
|
{
|
|
assert(stream);
|
|
od_token_t token;
|
|
int rc;
|
|
rc = od_parser_next(parser, &token);
|
|
od_instance_t *instance = client->global->instance;
|
|
|
|
switch (rc) {
|
|
case OD_PARSER_STRING: {
|
|
char module_path[MAX_MODULE_PATH_LEN];
|
|
od_token_to_string_dest(&token, module_path);
|
|
|
|
od_log(&instance->logger, "od module dynamic load", NULL, NULL,
|
|
"loading module with path %s", module_path);
|
|
int retcode = od_target_module_add(
|
|
&instance->logger,
|
|
((od_extention_t *)client->global->extentions)->modules,
|
|
module_path);
|
|
if (retcode == 0) {
|
|
od_frontend_infof(client, stream,
|
|
"module was successfully loaded!");
|
|
} else {
|
|
od_frontend_errorf(
|
|
client, stream, KIWI_SYSTEM_ERROR,
|
|
"module was NOT successfully loaded! Check logs for details");
|
|
}
|
|
return retcode;
|
|
}
|
|
case OD_PARSER_EOF:
|
|
default:
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
}
|
|
|
|
static inline int od_console_unload_module(od_client_t *client,
|
|
machine_msg_t *stream,
|
|
od_parser_t *parser)
|
|
{
|
|
assert(stream);
|
|
od_token_t token;
|
|
int rc;
|
|
rc = od_parser_next(parser, &token);
|
|
od_instance_t *instance = client->global->instance;
|
|
|
|
switch (rc) {
|
|
case OD_PARSER_STRING: {
|
|
char module_path[MAX_MODULE_PATH_LEN];
|
|
od_token_to_string_dest(&token, module_path);
|
|
|
|
od_log(&instance->logger, "od module dynamic unload", NULL,
|
|
NULL, "unloading module with path %s", module_path);
|
|
int retcode = od_target_module_unload(
|
|
&instance->logger,
|
|
((od_extention_t *)client->global->extentions)->modules,
|
|
module_path);
|
|
if (retcode == 0) {
|
|
od_frontend_infof(client, stream,
|
|
"module was successfully unloaded!");
|
|
} else {
|
|
od_frontend_errorf(client, stream, KIWI_SYSTEM_ERROR,
|
|
"module was NOT successfully "
|
|
"unloaded! Check logs for details");
|
|
}
|
|
return retcode;
|
|
}
|
|
case OD_PARSER_EOF:
|
|
default:
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
}
|
|
|
|
static inline int od_console_create(od_client_t *client, machine_msg_t *stream,
|
|
od_parser_t *parser)
|
|
{
|
|
assert(stream);
|
|
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 NOT_OK_RESPONSE;
|
|
}
|
|
od_keyword_t *keyword;
|
|
keyword = od_keyword_match(od_console_keywords, &token);
|
|
if (keyword == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
switch (keyword->id) {
|
|
case OD_LMODULE:
|
|
return od_console_add_module(client, stream, parser);
|
|
}
|
|
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
static inline int od_console_drop_server_cb(od_server_t *server,
|
|
od_attribute_unused() void **argv)
|
|
{
|
|
server->offline = 1;
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
static inline od_retcode_t od_console_drop_server(od_route_t *route,
|
|
void **argv)
|
|
{
|
|
od_route_lock(route);
|
|
|
|
od_server_pool_foreach(&route->server_pool, OD_SERVER_ACTIVE,
|
|
od_console_drop_server_cb, argv);
|
|
|
|
od_server_pool_foreach(&route->server_pool, OD_SERVER_IDLE,
|
|
od_console_drop_server_cb, argv);
|
|
|
|
od_route_unlock(route);
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
static inline od_retcode_t od_console_drop_servers(od_client_t *client,
|
|
machine_msg_t *stream,
|
|
od_parser_t *parser)
|
|
{
|
|
(void)client;
|
|
assert(stream);
|
|
|
|
od_token_t token;
|
|
int rc;
|
|
rc = od_parser_next(parser, &token);
|
|
switch (rc) {
|
|
case OD_PARSER_EOF:
|
|
break;
|
|
default:
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
od_router_t *router = client->global->router;
|
|
|
|
void *argv[] = { stream };
|
|
od_router_foreach(router, od_console_drop_server, argv);
|
|
return OK_RESPONSE;
|
|
}
|
|
|
|
static inline od_retcode_t
|
|
od_console_drop(od_client_t *client, machine_msg_t *stream, od_parser_t *parser)
|
|
{
|
|
assert(stream);
|
|
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 NOT_OK_RESPONSE;
|
|
}
|
|
od_keyword_t *keyword;
|
|
keyword = od_keyword_match(od_console_keywords, &token);
|
|
if (keyword == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
switch (keyword->id) {
|
|
case OD_LSERVERS:
|
|
return od_console_drop_servers(client, stream, parser);
|
|
case OD_LMODULE:
|
|
return od_console_unload_module(client, stream, parser);
|
|
default:
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
return NOT_OK_RESPONSE;
|
|
}
|
|
|
|
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;
|
|
machine_msg_t *msg;
|
|
if (client->rule->user_role != OD_RULE_ROLE_ADMIN &&
|
|
client->rule->user_role != OD_RULE_ROLE_STAT) {
|
|
goto incorrect_role;
|
|
}
|
|
int rc;
|
|
rc = kiwi_be_read_query(query_data, query_data_size, &query,
|
|
&query_len);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
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 NOT_OK_RESPONSE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
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 == NOT_OK_RESPONSE)
|
|
goto bad_query;
|
|
break;
|
|
case OD_LKILL_CLIENT:
|
|
if (client->rule->user_role != OD_RULE_ROLE_ADMIN)
|
|
goto incorrect_role;
|
|
rc = od_console_kill_client(client, stream, &parser);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto bad_query;
|
|
break;
|
|
case OD_LRELOAD:
|
|
if (client->rule->user_role != OD_RULE_ROLE_ADMIN)
|
|
goto incorrect_role;
|
|
rc = od_console_reload(client, stream);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto bad_query;
|
|
break;
|
|
case OD_LSET:
|
|
if (client->rule->user_role != OD_RULE_ROLE_ADMIN)
|
|
goto incorrect_role;
|
|
rc = od_console_set(client, stream);
|
|
if (rc == NOT_OK_RESPONSE)
|
|
goto bad_query;
|
|
break;
|
|
case OD_LCREATE:
|
|
if (client->rule->user_role != OD_RULE_ROLE_ADMIN)
|
|
goto incorrect_role;
|
|
rc = od_console_create(client, stream, &parser);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto bad_query;
|
|
}
|
|
break;
|
|
case OD_LDROP:
|
|
if (client->rule->user_role != OD_RULE_ROLE_ADMIN)
|
|
goto incorrect_role;
|
|
rc = od_console_drop(client, stream, &parser);
|
|
if (rc == NOT_OK_RESPONSE) {
|
|
goto bad_query;
|
|
}
|
|
break;
|
|
default:
|
|
goto bad_query;
|
|
}
|
|
|
|
return 0;
|
|
|
|
incorrect_role:
|
|
od_error(&instance->logger, "console", client, NULL,
|
|
"Unsuitable user role to emit console command");
|
|
msg = od_frontend_errorf(
|
|
client, stream, KIWI_INSUFFICIENT_PRIVILEGE,
|
|
"Unsuitable user role to emit console command");
|
|
if (msg == NULL)
|
|
return NOT_OK_RESPONSE;
|
|
|
|
return 0;
|
|
|
|
bad_query:
|
|
od_error(&instance->logger, "console", client, NULL,
|
|
"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 NOT_OK_RESPONSE;
|
|
|
|
return 0;
|
|
}
|