diff --git a/examples/roundrobinrouter.cpp b/examples/roundrobinrouter.cpp index 73663b61d..c7a1c5fbe 100644 --- a/examples/roundrobinrouter.cpp +++ b/examples/roundrobinrouter.cpp @@ -572,7 +572,8 @@ static MXS_ROUTER_SESSION* newSession(MXS_ROUTER* instance, MXS_SESSION* session static void closeSession(MXS_ROUTER* instance, MXS_ROUTER_SESSION* session); static void freeSession(MXS_ROUTER* instance, MXS_ROUTER_SESSION* session); static int routeQuery(MXS_ROUTER* instance, MXS_ROUTER_SESSION* session, GWBUF* querybuf); -static json_t* diagnostics(const MXS_ROUTER* instance); +static void diagnostics(MXS_ROUTER* instance, DCB* dcb); +static json_t* diagnostics_json(const MXS_ROUTER* instance); static void clientReply(MXS_ROUTER* instance, MXS_ROUTER_SESSION* router_session, GWBUF* resultbuf, DCB* backend_dcb); static void handleError(MXS_ROUTER* instance, MXS_ROUTER_SESSION* router_session, @@ -600,6 +601,7 @@ MXS_MODULE* MXS_CREATE_MODULE() freeSession, routeQuery, diagnostics, + diagnostics_json, clientReply, handleError, getCapabilities, @@ -759,7 +761,24 @@ static int routeQuery(MXS_ROUTER* instance, MXS_ROUTER_SESSION* session, GWBUF* * @param instance The router instance * @param dcb The DCB for diagnostic output */ -static json_t* diagnostics(const MXS_ROUTER* instance) +static void diagnostics(MXS_ROUTER* instance, DCB* dcb) +{ + RRRouter* router = static_cast(instance); + dcb_printf(dcb, "\t\tQueries routed successfully: %lu\n", router->m_routing_s); + dcb_printf(dcb, "\t\tFailed routing attempts: %lu\n", router->m_routing_f); + dcb_printf(dcb, "\t\tClient replies routed: %lu\n", router->m_routing_c); +} + +/** + * @brief Diagnostics routine (API) + * + * Print router statistics to the DCB passed in. This is usually called by the + * MaxInfo or MaxAdmin modules. + * + * @param instance The router instance + * @param dcb The DCB for diagnostic output + */ +static json_t* diagnostics_json(const MXS_ROUTER* instance) { const RRRouter* router = static_cast(instance); json_t* rval = json_object(); diff --git a/examples/testfilter.c b/examples/testfilter.c index 7c97f6d35..8b2a2ab3d 100644 --- a/examples/testfilter.c +++ b/examples/testfilter.c @@ -35,7 +35,8 @@ static void closeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session); static void freeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session); static void setDownstream(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, MXS_DOWNSTREAM *downstream); static int routeQuery(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, GWBUF *queue); -static json_t* diagnostic(const MXS_FILTER *instance, const MXS_FILTER_SESSION *fsession); +static void diagnostic(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, DCB *dcb); +static json_t* diagnostic_json(const MXS_FILTER *instance, const MXS_FILTER_SESSION *fsession); static uint64_t getCapabilities(MXS_FILTER* instance); static void destroyInstance(MXS_FILTER *instance); @@ -78,6 +79,7 @@ MXS_MODULE* MXS_CREATE_MODULE() routeQuery, NULL, // No clientReply diagnostic, + diagnostic_json, getCapabilities, destroyInstance, }; @@ -221,7 +223,32 @@ routeQuery(MXS_FILTER *instance, MXS_FILTER_SESSION *session, GWBUF *queue) * @param fsession Filter session, may be NULL * @param dcb The DCB for diagnostic output */ -static json_t* diagnostic(const MXS_FILTER *instance, const MXS_FILTER_SESSION *fsession) +static void +diagnostic(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, DCB *dcb) +{ + TEST_INSTANCE *my_instance = (TEST_INSTANCE *)instance; + TEST_SESSION *my_session = (TEST_SESSION *)fsession; + + if (my_session) + dcb_printf(dcb, "\t\tNo. of queries routed by filter: %d\n", + my_session->count); + else + dcb_printf(dcb, "\t\tNo. of sessions created: %d\n", + my_instance->sessions); +} + +/** + * Diagnostics routine + * + * If fsession is NULL then print diagnostics on the filter + * instance as a whole, otherwise print diagnostics for the + * particular session. + * + * @param instance The filter instance + * @param fsession Filter session, may be NULL + * @param dcb The DCB for diagnostic output + */ +static json_t* diagnostic_json(const MXS_FILTER *instance, const MXS_FILTER_SESSION *fsession) { return NULL; } diff --git a/examples/testroute.c b/examples/testroute.c index 74572a933..1cbdfa469 100644 --- a/examples/testroute.c +++ b/examples/testroute.c @@ -21,7 +21,8 @@ static void closeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *session); static void freeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *session); static int routeQuery(MXS_ROUTER *instance, MXS_ROUTER_SESSION *session, GWBUF *queue); static void clientReply(MXS_ROUTER *instance, MXS_ROUTER_SESSION *session, GWBUF *queue, DCB*); -static json_t* diagnostic(const MXS_ROUTER *instance); +static void diagnostic(MXS_ROUTER *instance, DCB *dcb); +static json_t* diagnostic_json(const MXS_ROUTER *instance); static uint64_t getCapabilities(MXS_ROUTER* instance); static void handleError(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session, @@ -56,6 +57,7 @@ MXS_MODULE* MXS_CREATE_MODULE() freeSession, routeQuery, diagnostic, + diagnostic_json, clientReply, handleError, getCapabilities, @@ -145,7 +147,18 @@ void clientReply(MXS_ROUTER* instance, MXS_ROUTER_SESSION* session, GWBUF* queue * @param instance The router instance * @param dcb The DCB for diagnostic output */ -static json_t* diagnostic(const MXS_ROUTER *instance) +static void +diagnostic(MXS_ROUTER *instance, DCB *dcb) +{ +} + +/** + * Diagnostics routine + * + * @param instance The router instance + * @param dcb The DCB for diagnostic output + */ +static json_t* diagnostic_json(const MXS_ROUTER *instance) { return NULL; } diff --git a/include/maxscale/authenticator.h b/include/maxscale/authenticator.h index e77abb52c..4da3bada3 100644 --- a/include/maxscale/authenticator.h +++ b/include/maxscale/authenticator.h @@ -82,6 +82,7 @@ typedef struct mxs_authenticator void (*free)(struct dcb *); void (*destroy)(void *); int (*loadusers)(struct servlistener *); + void (*diagnostic)(struct dcb*, struct servlistener *); /** * @brief Return diagnostic information about the authenticator @@ -95,7 +96,7 @@ typedef struct mxs_authenticator * * @see jansson.h */ - json_t* (*diagnostic)(const struct servlistener *listener); + json_t* (*diagnostic_json)(const struct servlistener *listener); /** This entry point was added to avoid calling authenticator functions * directly when a COM_CHANGE_USER command is executed. */ diff --git a/include/maxscale/filter.h b/include/maxscale/filter.h index 73b9e6b06..1952b1331 100644 --- a/include/maxscale/filter.h +++ b/include/maxscale/filter.h @@ -170,6 +170,15 @@ typedef struct mxs_filter_object */ int32_t (*clientReply)(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, GWBUF *queue); + /** + * @brief Called for diagnostic output + * + * @param instance Filter instance + * @param fsession Filter session, NULL if general information about the filter is queried + * @param dcb DCB where the diagnostic information should be written + */ + void (*diagnostics)(MXS_FILTER *instance, MXS_FILTER_SESSION *fsession, DCB *dcb); + /** * @brief Called for diagnostic output * @@ -180,7 +189,7 @@ typedef struct mxs_filter_object * * @see jansson.h */ - json_t* (*diagnostics)(const MXS_FILTER *instance, const MXS_FILTER_SESSION *fsession); + json_t* (*diagnostics_json)(const MXS_FILTER *instance, const MXS_FILTER_SESSION *fsession); /** * @brief Called to obtain the capabilities of the filter diff --git a/include/maxscale/filter.hh b/include/maxscale/filter.hh index 69b2cd414..d66051b0a 100644 --- a/include/maxscale/filter.hh +++ b/include/maxscale/filter.hh @@ -144,8 +144,15 @@ public: /** * Called for obtaining diagnostics about the filter session. + * + * @param pDcb The dcb where the diagnostics should be written. */ - json_t* diagnostics() const; + void diagnostics(DCB *pDcb); + + /** + * Called for obtaining diagnostics about the filter session. + */ + json_t* diagnostics_json() const; protected: FilterSession(MXS_SESSION* pSession); @@ -272,7 +279,23 @@ public: return rv; } - static json_t* diagnostics(const MXS_FILTER* pInstance, const MXS_FILTER_SESSION* pData) + static void diagnostics(MXS_FILTER* pInstance, MXS_FILTER_SESSION* pData, DCB* pDcb) + { + if (pData) + { + FilterSessionType* pFilterSession = static_cast(pData); + + MXS_EXCEPTION_GUARD(pFilterSession->diagnostics(pDcb)); + } + else + { + FilterType* pFilter = static_cast(pInstance); + + MXS_EXCEPTION_GUARD(pFilter->diagnostics(pDcb)); + } + } + + static json_t* diagnostics_json(const MXS_FILTER* pInstance, const MXS_FILTER_SESSION* pData) { json_t* rval = NULL; @@ -280,13 +303,13 @@ public: { const FilterSessionType* pFilterSession = static_cast(pData); - MXS_EXCEPTION_GUARD(rval = pFilterSession->diagnostics()); + MXS_EXCEPTION_GUARD(rval = pFilterSession->diagnostics_json()); } else { const FilterType* pFilter = static_cast(pInstance); - MXS_EXCEPTION_GUARD(rval = pFilter->diagnostics()); + MXS_EXCEPTION_GUARD(rval = pFilter->diagnostics_json()); } return rval; @@ -326,6 +349,7 @@ MXS_FILTER_OBJECT Filter::s_object = &Filter::routeQuery, &Filter::clientReply, &Filter::diagnostics, + &Filter::diagnostics_json, &Filter::getCapabilities, &Filter::destroyInstance, }; diff --git a/include/maxscale/monitor.h b/include/maxscale/monitor.h index 3c5433ab7..44e100fb4 100644 --- a/include/maxscale/monitor.h +++ b/include/maxscale/monitor.h @@ -78,6 +78,7 @@ typedef struct mxs_monitor_object * @param monitor The monitor object */ void (*stopMonitor)(MXS_MONITOR *monitor); + void (*diagnostics)(DCB *, const MXS_MONITOR *); /** * @brief Return diagnostic information about the monitor @@ -86,7 +87,7 @@ typedef struct mxs_monitor_object * * @see jansson.h */ - json_t* (*diagnostics)(const MXS_MONITOR *monitor); + json_t* (*diagnostics_json)(const MXS_MONITOR *monitor); } MXS_MONITOR_OBJECT; /** diff --git a/include/maxscale/router.h b/include/maxscale/router.h index e3af7c6df..cc6aa08cf 100644 --- a/include/maxscale/router.h +++ b/include/maxscale/router.h @@ -145,6 +145,15 @@ typedef struct mxs_router_object */ int32_t (*routeQuery)(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session, GWBUF *queue); + + /** + * @brief Called for diagnostic output + * + * @param instance Router instance + * @param dcb DCB where the diagnostic information should be written + */ + void (*diagnostics)(MXS_ROUTER *instance, DCB *dcb); + /** * @brief Called for diagnostic output * @@ -154,7 +163,7 @@ typedef struct mxs_router_object * * @see jansson.h */ - json_t* (*diagnostics)(const MXS_ROUTER *instance); + json_t* (*diagnostics_json)(const MXS_ROUTER *instance); /** * @brief Called for each reply packet diff --git a/include/maxscale/router.hh b/include/maxscale/router.hh index ec51e7275..b3800ba50 100644 --- a/include/maxscale/router.hh +++ b/include/maxscale/router.hh @@ -173,13 +173,20 @@ public: return rv; } - static json_t* diagnostics(const MXS_ROUTER* pInstance) + static void diagnostics(MXS_ROUTER* pInstance, DCB* pDcb) + { + RouterType* pRouter = static_cast(pInstance); + + MXS_EXCEPTION_GUARD(pRouter->diagnostics(pDcb)); + } + + static json_t* diagnostics_json(const MXS_ROUTER* pInstance) { const RouterType* pRouter = static_cast(pInstance); json_t* rval = NULL; - MXS_EXCEPTION_GUARD(rval = pRouter->diagnostics()); + MXS_EXCEPTION_GUARD(rval = pRouter->diagnostics_json()); return rval; } @@ -242,6 +249,7 @@ MXS_ROUTER_OBJECT Router::s_object = &Router::freeSession, &Router::routeQuery, &Router::diagnostics, + &Router::diagnostics_json, &Router::clientReply, &Router::handleError, &Router::getCapabilities, diff --git a/include/maxscale/users.h b/include/maxscale/users.h index ad8384596..ab4accc59 100644 --- a/include/maxscale/users.h +++ b/include/maxscale/users.h @@ -115,9 +115,17 @@ int users_default_loadusers(SERV_LISTENER *port); /** * @brief Default authenticator diagnostic function * + * @param dcb DCB where data is printed * @param port Port whose data is to be printed */ -json_t* users_default_diagnostic(const SERV_LISTENER *port); +void users_default_diagnostic(DCB *dcb, SERV_LISTENER *port); + +/** + * @brief Default authenticator diagnostic function + * + * @param port Port whose data is to be printed + */ +json_t* users_default_diagnostic_json(const SERV_LISTENER *port); /** * Print details of the users storage mechanism diff --git a/server/core/filter.cc b/server/core/filter.cc index d46fc007e..71db12b11 100644 --- a/server/core/filter.cc +++ b/server/core/filter.cc @@ -212,12 +212,7 @@ dprintAllFilters(DCB *dcb) } if (ptr->obj && ptr->filter) { - json_t* json = ptr->obj->diagnostics(ptr->filter, NULL); - - if (json) - { - json_decref(json); - } + ptr->obj->diagnostics(ptr->filter, NULL, dcb); } else { @@ -252,12 +247,7 @@ dprintFilter(DCB *dcb, const MXS_FILTER_DEF *filter) } if (filter->obj && filter->filter) { - json_t* json = filter->obj->diagnostics(filter->filter, NULL); - - if (json) - { - json_decref(json); - } + filter->obj->diagnostics(filter->filter, NULL, dcb); } } @@ -503,7 +493,7 @@ json_t* filter_to_json(const MXS_FILTER_DEF* filter, const char* host) if (filter->obj && filter->filter) { - json_t* diag = filter->obj->diagnostics(filter->filter, NULL); + json_t* diag = filter->obj->diagnostics_json(filter->filter, NULL); if (diag) { @@ -596,7 +586,11 @@ int FilterSession::clientReply(GWBUF* pPacket) return m_up.clientReply(pPacket); } -json_t* FilterSession::diagnostics() const +void FilterSession::diagnostics(DCB *pDcb) +{ +} + +json_t* FilterSession::diagnostics_json() const { return NULL; } diff --git a/server/core/monitor.cc b/server/core/monitor.cc index ce93fa519..d3e6e9980 100644 --- a/server/core/monitor.cc +++ b/server/core/monitor.cc @@ -477,12 +477,7 @@ monitorShow(DCB *dcb, MXS_MONITOR *monitor) { if (monitor->module->diagnostics) { - json_t* json = monitor->module->diagnostics(monitor); - - if (json) - { - json_decref(json); - } + monitor->module->diagnostics(dcb, monitor); } else { @@ -1550,7 +1545,7 @@ json_t* monitor_to_json(const MXS_MONITOR* monitor, const char* host) if (monitor->handle && monitor->module->diagnostics) { - json_t* diag = monitor->module->diagnostics(monitor); + json_t* diag = monitor->module->diagnostics_json(monitor); if (diag) { diff --git a/server/core/service.cc b/server/core/service.cc index f6bd50c6b..9c69022be 100644 --- a/server/core/service.cc +++ b/server/core/service.cc @@ -1415,12 +1415,7 @@ void dprintService(DCB *dcb, SERVICE *service) } if (service->router && service->router_instance) { - json_t* json = service->router->diagnostics(service->router_instance); - - if (json) - { - json_decref(json); - } + service->router->diagnostics(service->router_instance, dcb); } dcb_printf(dcb, "\tStarted: %s", asctime_r(localtime_r(&service->stats.started, &result), timebuf)); @@ -2298,12 +2293,7 @@ void service_print_users(DCB *dcb, const SERVICE *service) { if (port->listener && port->listener->authfunc.diagnostic) { - json_t* json = port->listener->authfunc.diagnostic(port); - - if (json) - { - json_decref(json); - } + port->listener->authfunc.diagnostic(dcb, port); } } } @@ -2368,7 +2358,7 @@ json_t* service_to_json(const SERVICE* service, const char* host) if (service->router && service->router_instance) { - json_t* diag = service->router->diagnostics(service->router_instance); + json_t* diag = service->router->diagnostics_json(service->router_instance); if (diag) { diff --git a/server/core/session.cc b/server/core/session.cc index b05e02ece..18b42d014 100644 --- a/server/core/session.cc +++ b/server/core/session.cc @@ -533,13 +533,9 @@ dprintSession(DCB *dcb, MXS_SESSION *print_session) { dcb_printf(dcb, "\tFilter: %s\n", print_session->filters[i].filter->name); - json_t* json = print_session->filters[i].filter->obj->diagnostics(print_session->filters[i].instance, - print_session->filters[i].session); - - if (json) - { - json_decref(json); - } + print_session->filters[i].filter->obj->diagnostics(print_session->filters[i].instance, + print_session->filters[i].session, + dcb); } } } diff --git a/server/core/users.cc b/server/core/users.cc index b66a22102..6ac253c21 100644 --- a/server/core/users.cc +++ b/server/core/users.cc @@ -109,7 +109,35 @@ void usersPrint(const USERS *users) hashtable_stats(users->data); } -json_t* users_default_diagnostic(const SERV_LISTENER *port) +void users_default_diagnostic(DCB *dcb, SERV_LISTENER *port) +{ + if (port->users && port->users->data) + { + HASHITERATOR *iter = hashtable_iterator(port->users->data); + + if (iter) + { + dcb_printf(dcb, "User names: "); + const char *sep = ""; + void *user; + + while ((user = hashtable_next(iter)) != NULL) + { + dcb_printf(dcb, "%s%s", sep, (char *)user); + sep = ", "; + } + + dcb_printf(dcb, "\n"); + hashtable_iterator_free(iter); + } + } + else + { + dcb_printf(dcb, "Users table is empty\n"); + } +} + +json_t* users_default_diagnostic_json(const SERV_LISTENER *port) { json_t* rval = json_array();