25 #include "my_global.h" 
   33 #include "sql_get_diagnostics.h" 
   34 #include "sql_string.h" 
   38 #include "../sql/sql_yacc.h" 
   39 #include "../storage/perfschema/pfs_lex_token.h" 
   46 #define LEX_YYSTYPE YYSTYPE 
   66 bool flag_statements_digest= 
true;
 
   71 volatile uint32 digest_index= 1;
 
   74 static bool digest_hash_inited= 
false;
 
   94   statements_digest_stat_array=
 
   97   if (unlikely(statements_digest_stat_array == NULL))
 
  100   for (index= 0; index < digest_max; index++)
 
  109 void cleanup_digest(
void)
 
  112   pfs_free(statements_digest_stat_array);
 
  113   statements_digest_stat_array= NULL;
 
  117 static uchar *digest_hash_get_key(
const uchar *
entry, 
size_t *length,
 
  124   DBUG_ASSERT(typed_entry != NULL);
 
  125   digest= *typed_entry;
 
  126   DBUG_ASSERT(digest != NULL);
 
  129   return const_cast<uchar*
> (
reinterpret_cast<const uchar*
> (result));
 
  138 int init_digest_hash(
void)
 
  140   if ((! digest_hash_inited) && (digest_max > 0))
 
  143                  LF_HASH_UNIQUE, 0, 0, digest_hash_get_key,
 
  145     digest_hash.size= digest_max;
 
  146     digest_hash_inited= 
true;
 
  151 void cleanup_digest_hash(
void)
 
  153   if (digest_hash_inited)
 
  155     lf_hash_destroy(&digest_hash);
 
  156     digest_hash_inited= 
false;
 
  164     if (!digest_hash_inited)
 
  173                       PSI_digest_storage *digest_storage,
 
  174                       const char *schema_name,
 
  175                       uint schema_name_length)
 
  177   if (statements_digest_stat_array == NULL)
 
  180   if (digest_storage->m_byte_count <= 0)
 
  183   LF_PINS *pins= get_digest_hash_pins(thread);
 
  184   if (unlikely(pins == NULL))
 
  193   memset(& hash_key, 0, 
sizeof(hash_key));
 
  196                    (
char *) digest_storage->m_token_array,
 
  197                    digest_storage->m_byte_count);
 
  199   hash_key.m_schema_name_length= schema_name_length;
 
  200   if (schema_name_length > 0)
 
  201     memcpy(hash_key.m_schema_name, schema_name, schema_name_length);
 
  206   const uint retry_max= 3;
 
  210   ulonglong now= my_micro_time();
 
  216     (lf_hash_search(&digest_hash, pins,
 
  219   if (entry && (entry != MY_ERRPTR))
 
  223     pfs->m_last_seen= now;
 
  224     lf_hash_search_unpin(pins);
 
  228   lf_hash_search_unpin(pins);
 
  231   if (digest_index == 0)
 
  234     pfs= &statements_digest_stat_array[0];
 
  238     pfs->m_last_seen= now;
 
  243   if (safe_index >= digest_max)
 
  247     pfs= &statements_digest_stat_array[0];
 
  251     pfs->m_last_seen= now;
 
  256   pfs= &statements_digest_stat_array[safe_index];
 
  268   pfs->m_last_seen= now;
 
  270   res= lf_hash_insert(&digest_hash, pins, &pfs);
 
  271   if (likely(res == 0))
 
  279     if (++retry_count > retry_max)
 
  295   LF_PINS *pins= get_digest_hash_pins(thread);
 
  296   if (unlikely(pins == NULL))
 
  303     (lf_hash_search(&digest_hash, pins,
 
  306   if (entry && (entry != MY_ERRPTR))
 
  308     lf_hash_delete(&digest_hash, pins,
 
  311   lf_hash_search_unpin(pins);
 
  332 void reset_esms_by_digest()
 
  336   if (statements_digest_stat_array == NULL)
 
  339   PFS_thread *thread= PFS_thread::get_current_thread();
 
  340   if (unlikely(thread == NULL))
 
  344   for (index= 0; index < digest_max; index++)
 
  360 void get_digest_text(
char* digest_text, PSI_digest_storage* digest_storage)
 
  362   DBUG_ASSERT(digest_storage != NULL);
 
  363   bool truncated= 
false;
 
  364   int byte_count= digest_storage->m_byte_count;
 
  365   char *digest_output= digest_text;
 
  369   lex_token_string *tok_data;
 
  373   if (byte_count <= 0 || byte_count > PSI_MAX_DIGEST_STORAGE_SIZE)
 
  380   const CHARSET_INFO *from_cs= get_charset(digest_storage->m_charset_number, MYF(0));
 
  397   const uint max_converted_size= PSI_MAX_DIGEST_STORAGE_SIZE * 4;
 
  398   char id_buffer[max_converted_size];
 
  401   bool convert_text= !my_charset_same(from_cs, to_cs);
 
  403   DBUG_ASSERT(byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
 
  405   while ((current_byte < byte_count) &&
 
  406          (bytes_available > 0) &&
 
  409     current_byte= 
read_token(digest_storage, current_byte, &tok);
 
  411     if (tok <= 0 || tok >= array_elements(lex_token_array))
 
  417     tok_data= &lex_token_array[tok];
 
  435           if (to_cs->mbmaxlen*id_len > max_converted_size)
 
  441           id_length= my_convert(id_buffer, max_converted_size, to_cs,
 
  442                                 id_ptr, id_len, from_cs, &err_cs);
 
  443           id_string= id_buffer;
 
  451         if (id_length == 0 || err_cs != 0)
 
  457         bytes_needed= id_length + (tok == IDENT ? 1 : 3);
 
  458         if (bytes_needed <= bytes_available)
 
  460           if (tok == IDENT_QUOTED)
 
  461             *digest_output++= 
'`';
 
  464             memcpy(digest_output, id_string, id_length);
 
  465             digest_output+= id_length;
 
  467           if (tok == IDENT_QUOTED)
 
  468             *digest_output++= 
'`';
 
  469           *digest_output++= 
' ';
 
  470           bytes_available-= bytes_needed;
 
  485       int tok_length= tok_data->m_token_length;
 
  486       bytes_needed= tok_length + 1;
 
  488       if (bytes_needed <= bytes_available)
 
  490         strncpy(digest_output, tok_data->m_token_string, tok_length);
 
  491         digest_output+= tok_length;
 
  492         *digest_output++= 
' ';
 
  493         bytes_available-= bytes_needed;
 
  504   if (digest_storage->m_full || truncated)
 
  506     strcpy(digest_output, 
"...");
 
  510   *digest_output= 
'\0';
 
  513 static inline uint peek_token(
const PSI_digest_storage *digest, 
int index)
 
  516   DBUG_ASSERT(index >= 0);
 
  517   DBUG_ASSERT(index + PFS_SIZE_OF_A_TOKEN <= digest->m_byte_count);
 
  518   DBUG_ASSERT(digest->m_byte_count <=  PSI_MAX_DIGEST_STORAGE_SIZE);
 
  520   token= ((digest->m_token_array[index + 1])<<8) | digest->m_token_array[
index];
 
  528 static inline void peek_last_two_tokens(
const PSI_digest_storage* digest_storage,
 
  529                                         int last_id_index, uint *t1, uint *t2)
 
  531   int byte_count= digest_storage->m_byte_count;
 
  532   int peek_index= byte_count - PFS_SIZE_OF_A_TOKEN;
 
  534   if (last_id_index <= peek_index)
 
  537     *t1= peek_token(digest_storage, peek_index);
 
  539     peek_index-= PFS_SIZE_OF_A_TOKEN;
 
  540     if (last_id_index <= peek_index)
 
  543       *t2= peek_token(digest_storage, peek_index);
 
  557 struct PSI_digest_locker* pfs_digest_start_v1(PSI_statement_locker *locker)
 
  559   PSI_statement_locker_state *statement_state;
 
  560   statement_state= 
reinterpret_cast<PSI_statement_locker_state*
> (locker);
 
  561   DBUG_ASSERT(statement_state != NULL);
 
  563   if (statement_state->m_discarded)
 
  568     PSI_digest_locker_state *digest_state;
 
  569     digest_state= &statement_state->m_digest_state;
 
  570     return reinterpret_cast<PSI_digest_locker*
> (digest_state);
 
  576 PSI_digest_locker* pfs_digest_add_token_v1(PSI_digest_locker *locker,
 
  578                                            OPAQUE_LEX_YYSTYPE *yylval)
 
  580   PSI_digest_locker_state *state= NULL;
 
  581   PSI_digest_storage      *digest_storage= NULL;
 
  583   state= 
reinterpret_cast<PSI_digest_locker_state*
> (locker);
 
  584   DBUG_ASSERT(state != NULL);
 
  586   digest_storage= &state->m_digest_storage;
 
  592   if (digest_storage->m_full || token == END_OF_INPUT)
 
  619       token= TOK_PFS_GENERIC_VALUE;
 
  624       peek_last_two_tokens(digest_storage, state->m_last_id_index,
 
  625                            &last_token, &last_token2);
 
  627       if ((last_token2 == TOK_PFS_GENERIC_VALUE ||
 
  628            last_token2 == TOK_PFS_GENERIC_VALUE_LIST ||
 
  629            last_token2 == NULL_SYM) &&
 
  641         digest_storage->m_byte_count-= 2*PFS_SIZE_OF_A_TOKEN;
 
  642         token= TOK_PFS_GENERIC_VALUE_LIST;
 
  652       peek_last_two_tokens(digest_storage, state->m_last_id_index,
 
  653                            &last_token, &last_token2);
 
  655       if (last_token == TOK_PFS_GENERIC_VALUE &&
 
  663         digest_storage->m_byte_count-= 2*PFS_SIZE_OF_A_TOKEN;
 
  664         token= TOK_PFS_ROW_SINGLE_VALUE;
 
  667         peek_last_two_tokens(digest_storage, state->m_last_id_index,
 
  668                              &last_token, &last_token2);
 
  670         if ((last_token2 == TOK_PFS_ROW_SINGLE_VALUE ||
 
  671              last_token2 == TOK_PFS_ROW_SINGLE_VALUE_LIST) &&
 
  683           digest_storage->m_byte_count-= 2*PFS_SIZE_OF_A_TOKEN;
 
  684           token= TOK_PFS_ROW_SINGLE_VALUE_LIST;
 
  687       else if (last_token == TOK_PFS_GENERIC_VALUE_LIST &&
 
  695         digest_storage->m_byte_count-= 2*PFS_SIZE_OF_A_TOKEN;
 
  696         token= TOK_PFS_ROW_MULTIPLE_VALUE;
 
  699         peek_last_two_tokens(digest_storage, state->m_last_id_index,
 
  700                              &last_token, &last_token2);
 
  702         if ((last_token2 == TOK_PFS_ROW_MULTIPLE_VALUE ||
 
  703              last_token2 == TOK_PFS_ROW_MULTIPLE_VALUE_LIST) &&
 
  715           digest_storage->m_byte_count-= 2*PFS_SIZE_OF_A_TOKEN;
 
  716           token= TOK_PFS_ROW_MULTIPLE_VALUE_LIST;
 
  728       LEX_YYSTYPE *lex_token= (LEX_YYSTYPE*) yylval;
 
  729       char *yytext= lex_token->lex_str.str;
 
  730       int yylen= lex_token->lex_str.length;
 
  736       state->m_last_id_index= digest_storage->m_byte_count;