Merge branch '2.2' into develop

This commit is contained in:
Johan Wikman
2018-03-27 10:17:15 +03:00
7 changed files with 231 additions and 1 deletions

View File

@ -80,6 +80,7 @@ const char CN_CONNECTION_TIMEOUT[] = "connection_timeout";
const char CN_DATA[] = "data";
const char CN_DEFAULT[] = "default";
const char CN_DESCRIPTION[] = "description";
const char CN_DUMP_LAST_STATEMENTS[] = "dump_last_statements";
const char CN_ENABLE_ROOT_USER[] = "enable_root_user";
const char CN_FILTERS[] = "filters";
const char CN_FILTER[] = "filter";
@ -121,6 +122,7 @@ const char CN_RELATIONSHIPS[] = "relationships";
const char CN_LINKS[] = "links";
const char CN_LOCAL_ADDRESS[] = "local_address";
const char CN_REQUIRED[] = "required";
const char CN_RETAIN_LAST_STATEMENTS[] = "retain_last_statements";
const char CN_RETRY_ON_FAILURE[] = "retry_on_failure";
const char CN_ROUTER[] = "router";
const char CN_ROUTER_DIAGNOSTICS[] = "router_diagnostics";
@ -1782,6 +1784,39 @@ handle_global_item(const char *name, const char *value)
gateway.users_refresh_time = USERS_REFRESH_TIME_DEFAULT;
}
}
else if (strcmp(name, CN_RETAIN_LAST_STATEMENTS) == 0)
{
char* endptr;
int intval = strtol(value, &endptr, 0);
if (*endptr == '\0' && intval >= 0)
{
session_set_retain_last_statements(intval);
}
else
{
MXS_ERROR("Invalid value for '%s': %s", CN_RETAIN_LAST_STATEMENTS, value);
}
}
else if (strcmp(name, CN_DUMP_LAST_STATEMENTS) == 0)
{
if (strcmp(value, "on_close") == 0)
{
session_set_dump_statements(SESSION_DUMP_STATEMENTS_ON_CLOSE);
}
else if (strcmp(value, "on_error") == 0)
{
session_set_dump_statements(SESSION_DUMP_STATEMENTS_ON_ERROR);
}
else if (strcmp(value, "never") == 0)
{
session_set_dump_statements(SESSION_DUMP_STATEMENTS_NEVER);
}
else
{
MXS_ERROR("%s can have the values 'never', 'on_close' or 'on_error'.",
CN_DUMP_LAST_STATEMENTS);
}
}
else
{
for (i = 0; lognames[i].name; i++)

View File

@ -37,6 +37,7 @@
#include <maxscale/spinlock.h>
#include <maxscale/utils.h>
#include <maxscale/json_api.h>
#include <maxscale/protocol/mysql.h>
#include "internal/dcb.h"
#include "internal/session.h"
@ -52,6 +53,9 @@ using std::stringstream;
*/
static uint64_t next_session_id = 1;
static uint32_t retain_last_statements = 0;
static session_dump_statements_t dump_statements = SESSION_DUMP_STATEMENTS_NEVER;
static struct session session_dummy_struct;
static void session_initialize(void *session);
@ -88,6 +92,7 @@ session_initialize(MXS_SESSION *session)
session->ses_chk_top = CHK_NUM_SESSION;
session->state = SESSION_STATE_ALLOC;
session->last_statements = new SessionStmtQueue;
session->ses_chk_tail = CHK_NUM_SESSION;
}
@ -388,8 +393,14 @@ static void session_free(MXS_SESSION *session)
static void
session_final_free(MXS_SESSION *session)
{
if (dump_statements == SESSION_DUMP_STATEMENTS_ON_CLOSE)
{
session_dump_statements(session);
}
gwbuf_free(session->stmt.buffer);
delete session->variables;
delete session->last_statements;
MXS_FREE(session);
}
@ -1276,3 +1287,94 @@ static void session_deliver_response(MXS_SESSION* session)
ss_dassert(!session->response.up.error);
ss_dassert(!session->response.buffer);
}
void session_set_retain_last_statements(uint32_t n)
{
retain_last_statements = n;
}
void session_set_dump_statements(session_dump_statements_t value)
{
dump_statements = value;
}
session_dump_statements_t session_get_dump_statements()
{
return dump_statements;
}
void session_retain_statement(MXS_SESSION* pSession, GWBUF* pBuffer)
{
if (retain_last_statements)
{
size_t len = gwbuf_length(pBuffer);
if (len > MYSQL_HEADER_LEN)
{
uint8_t header[MYSQL_HEADER_LEN + 1];
uint8_t* pHeader = NULL;
if (GWBUF_LENGTH(pBuffer) > MYSQL_HEADER_LEN)
{
pHeader = GWBUF_DATA(pBuffer);
}
else
{
gwbuf_copy_data(pBuffer, 0, MYSQL_HEADER_LEN + 1, header);
pHeader = header;
}
if (MYSQL_GET_COMMAND(pHeader) == MXS_COM_QUERY)
{
ss_dassert(pSession->last_statements->size() <= retain_last_statements);
if (pSession->last_statements->size() == retain_last_statements)
{
pSession->last_statements->pop_back();
}
std::vector<uint8_t> stmt(len - MYSQL_HEADER_LEN - 1);
gwbuf_copy_data(pBuffer, MYSQL_HEADER_LEN + 1, len - (MYSQL_HEADER_LEN + 1), &stmt.front());
pSession->last_statements->push_front(stmt);
}
}
}
}
void session_dump_statements(MXS_SESSION* pSession)
{
if (retain_last_statements)
{
int n = pSession->last_statements->size();
uint64_t id = session_get_current_id();
if ((id != 0) && (id != pSession->ses_id))
{
MXS_WARNING("Current session is %" PRIu64 ", yet statements are dumped for %" PRIu64 ". "
"The session id in the subsequent dumped statements is the wrong one.",
id, pSession->ses_id);
}
for (auto i = pSession->last_statements->rbegin(); i != pSession->last_statements->rend(); ++i)
{
int len = i->size();
const char* pStmt = (char*) &i->front();
if (id != 0)
{
MXS_NOTICE("Stmt %d: %.*s", n, len, pStmt);
}
else
{
// We are in a context where we do not have a current session, so we need to
// log the session id ourselves.
MXS_NOTICE("(%" PRIu64 ") Stmt %d: %.*s", pSession->ses_id, n, len, pStmt);
}
--n;
}
}
}