MXS-852: Map client PS handle to internal ID

Mapping the handles returned to the client to a session command ID allows
the mapping of client handle to the backend specific handle. Currently,
the mapping is used for diagnostic output only.
This commit is contained in:
Markus Mäkelä
2017-06-21 15:02:26 +03:00
parent 0aa0fa82b7
commit 77f78c4b20
6 changed files with 52 additions and 10 deletions

View File

@ -536,4 +536,13 @@ uint8_t mxs_mysql_get_command(GWBUF* buffer);
*/ */
bool mxs_mysql_extract_ps_response(GWBUF* buffer, MXS_PS_RESPONSE* out); bool mxs_mysql_extract_ps_response(GWBUF* buffer, MXS_PS_RESPONSE* out);
/**
* @brief Extract the ID of a COM_STMT_EXECUTE
*
* @param buffer Buffer containing a COM_STMT_EXECUTE packet
*
* @return The ID of the prepared statement being executed or 0 on failure
*/
uint32_t mxs_mysql_extract_execute(GWBUF* buffer);
MXS_END_DECLS MXS_END_DECLS

View File

@ -1636,3 +1636,16 @@ bool mxs_mysql_extract_ps_response(GWBUF* buffer, MXS_PS_RESPONSE* out)
return rval; return rval;
} }
uint32_t mxs_mysql_extract_execute(GWBUF* buffer)
{
uint32_t rval = 0;
uint8_t id[MYSQL_PS_ID_SIZE];
if (gwbuf_copy_data(buffer, MYSQL_PS_ID_OFFSET, sizeof(id), id) == sizeof(id))
{
rval = gw_mysql_get_byte4(id);
}
return rval;
}

View File

@ -154,7 +154,8 @@ struct rwsplit_config_t
* been idle for too long */ * been idle for too long */
}; };
typedef std::map<uint64_t, uint32_t> HandleMap; typedef std::map<uint64_t, uint32_t> BackendHandleMap;
typedef std::map<uint32_t, uint64_t> ClientHandleMap;
class RWBackend: public mxs::Backend class RWBackend: public mxs::Backend
{ {
@ -213,8 +214,8 @@ public:
} }
private: private:
reply_state_t m_reply_state; reply_state_t m_reply_state;
HandleMap m_ps_handles; BackendHandleMap m_ps_handles; /**< Internal ID to backend PS handle mapping */
}; };
/** Prepared statement ID to type maps for text protocols */ /** Prepared statement ID to type maps for text protocols */
@ -295,7 +296,8 @@ struct ROUTER_CLIENT_SES
ResponseMap sescmd_responses; /**< Response to each session command */ ResponseMap sescmd_responses; /**< Response to each session command */
uint64_t sent_sescmd; /**< ID of the last sent session command*/ uint64_t sent_sescmd; /**< ID of the last sent session command*/
uint64_t recv_sescmd; /**< ID of the most recently completed session command */ uint64_t recv_sescmd; /**< ID of the most recently completed session command */
PSManager ps_manager; /**< Prepared statement manager*/ PSManager ps_manager; /**< Prepared statement manager*/
ClientHandleMap ps_handles; /**< Client PS handle to internal ID mapping */
skygw_chk_t rses_chk_tail; skygw_chk_t rses_chk_tail;
}; };

View File

@ -126,6 +126,7 @@ uint32_t PSManager::get_type(uint64_t id) const
MXS_WARNING("Using unknown prepared statement with ID %lu", id); MXS_WARNING("Using unknown prepared statement with ID %lu", id);
} }
ss_dassert(rval != QUERY_TYPE_UNKNOWN);
return rval; return rval;
} }

View File

@ -148,6 +148,18 @@ bool route_single_stmt(ROUTER_INSTANCE *inst, ROUTER_CLIENT_SES *rses,
std::string id = extract_text_ps_id(querybuf); std::string id = extract_text_ps_id(querybuf);
qtype = rses->ps_manager.get_type(id); qtype = rses->ps_manager.get_type(id);
} }
else if (command == MYSQL_COM_STMT_EXECUTE)
{
uint32_t id = mxs_mysql_extract_execute(querybuf);
ClientHandleMap::iterator it = rses->ps_handles.find(id);
if (it != rses->ps_handles.end())
{
char *qtypestr = qc_typemask_to_string(rses->ps_manager.get_type(it->second));
MXS_INFO("Client handle %u maps to %lu of type %s", id, it->second, qtypestr);
MXS_FREE(qtypestr);
}
}
route_target = get_route_target(rses, qtype, querybuf->hint); route_target = get_route_target(rses, qtype, querybuf->hint);
} }

View File

@ -38,15 +38,14 @@ void process_sescmd_response(ROUTER_CLIENT_SES* rses, SRWBackend& backend,
gwbuf_copy_data(*ppPacket, MYSQL_HEADER_LEN, 1, &cmd); gwbuf_copy_data(*ppPacket, MYSQL_HEADER_LEN, 1, &cmd);
uint8_t command = backend->next_session_command()->get_command(); uint8_t command = backend->next_session_command()->get_command();
uint64_t id = backend->complete_session_command(); uint64_t id = backend->complete_session_command();
MXS_PS_RESPONSE resp = {};
if (command == MYSQL_COM_STMT_PREPARE) if (command == MYSQL_COM_STMT_PREPARE)
{ {
MXS_PS_RESPONSE resp; // This should never fail or the backend protocol is broken
ss_debug(bool b = )mxs_mysql_extract_ps_response(*ppPacket, &resp);
if (mxs_mysql_extract_ps_response(*ppPacket, &resp)) ss_dassert(b);
{ backend->add_ps_handle(id, resp.id);
backend->add_ps_handle(id, resp.id);
}
} }
if (rses->recv_sescmd < rses->sent_sescmd && if (rses->recv_sescmd < rses->sent_sescmd &&
@ -60,6 +59,12 @@ void process_sescmd_response(ROUTER_CLIENT_SES* rses, SRWBackend& backend,
/** Store the master's response so that the slave responses can /** Store the master's response so that the slave responses can
* be compared to it */ * be compared to it */
rses->sescmd_responses[id] = cmd; rses->sescmd_responses[id] = cmd;
if (command == MYSQL_COM_STMT_PREPARE)
{
/** Map the returned response to the internal ID */
rses->ps_handles[resp.id] = id;
}
} }
else else
{ {