1
0
mirror of https://github.com/mariadb-corporation/mariadb-connector-c.git synced 2025-08-07 02:42:49 +03:00

session tracking implementation (10.2-integration):

- At the moment the following session tracking types are supported:
  SESSION_TRACK_SCHEMA
  SESSION_TRACK_SYSTEM_VARIABLES
  SESSION_TRACK_STATE_CHANGE
  SESSION_TRACK_TRANSACTION_CHARACTERISTICS
- New API functions
  mysql_session_track_get_next
  mysql_session_track_get_first
This commit is contained in:
Georg Richter
2016-03-31 08:41:12 +02:00
parent 21be8f4eef
commit b4efe73c9e
9 changed files with 276 additions and 7 deletions

View File

@@ -36,6 +36,7 @@
#include <sys/stat.h>
#include <signal.h>
#include <time.h>
#include <mariadb_dyncol.h>
#ifdef HAVE_PWD_H
#include <pwd.h>
@@ -1835,6 +1836,21 @@ void mysql_close_slow_part(MYSQL *mysql)
}
}
void ma_clear_session_state(MYSQL *mysql)
{
uint i;
if (!mysql || !mysql->extension)
return;
for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
{
/* we acquired memory via ma_multi_alloc, so we don't need to free data */
list_free(mysql->extension->session_state[i].list, 0);
}
memset(mysql->extension->session_state, 0, sizeof(struct st_mariadb_session_state) * SESSION_TRACK_TYPES);
}
void STDCALL
mysql_close(MYSQL *mysql)
{
@@ -1855,6 +1871,7 @@ mysql_close(MYSQL *mysql)
mysql_close_memory(mysql);
mysql_close_options(mysql);
ma_clear_session_state(mysql);
if (mysql->net.extension)
free(mysql->net.extension);
@@ -1914,14 +1931,124 @@ get_info:
pos=(uchar*) mysql->net.read_pos;
if ((field_count= net_field_length(&pos)) == 0)
{
size_t item_len;
mysql->affected_rows= net_field_length_ll(&pos);
mysql->insert_id= net_field_length_ll(&pos);
mysql->server_status=uint2korr(pos);
pos+=2;
mysql->warning_count=uint2korr(pos);
pos+=2;
if (pos < mysql->net.read_pos+length && net_field_length(&pos))
if (pos < mysql->net.read_pos+length && (item_len= net_field_length(&pos)))
mysql->info=(char*) pos;
/* check if server supports session tracking */
if (mysql->server_capabilities & CLIENT_SESSION_TRACKING)
{
ma_clear_session_state(mysql);
pos+= item_len;
if (mysql->server_status & SERVER_SESSION_STATE_CHANGED)
{
int i;
if (pos < mysql->net.read_pos + length)
{
LIST *session_item;
MYSQL_LEX_STRING *str= NULL;
enum enum_session_state_type si_type;
uchar *old_pos= pos;
size_t item_len= net_field_length(&pos); /* length for all items */
/* length was already set, so make sure that info will be zero terminated */
if (mysql->info)
*old_pos= 0;
while (item_len > 0)
{
size_t plen;
char *data;
old_pos= pos;
si_type= (enum enum_session_state_type)net_field_length(&pos);
switch(si_type) {
case SESSION_TRACK_SCHEMA:
case SESSION_TRACK_STATE_CHANGE:
case SESSION_TRACK_TRANSACTION_CHARACTERISTICS:
case SESSION_TRACK_SYSTEM_VARIABLES:
net_field_length(&pos); /* ignore total length, item length will follow next */
plen= net_field_length(&pos);
if (!ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
0))
{
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return -1;
}
str->length= plen;
str->str= data;
memcpy(str->str, (char *)pos, plen);
pos+= plen;
session_item->data= str;
mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item);
/* in case schema has changed, we have to update mysql->db */
if (si_type == SESSION_TRACK_SCHEMA)
{
free(mysql->db);
mysql->db= malloc(plen + 1);
memcpy(mysql->db, str->str, plen);
mysql->db[plen]= 0;
}
else if (si_type == SESSION_TRACK_SYSTEM_VARIABLES)
{
my_bool set_charset= 0;
/* make sure that we update charset in case it has changed */
if (!strncmp(str->str, "character_set_client", str->length))
set_charset= 1;
plen= net_field_length(&pos);
if (!ma_multi_malloc(0,
&session_item, sizeof(LIST),
&str, sizeof(MYSQL_LEX_STRING),
&data, plen,
0))
{
SET_CLIENT_ERROR(mysql, CR_OUT_OF_MEMORY, SQLSTATE_UNKNOWN, 0);
return -1;
}
str->length= plen;
str->str= data;
memcpy(str->str, (char *)pos, plen);
pos+= plen;
session_item->data= str;
mysql->extension->session_state[si_type].list= list_add(mysql->extension->session_state[si_type].list, session_item);
if (set_charset &&
strncmp(mysql->charset->csname, str->str, str->length) != 0)
{
char cs_name[64];
MARIADB_CHARSET_INFO *cs_info;
memcpy(cs_name, str->str, str->length);
cs_name[str->length]= 0;
if ((cs_info = (MARIADB_CHARSET_INFO *)mysql_find_charset_name(cs_name)))
mysql->charset= cs_info;
}
}
break;
default:
/* not supported yet */
plen= net_field_length(&pos);
pos+= plen;
break;
}
item_len-= (pos - old_pos);
}
}
for (i= SESSION_TRACK_BEGIN; i <= SESSION_TRACK_END; i++)
{
mysql->extension->session_state[i].list= list_reverse(mysql->extension->session_state[i].list);
mysql->extension->session_state[i].current= mysql->extension->session_state[i].list;
}
}
}
return(0);
}
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
@@ -1948,6 +2075,28 @@ get_info:
return(0);
}
int STDCALL mysql_session_track_get_next(MYSQL *mysql, enum enum_session_state_type type,
const char **data, size_t *length)
{
MYSQL_LEX_STRING *str;
if (!mysql->extension->session_state[type].current)
return 1;
str= (MYSQL_LEX_STRING *)mysql->extension->session_state[type].current->data;
mysql->extension->session_state[type].current= mysql->extension->session_state[type].current->next;
*data= str->str ? str->str : NULL;
*length= str->str ? str->length : 0;
return 0;
}
int STDCALL mysql_session_track_get_first(MYSQL *mysql, enum enum_session_state_type type,
const char **data, size_t *length)
{
mysql->extension->session_state[type].current= mysql->extension->session_state[type].list;
return mysql_session_track_get_next(mysql, type, data, length);
}
my_bool STDCALL
mysql_read_query_result(MYSQL *mysql)
{