1
/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software Foundation,
14
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
16
#include "table_session_connect.h"
18
static const TABLE_FIELD_TYPE field_types[]=
21
{ C_STRING_WITH_LEN("PROCESSLIST_ID") },
22
{ C_STRING_WITH_LEN("int(11)") },
26
{ C_STRING_WITH_LEN("ATTR_NAME") },
27
{ C_STRING_WITH_LEN("varchar(32)") },
31
{ C_STRING_WITH_LEN("ATTR_VALUE") },
32
{ C_STRING_WITH_LEN("varchar(1024)") },
36
{ C_STRING_WITH_LEN("ORDINAL_POSITION") },
37
{ C_STRING_WITH_LEN("int(11)") },
42
TABLE_FIELD_DEF table_session_connect::m_field_def=
45
table_session_connect::table_session_connect(const PFS_engine_table_share *share)
46
: cursor_by_thread_connect_attr(share)
48
if (session_connect_attrs_size_per_thread > 0)
50
m_copy_session_connect_attrs= (char *) my_malloc(/* 5.7: PSI_INSTRUMENT_ME, */
51
session_connect_attrs_size_per_thread,
56
m_copy_session_connect_attrs= NULL;
58
m_copy_session_connect_attrs_length= 0;
61
table_session_connect::~table_session_connect()
63
my_free(m_copy_session_connect_attrs);
67
Take a length encoded string
69
@arg ptr inout the input string array
70
@arg dest where to store the result
71
@arg dest_size max size of @c dest
72
@arg copied_len the actual length of the data copied
73
@arg start_ptr pointer to the start of input
74
@arg input_length the length of the incoming data
75
@arg copy_data copy the data or just skip the input
76
@arg from_cs character set in which @c ptr is encoded
77
@arg nchars_max maximum number of characters to read
79
@retval true parsing failed
80
@retval false parsing succeeded
82
bool parse_length_encoded_string(const char **ptr,
83
char *dest, uint dest_size,
85
const char *start_ptr, uint input_length,
87
const CHARSET_INFO *from_cs,
90
ulong copy_length, data_length;
91
const char *well_formed_error_pos= NULL, *cannot_convert_error_pos= NULL,
94
copy_length= data_length= net_field_length((uchar **) ptr);
96
/* we don't tolerate NULL as a length */
97
if (data_length == NULL_LENGTH)
100
if (*ptr - start_ptr + data_length > input_length)
103
copy_length= well_formed_copy_nchars(&my_charset_utf8_bin, dest, dest_size,
104
from_cs, *ptr, data_length, nchars_max,
105
&well_formed_error_pos,
106
&cannot_convert_error_pos,
108
*copied_len= copy_length;
109
(*ptr)+= data_length;
115
Take the nth attribute name/value pair
117
Parse the attributes blob form the beginning, skipping the attributes
118
whose number is lower than the one we seek.
119
When we reach the attribute at an index we're looking for the values
120
are copied to the output parameters.
121
If parsing fails or no more attributes are found the function stops
122
and returns an error code.
124
@arg connect_attrs pointer to the connect attributes blob
125
@arg connect_attrs_length length of @c connect_attrs
126
@arg connect_attrs_cs character set used to encode @c connect_attrs
127
@arg ordinal index of the attribute we need
128
@arg attr_name [out] buffer to receive the attribute name
129
@arg max_attr_name max size of @c attr_name in bytes
130
@arg attr_name_length [out] number of bytes written in @attr_name
131
@arg attr_value [out] buffer to receive the attribute name
132
@arg max_attr_value max size of @c attr_value in bytes
133
@arg attr_value_length [out] number of bytes written in @attr_value
135
@retval true requested attribute pair is found and copied
136
@retval false error. Either because of parsing or too few attributes.
138
bool read_nth_attr(const char *connect_attrs,
139
uint connect_attrs_length,
140
const CHARSET_INFO *connect_attrs_cs,
142
char *attr_name, uint max_attr_name,
143
uint *attr_name_length,
144
char *attr_value, uint max_attr_value,
145
uint *attr_value_length)
150
for (ptr= connect_attrs, idx= 0;
151
(uint)(ptr - connect_attrs) < connect_attrs_length && idx <= ordinal;
155
/* do the copying only if we absolutely have to */
156
bool fill_in_attr_name= idx == ordinal;
157
bool fill_in_attr_value= idx == ordinal;
160
if (parse_length_encoded_string(&ptr,
161
attr_name, max_attr_name, ©_length,
163
connect_attrs_length,
165
connect_attrs_cs, 32) ||
171
*attr_name_length= copy_length;
174
if (parse_length_encoded_string(&ptr,
175
attr_value, max_attr_value, ©_length,
177
connect_attrs_length,
179
connect_attrs_cs, 1024))
183
*attr_value_length= copy_length;
192
void table_session_connect::make_row(PFS_thread *pfs, uint ordinal)
195
pfs_lock session_lock;
196
PFS_thread_class *safe_class;
197
const CHARSET_INFO *cs;
201
/* Protect this reader against thread termination */
202
pfs->m_lock.begin_optimistic_lock(&lock);
203
/* Protect this reader against writing on session attributes */
204
pfs->m_session_lock.begin_optimistic_lock(&session_lock);
206
safe_class= sanitize_thread_class(pfs->m_class);
207
if (unlikely(safe_class == NULL))
210
/* Filtering threads must be done under the protection of the optimistic lock. */
211
if (! thread_fits(pfs))
214
/* Make a safe copy of the session attributes */
216
if (m_copy_session_connect_attrs == NULL)
219
m_copy_session_connect_attrs_length= pfs->m_session_connect_attrs_length;
221
if (m_copy_session_connect_attrs_length > session_connect_attrs_size_per_thread)
224
memcpy(m_copy_session_connect_attrs,
225
pfs->m_session_connect_attrs,
226
m_copy_session_connect_attrs_length);
228
cs= get_charset(pfs->m_session_connect_attrs_cs_number, MYF(0));
232
if (! pfs->m_session_lock.end_optimistic_lock(& session_lock))
235
if (! pfs->m_lock.end_optimistic_lock(& lock))
239
Now we have a safe copy of the data,
240
that will not change while parsing it
243
/* populate the row */
244
if (read_nth_attr(m_copy_session_connect_attrs,
245
m_copy_session_connect_attrs_length,
248
m_row.m_attr_name, (uint) sizeof(m_row.m_attr_name),
249
&m_row.m_attr_name_length,
250
m_row.m_attr_value, (uint) sizeof(m_row.m_attr_value),
251
&m_row.m_attr_value_length))
253
/* we don't expect internal threads to have connection attributes */
254
DBUG_ASSERT(pfs->m_processlist_id != 0);
256
m_row.m_ordinal_position= ordinal;
257
m_row.m_process_id= pfs->m_processlist_id;
263
int table_session_connect::read_row_values(TABLE *table,
270
if (unlikely(!m_row_exists))
271
return HA_ERR_RECORD_DELETED;
273
/* Set the null bits */
274
DBUG_ASSERT(table->s->null_bytes == 1);
277
for (; (f= *fields) ; fields++)
279
if (read_all || bitmap_is_set(table->read_set, f->field_index))
281
switch(f->field_index)
284
if (m_row.m_process_id != 0)
285
set_field_ulong(f, m_row.m_process_id);
290
set_field_varchar_utf8(f, m_row.m_attr_name,
291
m_row.m_attr_name_length);
294
if (m_row.m_attr_value_length)
295
set_field_varchar_utf8(f, m_row.m_attr_value,
296
m_row.m_attr_value_length);
300
case FO_ORDINAL_POSITION:
301
set_field_ulong(f, m_row.m_ordinal_position);
312
table_session_connect::thread_fits(PFS_thread *thread)