~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

Viewing changes to storage/perfschema/table_session_connect.cc

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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 */
 
15
 
 
16
#include "table_session_connect.h"
 
17
 
 
18
static const TABLE_FIELD_TYPE field_types[]=
 
19
{
 
20
  {
 
21
    { C_STRING_WITH_LEN("PROCESSLIST_ID") },
 
22
    { C_STRING_WITH_LEN("int(11)") },
 
23
    { NULL, 0}
 
24
  },
 
25
  {
 
26
    { C_STRING_WITH_LEN("ATTR_NAME") },
 
27
    { C_STRING_WITH_LEN("varchar(32)") },
 
28
    { NULL, 0}
 
29
  },
 
30
  {
 
31
    { C_STRING_WITH_LEN("ATTR_VALUE") },
 
32
    { C_STRING_WITH_LEN("varchar(1024)") },
 
33
    { NULL, 0}
 
34
  },
 
35
  {
 
36
    { C_STRING_WITH_LEN("ORDINAL_POSITION") },
 
37
    { C_STRING_WITH_LEN("int(11)") },
 
38
    { NULL, 0}
 
39
  }
 
40
};
 
41
 
 
42
TABLE_FIELD_DEF table_session_connect::m_field_def=
 
43
{ 4, field_types };
 
44
 
 
45
table_session_connect::table_session_connect(const PFS_engine_table_share *share)
 
46
 : cursor_by_thread_connect_attr(share)
 
47
{
 
48
  if (session_connect_attrs_size_per_thread > 0)
 
49
  {
 
50
    m_copy_session_connect_attrs= (char *) my_malloc(/* 5.7: PSI_INSTRUMENT_ME, */
 
51
                                             session_connect_attrs_size_per_thread,
 
52
                                             MYF(0));
 
53
  }
 
54
  else
 
55
  {
 
56
    m_copy_session_connect_attrs= NULL;
 
57
  }
 
58
  m_copy_session_connect_attrs_length= 0;
 
59
}
 
60
 
 
61
table_session_connect::~table_session_connect()
 
62
{
 
63
  my_free(m_copy_session_connect_attrs);
 
64
}
 
65
 
 
66
/**
 
67
  Take a length encoded string
 
68
 
 
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
 
78
  @return status
 
79
    @retval true    parsing failed
 
80
    @retval false   parsing succeeded
 
81
*/
 
82
bool parse_length_encoded_string(const char **ptr,
 
83
                 char *dest, uint dest_size,
 
84
                 uint *copied_len,
 
85
                 const char *start_ptr, uint input_length,
 
86
                 bool copy_data,
 
87
                 const CHARSET_INFO *from_cs,
 
88
                 uint nchars_max)
 
89
{
 
90
  ulong copy_length, data_length;
 
91
  const char *well_formed_error_pos= NULL, *cannot_convert_error_pos= NULL,
 
92
        *from_end_pos= NULL;
 
93
 
 
94
  copy_length= data_length= net_field_length((uchar **) ptr);
 
95
 
 
96
  /* we don't tolerate NULL as a length */
 
97
  if (data_length == NULL_LENGTH)
 
98
    return true;
 
99
 
 
100
  if (*ptr - start_ptr + data_length > input_length)
 
101
    return true;
 
102
 
 
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,
 
107
                                       &from_end_pos);
 
108
  *copied_len= copy_length;
 
109
  (*ptr)+= data_length;
 
110
 
 
111
  return false;
 
112
}
 
113
 
 
114
/**
 
115
  Take the nth attribute name/value pair
 
116
 
 
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.
 
123
 
 
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
 
134
  @return status
 
135
    @retval true    requested attribute pair is found and copied
 
136
    @retval false   error. Either because of parsing or too few attributes.
 
137
*/
 
138
bool read_nth_attr(const char *connect_attrs,
 
139
                   uint connect_attrs_length,
 
140
                   const CHARSET_INFO *connect_attrs_cs,
 
141
                   uint ordinal,
 
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)
 
146
{
 
147
  uint idx;
 
148
  const char *ptr;
 
149
 
 
150
  for (ptr= connect_attrs, idx= 0;
 
151
       (uint)(ptr - connect_attrs) < connect_attrs_length && idx <= ordinal;
 
152
      idx++)
 
153
  {
 
154
    uint copy_length;
 
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;
 
158
 
 
159
    /* read the key */
 
160
    if (parse_length_encoded_string(&ptr,
 
161
                                    attr_name, max_attr_name, &copy_length,
 
162
                                    connect_attrs,
 
163
                                    connect_attrs_length,
 
164
                                    fill_in_attr_name,
 
165
                                    connect_attrs_cs, 32) ||
 
166
        !copy_length
 
167
        )
 
168
      return false;
 
169
 
 
170
    if (idx == ordinal)
 
171
      *attr_name_length= copy_length;
 
172
      
 
173
    /* read the value */
 
174
    if (parse_length_encoded_string(&ptr,
 
175
                                    attr_value, max_attr_value, &copy_length,
 
176
                                    connect_attrs,
 
177
                                    connect_attrs_length,
 
178
                                    fill_in_attr_value,
 
179
                                    connect_attrs_cs, 1024))
 
180
      return false;
 
181
 
 
182
    if (idx == ordinal)
 
183
      *attr_value_length= copy_length;
 
184
 
 
185
    if (idx == ordinal)
 
186
      return true;
 
187
  }
 
188
 
 
189
  return false;
 
190
}
 
191
 
 
192
void table_session_connect::make_row(PFS_thread *pfs, uint ordinal)
 
193
{
 
194
  pfs_lock lock;
 
195
  pfs_lock session_lock;
 
196
  PFS_thread_class *safe_class;
 
197
  const CHARSET_INFO *cs;
 
198
 
 
199
  m_row_exists= false;
 
200
 
 
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);
 
205
 
 
206
  safe_class= sanitize_thread_class(pfs->m_class);
 
207
  if (unlikely(safe_class == NULL))
 
208
    return;
 
209
 
 
210
  /* Filtering threads must be done under the protection of the optimistic lock. */
 
211
  if (! thread_fits(pfs))
 
212
    return;
 
213
 
 
214
  /* Make a safe copy of the session attributes */
 
215
 
 
216
  if (m_copy_session_connect_attrs == NULL)
 
217
    return;
 
218
 
 
219
  m_copy_session_connect_attrs_length= pfs->m_session_connect_attrs_length;
 
220
 
 
221
  if (m_copy_session_connect_attrs_length > session_connect_attrs_size_per_thread)
 
222
    return;
 
223
 
 
224
  memcpy(m_copy_session_connect_attrs,
 
225
         pfs->m_session_connect_attrs,
 
226
         m_copy_session_connect_attrs_length);
 
227
 
 
228
  cs= get_charset(pfs->m_session_connect_attrs_cs_number, MYF(0));
 
229
  if (cs == NULL)
 
230
    return;
 
231
 
 
232
  if (! pfs->m_session_lock.end_optimistic_lock(& session_lock))
 
233
    return;
 
234
 
 
235
  if (! pfs->m_lock.end_optimistic_lock(& lock))
 
236
    return;
 
237
 
 
238
  /*
 
239
    Now we have a safe copy of the data,
 
240
    that will not change while parsing it
 
241
  */
 
242
 
 
243
  /* populate the row */
 
244
  if (read_nth_attr(m_copy_session_connect_attrs,
 
245
                    m_copy_session_connect_attrs_length,
 
246
                    cs,
 
247
                    ordinal,
 
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))
 
252
  {
 
253
    /* we don't expect internal threads to have connection attributes */
 
254
    DBUG_ASSERT(pfs->m_processlist_id != 0);
 
255
 
 
256
    m_row.m_ordinal_position= ordinal;
 
257
    m_row.m_process_id= pfs->m_processlist_id;
 
258
 
 
259
    m_row_exists= true;
 
260
  }
 
261
}
 
262
 
 
263
int table_session_connect::read_row_values(TABLE *table,
 
264
                                         unsigned char *buf,
 
265
                                         Field **fields,
 
266
                                         bool read_all)
 
267
{
 
268
  Field *f;
 
269
 
 
270
  if (unlikely(!m_row_exists))
 
271
    return HA_ERR_RECORD_DELETED;
 
272
 
 
273
  /* Set the null bits */
 
274
  DBUG_ASSERT(table->s->null_bytes == 1);
 
275
  buf[0]= 0;
 
276
 
 
277
  for (; (f= *fields) ; fields++)
 
278
  {
 
279
    if (read_all || bitmap_is_set(table->read_set, f->field_index))
 
280
    {
 
281
      switch(f->field_index)
 
282
      {
 
283
      case FO_PROCESS_ID:
 
284
        if (m_row.m_process_id != 0)
 
285
          set_field_ulong(f, m_row.m_process_id);
 
286
        else
 
287
          f->set_null();
 
288
        break;
 
289
      case FO_ATTR_NAME:
 
290
        set_field_varchar_utf8(f, m_row.m_attr_name,
 
291
                               m_row.m_attr_name_length);
 
292
        break;
 
293
      case FO_ATTR_VALUE:
 
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);
 
297
        else
 
298
          f->set_null();
 
299
        break;
 
300
      case FO_ORDINAL_POSITION:
 
301
        set_field_ulong(f, m_row.m_ordinal_position);
 
302
        break;
 
303
      default:
 
304
        DBUG_ASSERT(false);
 
305
      }
 
306
    }
 
307
  }
 
308
  return 0;
 
309
}
 
310
 
 
311
bool
 
312
table_session_connect::thread_fits(PFS_thread *thread)
 
313
{
 
314
  return true;
 
315
}
 
316