Markus Mäkelä cbb8c68770
Remove router_options
Relaced router_options with configuration parameters in the createInstance
router entry point. The same needs to be done for the filter API as barely
any filters use the feature.

Some routers (binlogrouter) still support router_options but using it is
deprecated. This had to be done as their use wasn't deprecated in 2.2.
2018-07-11 14:08:56 +03:00

311 lines
7.9 KiB
C++

/*
* Copyright (c) 2016 MariaDB Corporation Ab
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
*
* Change Date: 2022-01-01
*
* On the date above, in accordance with the Business Source License, use
* of this software will be governed by version 2 or later of the General
* Public License.
*/
/**
* @file debugcli.c - A "routing module" that in fact merely gives
* access to debug commands within the gateway
*
* @verbatim
* Revision History
*
* Date Who Description
* 18/06/13 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#define MXS_MODULE_NAME "debugcli"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <maxscale/service.h>
#include <maxscale/session.h>
#include <maxscale/router.h>
#include <maxscale/modinfo.h>
#include <maxscale/atomic.h>
#include <maxscale/spinlock.h>
#include <maxscale/dcb.h>
#include <maxscale/alloc.h>
#include <maxscale/poll.h>
#include <debugcli.h>
#include <maxscale/log_manager.h>
/* The router entry points */
static MXS_ROUTER *createInstance(SERVICE *service, MXS_CONFIG_PARAMETER* params);
static MXS_ROUTER_SESSION *newSession(MXS_ROUTER *instance, MXS_SESSION *session);
static void closeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session);
static void freeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session);
static int execute(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session, GWBUF *queue);
static void diagnostics(MXS_ROUTER *instance, DCB *dcb);
static json_t* diagnostics_json(const MXS_ROUTER *instance);
static uint64_t getCapabilities(MXS_ROUTER* instance);
extern int execute_cmd(CLI_SESSION *cli);
static SPINLOCK instlock;
static CLI_INSTANCE *instances;
/**
* The module entry point routine. It is this routine that
* must populate the structure that is referred to as the
* "module object", this is a structure with the set of
* external entry points for this module.
*
* @return The module object
*/
extern "C" MXS_MODULE* MXS_CREATE_MODULE()
{
MXS_NOTICE("Initialise debug CLI router module.");
spinlock_init(&instlock);
instances = NULL;
static MXS_ROUTER_OBJECT MyObject =
{
createInstance,
newSession,
closeSession,
freeSession,
execute,
diagnostics,
diagnostics_json,
NULL,
NULL,
getCapabilities,
NULL
};
static MXS_MODULE info =
{
MXS_MODULE_API_ROUTER,
MXS_MODULE_GA,
MXS_ROUTER_VERSION,
"The debug user interface",
"V1.1.1",
RCAP_TYPE_NO_AUTH,
&MyObject,
NULL, /* Process init. */
NULL, /* Process finish. */
NULL, /* Thread init. */
NULL, /* Thread finish. */
{
{MXS_END_MODULE_PARAMS}
}
};
return &info;
}
/**
* Create an instance of the router for a particular service
* within the gateway.
*
* @param service The service this router is being create for
* @param options Any array of options for the query router
*
* @return The instance data for this new instance
*/
static MXS_ROUTER* createInstance(SERVICE* service, MXS_CONFIG_PARAMETER* params)
{
CLI_INSTANCE *inst;
if ((inst = static_cast<CLI_INSTANCE*>(MXS_MALLOC(sizeof(CLI_INSTANCE)))) == NULL)
{
return NULL;
}
inst->service = service;
spinlock_init(&inst->lock);
inst->sessions = NULL;
/*
* We have completed the creation of the instance data, so now
* insert this router instance into the linked list of routers
* that have been created with this module.
*/
spinlock_acquire(&instlock);
inst->next = instances;
instances = inst;
spinlock_release(&instlock);
return (MXS_ROUTER *)inst;
}
/**
* Associate a new session with this instance of the router.
*
* @param instance The router instance data
* @param session The session itself
* @return Session specific data for this session
*/
static MXS_ROUTER_SESSION *
newSession(MXS_ROUTER *instance, MXS_SESSION *session)
{
CLI_INSTANCE *inst = (CLI_INSTANCE *)instance;
CLI_SESSION *client;
if ((client = (CLI_SESSION *)MXS_MALLOC(sizeof(CLI_SESSION))) == NULL)
{
return NULL;
}
client->session = session;
memset(client->cmdbuf, 0, 80);
spinlock_acquire(&inst->lock);
client->next = inst->sessions;
inst->sessions = client;
spinlock_release(&inst->lock);
session->state = SESSION_STATE_READY;
dcb_printf(session->client_dcb, "Welcome to the MariaDB Corporation MaxScale Debug Interface.\n");
dcb_printf(session->client_dcb, "Type help for a list of available commands.\n\n");
return reinterpret_cast<MXS_ROUTER_SESSION*>(client);
}
/**
* Close a session with the router, this is the mechanism
* by which a router may cleanup data structure etc.
*
* @param instance The router instance data
* @param router_session The session being closed
*/
static void
closeSession(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session)
{
CLI_INSTANCE *inst = (CLI_INSTANCE *)instance;
CLI_SESSION *session = (CLI_SESSION *)router_session;
spinlock_acquire(&inst->lock);
if (inst->sessions == session)
{
inst->sessions = session->next;
}
else
{
CLI_SESSION *ptr = inst->sessions;
while (ptr && ptr->next != session)
{
ptr = ptr->next;
}
if (ptr)
{
ptr->next = session->next;
}
}
spinlock_release(&inst->lock);
/**
* Router session is freed in session.c:session_close, when session who
* owns it, is freed.
*/
}
/**
* Free a debugcli session
*
* @param router_instance The router session
* @param router_client_session The router session as returned from newSession
*/
static void freeSession(MXS_ROUTER* router_instance,
MXS_ROUTER_SESSION* router_client_session)
{
MXS_FREE(router_client_session);
return;
}
/**
* We have data from the client, we must route it to the backend.
* This is simply a case of sending it to the connection that was
* chosen when we started the client session.
*
* @param instance The router instance
* @param router_session The router session returned from the newSession call
* @param queue The queue of data buffers to route
* @return The number of bytes sent
*/
static int
execute(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session, GWBUF *queue)
{
CLI_SESSION *session = (CLI_SESSION *)router_session;
char *cmdbuf = session->cmdbuf;
int cmdlen = 0;
*cmdbuf = 0;
/* Extract the characters */
while (queue && (cmdlen < CMDBUFLEN - 1))
{
const char* data = (char*)GWBUF_DATA(queue);
int len = GWBUF_LENGTH(queue);
int n = MXS_MIN(len, CMDBUFLEN - cmdlen - 1);
if (n != len)
{
MXS_WARNING("Too long user command truncated.");
}
strncat(cmdbuf, data, n);
cmdlen += n;
cmdbuf += n;
queue = gwbuf_consume(queue, GWBUF_LENGTH(queue));
}
if (strrchr(session->cmdbuf, '\n'))
{
if (execute_cmd(session))
{
dcb_printf(session->session->client_dcb, "MaxScale> ");
}
else
{
dcb_close(session->session->client_dcb);
}
}
return 1;
}
/**
* Display router diagnostics
*
* @param instance Instance of the router
* @param dcb DCB to send diagnostics to
*/
static void
diagnostics(MXS_ROUTER *instance, DCB *dcb)
{
return; /* Nothing to do currently */
}
/**
* Display router diagnostics
*
* @param instance Instance of the router
* @param dcb DCB to send diagnostics to
*/
static json_t* diagnostics_json(const MXS_ROUTER *instance)
{
return NULL;
}
static uint64_t getCapabilities(MXS_ROUTER* instance)
{
return RCAP_TYPE_NONE;
}