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);
/**
* @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

View File

@ -1636,3 +1636,16 @@ bool mxs_mysql_extract_ps_response(GWBUF* buffer, MXS_PS_RESPONSE* out)
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 */
};
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
{
@ -214,7 +215,7 @@ public:
private:
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 */
@ -296,6 +297,7 @@ struct ROUTER_CLIENT_SES
uint64_t sent_sescmd; /**< ID of the last sent session command*/
uint64_t recv_sescmd; /**< ID of the most recently completed session command */
PSManager ps_manager; /**< Prepared statement manager*/
ClientHandleMap ps_handles; /**< Client PS handle to internal ID mapping */
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);
}
ss_dassert(rval != QUERY_TYPE_UNKNOWN);
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);
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);
}

View File

@ -38,16 +38,15 @@ void process_sescmd_response(ROUTER_CLIENT_SES* rses, SRWBackend& backend,
gwbuf_copy_data(*ppPacket, MYSQL_HEADER_LEN, 1, &cmd);
uint8_t command = backend->next_session_command()->get_command();
uint64_t id = backend->complete_session_command();
MXS_PS_RESPONSE resp = {};
if (command == MYSQL_COM_STMT_PREPARE)
{
MXS_PS_RESPONSE resp;
if (mxs_mysql_extract_ps_response(*ppPacket, &resp))
{
// This should never fail or the backend protocol is broken
ss_debug(bool b = )mxs_mysql_extract_ps_response(*ppPacket, &resp);
ss_dassert(b);
backend->add_ps_handle(id, resp.id);
}
}
if (rses->recv_sescmd < rses->sent_sescmd &&
id == rses->recv_sescmd + 1 &&
@ -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
* be compared to it */
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
{