diff --git a/server/core/dcb.c b/server/core/dcb.c index e6e1f2ac0..3875c4ca2 100644 --- a/server/core/dcb.c +++ b/server/core/dcb.c @@ -1583,8 +1583,10 @@ va_list args; int dcb_isclient(DCB *dcb) { - if(dcb->session) { - if (dcb->session->client) { + if (dcb->state != DCB_STATE_LISTENING && dcb->session) + { + if (dcb->session->client) + { return (dcb->session && dcb == dcb->session->client); } } @@ -2168,3 +2170,52 @@ dcb_null_auth(DCB *dcb, SERVER *server, SESSION *session, GWBUF *buf) { return 0; } + +/** + * Return DCB counts optionally filtered by usage + * + * @param usage The usage of the DCB + * @return A count of DCBs in the desired state + */ +int +dcb_count_by_usage(DCB_USAGE usage) +{ +int rval = 0; +DCB *ptr; + + spinlock_acquire(&dcbspin); + ptr = allDCBs; + while (ptr) + { + switch (usage) + { + case DCB_USAGE_CLIENT: + if (dcb_isclient(ptr)) + rval++; + break; + case DCB_USAGE_LISTENER: + if (ptr->state == DCB_STATE_LISTENING) + rval++; + break; + case DCB_USAGE_BACKEND: + if (dcb_isclient(ptr) == 0 + && ptr->dcb_role == DCB_ROLE_REQUEST_HANDLER) + rval++; + break; + case DCB_USAGE_INTERNAL: + if (ptr->dcb_role == DCB_ROLE_REQUEST_HANDLER) + rval++; + break; + case DCB_USAGE_ZOMBIE: + if (DCB_ISZOMBIE(ptr)) + rval++; + break; + case DCB_USAGE_ALL: + rval++; + break; + } + ptr = ptr->next; + } + spinlock_release(&dcbspin); + return rval; +} diff --git a/server/core/poll.c b/server/core/poll.c index 46d049592..a581ed773 100644 --- a/server/core/poll.c +++ b/server/core/poll.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #define PROFILE_POLL 0 @@ -152,8 +153,8 @@ static struct { int n_hup; /*< Number of hangup events */ int n_accept; /*< Number of accept events */ int n_polls; /*< Number of poll cycles */ - int n_pollev; /*< Number of polls returnign events */ - int n_nbpollev; /*< Number of polls returnign events */ + int n_pollev; /*< Number of polls returning events */ + int n_nbpollev; /*< Number of polls returning events */ int n_nothreads; /*< Number of times no threads are polling */ int n_fds[MAXNFDS]; /*< Number of wakeups with particular n_fds value */ @@ -1525,3 +1526,38 @@ int i; dcb_printf(pdcb, " > %2d00ms | %-10d | %-10d\n", N_QUEUE_TIMES, queueStats.qtimes[N_QUEUE_TIMES], queueStats.exectimes[N_QUEUE_TIMES]); } + +/** + * Return a poll statistic from the polling subsystem + * + * @param stat The required statistic + * @return The value of that statistic + */ +int +poll_get_stat(POLL_STAT stat) +{ + switch (stat) + { + case POLL_STAT_READ: + return pollStats.n_read; + case POLL_STAT_WRITE: + return pollStats.n_write; + case POLL_STAT_ERROR: + return pollStats.n_error; + case POLL_STAT_HANGUP: + return pollStats.n_hup; + case POLL_STAT_ACCEPT: + return pollStats.n_accept; + case POLL_STAT_EVQ_LEN: + return pollStats.evq_length; + case POLL_STAT_EVQ_PENDING: + return pollStats.evq_pending; + case POLL_STAT_EVQ_MAX: + return pollStats.evq_max; + case POLL_STAT_MAX_QTIME: + return (int)queueStats.maxqtime; + case POLL_STAT_MAX_EXECTIME: + return (int)queueStats.maxexectime; + } + return 0; +} diff --git a/server/include/config.h b/server/include/config.h index ca3092576..f5f445c71 100644 --- a/server/include/config.h +++ b/server/include/config.h @@ -1,5 +1,5 @@ -#ifndef _CONFIG_H -#define _CONFIG_H +#ifndef _MAXSCALE_CONFIG_H +#define _MAXSCALE_CONFIG_H /* * This file is distributed as part of the MariaDB Corporation MaxScale. It is free * software: you can redistribute it and/or modify it under the terms of the diff --git a/server/include/dcb.h b/server/include/dcb.h index e82b55e33..4a4a52c80 100644 --- a/server/include/dcb.h +++ b/server/include/dcb.h @@ -271,6 +271,18 @@ typedef struct dcb { #endif } DCB; +/** + * The DCB usage filer used for returning DCB's in use for a certain reason + */ +typedef enum { + DCB_USAGE_CLIENT, + DCB_USAGE_LISTENER, + DCB_USAGE_BACKEND, + DCB_USAGE_INTERNAL, + DCB_USAGE_ZOMBIE, + DCB_USAGE_ALL +} DCB_USAGE; + #if defined(FAKE_CODE) unsigned char dcb_fake_write_errno[10240]; __int32_t dcb_fake_write_ev[10240]; @@ -319,6 +331,7 @@ int dcb_add_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void int dcb_remove_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *), void *); int dcb_isvalid(DCB *); /* Check the DCB is in the linked list */ +int dcb_count_by_usage(DCB_USAGE); /* Return counts of DCBs */ bool dcb_set_state(DCB* dcb, dcb_state_t new_state, dcb_state_t* old_state); void dcb_call_foreach (DCB_REASON reason); diff --git a/server/include/poll.h b/server/include/poll.h index 24bf0645d..4030feeb1 100644 --- a/server/include/poll.h +++ b/server/include/poll.h @@ -33,6 +33,22 @@ */ #define MAX_EVENTS 1000 +/** +* A statistic identifier that can be returned by poll_get_stat +*/ +typedef enum { + POLL_STAT_READ, + POLL_STAT_WRITE, + POLL_STAT_ERROR, + POLL_STAT_HANGUP, + POLL_STAT_ACCEPT, + POLL_STAT_EVQ_LEN, + POLL_STAT_EVQ_PENDING, + POLL_STAT_EVQ_MAX, + POLL_STAT_MAX_QTIME, + POLL_STAT_MAX_EXECTIME +} POLL_STAT; + extern void poll_init(); extern int poll_add_dcb(DCB *); extern int poll_remove_dcb(DCB *); @@ -46,4 +62,5 @@ extern void dShowThreads(DCB *dcb); void poll_add_epollin_event_to_dcb(DCB* dcb, GWBUF* buf); extern void dShowEventQ(DCB *dcb); extern void dShowEventStats(DCB *dcb); +extern int poll_get_stat(POLL_STAT stat); #endif diff --git a/server/modules/routing/maxinfo/maxinfo.c b/server/modules/routing/maxinfo/maxinfo.c index b10e07758..7ccbcba2a 100644 --- a/server/modules/routing/maxinfo/maxinfo.c +++ b/server/modules/routing/maxinfo/maxinfo.c @@ -550,7 +550,7 @@ static char buf[40]; { (*context)++; row = resultset_make_row(result); - sprintf(buf, "%u", MaxScaleStarted); + sprintf(buf, "%u", (unsigned int)MaxScaleStarted); resultset_row_set(row, 0, buf); return row; } @@ -666,9 +666,9 @@ PARSE_ERROR err; typedef RESULTSET *(*RESULTSETFUNC)(); -static struct { +static struct uri_table { char *uri; - RESULTSETFUNC func + RESULTSETFUNC func; } supported_uri[] = { { "/services", serviceGetList }, { "/listeners", serviceGetListenerList }, diff --git a/server/modules/routing/maxinfo/maxinfo_exec.c b/server/modules/routing/maxinfo/maxinfo_exec.c index 0ce3e906f..d3941525a 100644 --- a/server/modules/routing/maxinfo/maxinfo_exec.c +++ b/server/modules/routing/maxinfo/maxinfo_exec.c @@ -421,7 +421,151 @@ static VARCONTEXT context; } /** - * Variables that may be sent in a show variables + * Interface to dcb_count_by_usage for all dcbs + */ +static int +maxinfo_all_dcbs() +{ + return dcb_count_by_usage(DCB_USAGE_ALL); +} + +/** + * Interface to dcb_count_by_usage for client dcbs + */ +static int +maxinfo_client_dcbs() +{ + return dcb_count_by_usage(DCB_USAGE_CLIENT); +} + +/** + * Interface to dcb_count_by_usage for listener dcbs + */ +static int +maxinfo_listener_dcbs() +{ + return dcb_count_by_usage(DCB_USAGE_LISTENER); +} + +/** + * Interface to dcb_count_by_usage for backend dcbs + */ +static int +maxinfo_backend_dcbs() +{ + return dcb_count_by_usage(DCB_USAGE_BACKEND); +} + +/** + * Interface to dcb_count_by_usage for internal dcbs + */ +static int +maxinfo_internal_dcbs() +{ + return dcb_count_by_usage(DCB_USAGE_INTERNAL); +} + +/** + * Interface to dcb_count_by_usage for zombie dcbs + */ +static int +maxinfo_zombie_dcbs() +{ + return dcb_count_by_usage(DCB_USAGE_ZOMBIE); +} + +/** + * Interface to poll stats for reads + */ +static int +maxinfo_read_events() +{ + return poll_get_stat(POLL_STAT_READ); +} + +/** + * Interface to poll stats for writes + */ +static int +maxinfo_write_events() +{ + return poll_get_stat(POLL_STAT_WRITE); +} + +/** + * Interface to poll stats for errors + */ +static int +maxinfo_error_events() +{ + return poll_get_stat(POLL_STAT_ERROR); +} + +/** + * Interface to poll stats for hangup + */ +static int +maxinfo_hangup_events() +{ + return poll_get_stat(POLL_STAT_HANGUP); +} + +/** + * Interface to poll stats for accepts + */ +static int +maxinfo_accept_events() +{ + return poll_get_stat(POLL_STAT_ACCEPT); +} + +/** + * Interface to poll stats for event queue length + */ +static int +maxinfo_event_queue_length() +{ + return poll_get_stat(POLL_STAT_EVQ_LEN); +} + +/** + * Interface to poll stats for event pending queue length + */ +static int +maxinfo_event_pending_queue_length() +{ + return poll_get_stat(POLL_STAT_EVQ_PENDING); +} + +/** + * Interface to poll stats for max event queue length + */ +static int +maxinfo_max_event_queue_length() +{ + return poll_get_stat(POLL_STAT_EVQ_MAX); +} + +/** + * Interface to poll stats for max queue time + */ +static int +maxinfo_max_event_queue_time() +{ + return poll_get_stat(POLL_STAT_MAX_QTIME); +} + +/** + * Interface to poll stats for max event execution time + */ +static int +maxinfo_max_event_exec_time() +{ + return poll_get_stat(POLL_STAT_MAX_EXECTIME); +} + +/** + * Variables that may be sent in a show status */ static struct { char *name; @@ -434,6 +578,22 @@ static struct { { "Threads_running", VT_INT, (STATSFUNC)config_threadcount }, { "Threadpool_threads", VT_INT, (STATSFUNC)config_threadcount }, { "Threads_connected", VT_INT, (STATSFUNC)serviceSessionCountAll }, + { "Connections", VT_INT, (STATSFUNC)maxinfo_all_dcbs }, + { "Client_connections", VT_INT, (STATSFUNC)maxinfo_client_dcbs }, + { "Backend_connections", VT_INT, (STATSFUNC)maxinfo_backend_dcbs }, + { "Listeners", VT_INT, (STATSFUNC)maxinfo_listener_dcbs }, + { "Zombie_connections", VT_INT, (STATSFUNC)maxinfo_zombie_dcbs }, + { "Internal_descriptors", VT_INT, (STATSFUNC)maxinfo_internal_dcbs }, + { "Read_events", VT_INT, (STATSFUNC)maxinfo_read_events }, + { "Write_events", VT_INT, (STATSFUNC)maxinfo_write_events }, + { "Hangup_events", VT_INT, (STATSFUNC)maxinfo_hangup_events }, + { "Error_events", VT_INT, (STATSFUNC)maxinfo_error_events }, + { "Accept_events", VT_INT, (STATSFUNC)maxinfo_accept_events }, + { "Event_queue_length", VT_INT, (STATSFUNC)maxinfo_event_queue_length }, + { "Pending_events", VT_INT, (STATSFUNC)maxinfo_event_pending_queue_length }, + { "Max_event_queue_length", VT_INT, (STATSFUNC)maxinfo_max_event_queue_length }, + { "Max_event_queue_time", VT_INT, (STATSFUNC)maxinfo_max_event_queue_time }, + { "Max_event_execution_time", VT_INT, (STATSFUNC)maxinfo_max_event_exec_time }, { NULL, 0, NULL } };