List:Commits« Previous MessageNext Message »
From:Marc Alff Date:February 23 2012 11:27pm
Subject:bzr push into mysql-trunk-wl5767 branch (marc.alff:3445 to 3446)
View as plain text  
 3446 Marc Alff	2012-02-24
      Code cleanup, continued

    modified:
      include/mysql/psi/psi.h
      include/mysql/psi/psi_abi_v1.h.pp
      mysql-test/suite/perfschema/r/statement_digest_long_query.result
      storage/perfschema/pfs.cc
      storage/perfschema/pfs_digest.cc
      storage/perfschema/pfs_digest.h
      storage/perfschema/pfs_engine_table.cc
      storage/perfschema/pfs_instr.cc
      storage/perfschema/pfs_instr.h
      storage/perfschema/table_esms_by_digest.cc
      storage/perfschema/table_events_statements.cc
      storage/perfschema/table_events_statements.h
      storage/perfschema/table_helper.cc
 3445 Marc Alff	2012-02-22 [merge]
      Merge mysql-trunk --> mysql-trunk-wl5767

    added:
      mysql-test/r/mysql_client_test_embedded.result
      mysql-test/t/mysql_client_test_embedded.cnf
      mysql-test/t/mysql_client_test_embedded.test
    modified:
      client/sql_string.cc
      client/sql_string.h
      mysql-test/r/func_group.result
      mysql-test/r/func_set.result
      mysql-test/r/group_by.result
      mysql-test/r/join_cache_bka.result
      mysql-test/r/join_cache_bka_nixbnl.result
      mysql-test/r/join_cache_bkaunique.result
      mysql-test/r/join_cache_bnl.result
      mysql-test/r/join_cache_nojb.result
      mysql-test/r/select_found.result
      mysql-test/r/subquery_mat_none.result
      mysql-test/suite/innodb/t/innodb_bug34300.test
      mysql-test/suite/opt_trace/r/bugs_no_prot_all.result
      mysql-test/suite/opt_trace/r/bugs_no_prot_none.result
      mysql-test/suite/opt_trace/r/bugs_ps_prot_all.result
      mysql-test/suite/opt_trace/r/bugs_ps_prot_none.result
      mysql-test/suite/opt_trace/r/range_no_prot.result
      mysql-test/suite/opt_trace/r/range_ps_prot.result
      mysql-test/t/disabled.def
      mysql-test/t/func_group.test
      mysql-test/t/func_set.test
      sql/item_strfunc.cc
      sql/item_strfunc.h
      sql/log_event.cc
      sql/mysqld.cc
      sql/rpl_handler.cc
      sql/sql_class.cc
      sql/sql_class.h
      sql/sql_executor.cc
      sql/sql_list.h
      sql/sql_load.cc
      sql/sql_optimizer.cc
      sql/sql_optimizer.h
      sql/sql_select.cc
      sql/sql_show.cc
      sql/sql_string.cc
      sql/sql_string.h
      sql/sys_vars.cc
      tests/mysql_client_test.c
      unittest/gunit/opt_range-t.cc
=== modified file 'include/mysql/psi/psi.h'
--- a/include/mysql/psi/psi.h	2012-02-21 18:27:58 +0000
+++ b/include/mysql/psi/psi.h	2012-02-23 23:27:02 +0000
@@ -958,7 +958,7 @@ struct PSI_digest_storage
 {
   my_bool m_full;
   int m_byte_count;
-  char m_token_array[PSI_MAX_DIGEST_STORAGE_SIZE];
+  unsigned char m_token_array[PSI_MAX_DIGEST_STORAGE_SIZE];
 };
 typedef struct PSI_digest_storage PSI_digest_storage;
 

=== modified file 'include/mysql/psi/psi_abi_v1.h.pp'
--- a/include/mysql/psi/psi_abi_v1.h.pp	2012-02-21 18:27:58 +0000
+++ b/include/mysql/psi/psi_abi_v1.h.pp	2012-02-23 23:27:02 +0000
@@ -243,7 +243,7 @@ struct PSI_digest_storage
 {
   my_bool m_full;
   int m_byte_count;
-  char m_token_array[1024];
+  unsigned char m_token_array[1024];
 };
 typedef struct PSI_digest_storage PSI_digest_storage;
 struct PSI_digest_locker_state

=== modified file 'mysql-test/suite/perfschema/r/statement_digest_long_query.result'
--- a/mysql-test/suite/perfschema/r/statement_digest_long_query.result	2012-02-21 18:27:58 +0000
+++ b/mysql-test/suite/perfschema/r/statement_digest_long_query.result	2012-02-23 23:27:02 +0000
@@ -9,4 +9,4 @@ SELECT 1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1
 SELECT digest, digest_text, count_star FROM events_statements_summary_by_digest;
 digest	digest_text	count_star
 4b653d085960e08d033c67cb23748eb3	TRUNCATE TABLE events_statements_summary_by_digest  	1
-2dd9d11451985e288ffd7f2cdefc28e2	SELECT ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + !
 ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? +  ...	1
+2dd9d11451985e288ffd7f2cdefc28e2	SELECT ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + !
 ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ? + ...	1

=== modified file 'storage/perfschema/pfs.cc'
--- a/storage/perfschema/pfs.cc	2012-02-21 18:27:58 +0000
+++ b/storage/perfschema/pfs.cc	2012-02-23 23:27:02 +0000
@@ -39,7 +39,6 @@
 #include "pfs_setup_object.h"
 #include "sql_error.h"
 #include "sp_head.h"
-#include "my_md5.h"
 #include "pfs_digest.h"
 
 /**
@@ -4527,16 +4526,15 @@ static void end_statement_v1(PSI_stateme
     wait_time= timer_end - state->m_timer_start;
   }
 
-  PFS_statement_stat *event_name_array= NULL;
+  PFS_statement_stat *event_name_array;
   uint index= klass->m_event_name_index;
-  PFS_statement_stat *stat= NULL;
+  PFS_statement_stat *stat;
   
   /*
    Capture statement stats by digest.
   */
   PSI_digest_storage *digest_storage= NULL;
   PFS_statement_stat *digest_stat= NULL;
-  PFS_statements_digest_stat* digest_stat_ptr= NULL;
 
   if (flags & STATE_FLAG_THREAD)
   {
@@ -4546,16 +4544,14 @@ static void end_statement_v1(PSI_stateme
     /* Aggregate to EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME */
     stat= & event_name_array[index];
 
-    /* Set digest stat. */
-    digest_storage= &state->m_digest_state.m_digest_storage;
-
-    /* 
-      Populate PFS_statements_digest_stat with computed digest information.
-    */
-    digest_stat_ptr= find_or_create_digest(thread, digest_storage);
-    if(digest_stat_ptr)
+    if (flags & STATE_FLAG_DIGEST)
     {
-      digest_stat= &(digest_stat_ptr->m_stat);
+      digest_storage= &state->m_digest_state.m_digest_storage;
+
+      /* 
+        Populate PFS_statements_digest_stat with computed digest information.
+      */
+      digest_stat= find_or_create_digest(thread, digest_storage);
     }
 
     if (flags & STATE_FLAG_EVENT)
@@ -4590,9 +4586,7 @@ static void end_statement_v1(PSI_stateme
       pfs->m_timer_end= timer_end;
       pfs->m_end_event_id= thread->m_event_id;
 
-      PSI_digest_storage *from= & state->m_digest_state.m_digest_storage;
-
-      if (from->m_byte_count > 0)
+      if (flags & STATE_FLAG_DIGEST)
       {
         /*
           The following columns in events_statement_current:
@@ -4600,7 +4594,7 @@ static void end_statement_v1(PSI_stateme
           - DIGEST_TEXT
           are computed from the digest storage.
         */
-        digest_copy(& pfs->m_digest_storage, from);
+        digest_copy(& pfs->m_digest_storage, digest_storage);
       }
 
       if (flag_events_statements_history)
@@ -4614,20 +4608,20 @@ static void end_statement_v1(PSI_stateme
   }
   else
   {
-    PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
-
-    if(thread)
+    if (flags & STATE_FLAG_DIGEST)
     {
-      /* Set digest stat. */
-      digest_storage= &state->m_digest_state.m_digest_storage;
+      PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS);
 
-      /* 
-        Populate PFS_statements_digest_stat with computed digest information.
-      */
-      digest_stat_ptr= find_or_create_digest(thread, digest_storage);
-      if(digest_stat_ptr)
+      /* An instrumented thread is required, for LF_PINS. */
+      if (thread != NULL)
       {
-        digest_stat= &(digest_stat_ptr->m_stat);
+        /* Set digest stat. */
+        digest_storage= &state->m_digest_state.m_digest_storage;
+
+        /* 
+          Populate PFS_statements_digest_stat with computed digest information.
+        */
+        digest_stat= find_or_create_digest(thread, digest_storage);
       }
     }
 
@@ -4664,7 +4658,7 @@ static void end_statement_v1(PSI_stateme
   stat->m_no_index_used+= state->m_no_index_used;
   stat->m_no_good_index_used+= state->m_no_good_index_used;
 
-  if(digest_stat)
+  if (digest_stat != NULL)
   {
     if (flags & STATE_FLAG_TIMED)
     {
@@ -4693,14 +4687,14 @@ static void end_statement_v1(PSI_stateme
     digest_stat->m_no_good_index_used+= state->m_no_good_index_used;
   }
 
-  switch(da->status())
+  switch (da->status())
   {
     case Diagnostics_area::DA_EMPTY:
       break;
     case Diagnostics_area::DA_OK:
       stat->m_rows_affected+= da->affected_rows();
       stat->m_warning_count+= da->statement_warn_count();
-      if(digest_stat)
+      if (digest_stat != NULL)
       {
         digest_stat->m_rows_affected+= da->affected_rows();
         digest_stat->m_warning_count+= da->statement_warn_count();
@@ -4708,14 +4702,14 @@ static void end_statement_v1(PSI_stateme
       break;
     case Diagnostics_area::DA_EOF:
       stat->m_warning_count+= da->statement_warn_count();
-      if(digest_stat)
+      if (digest_stat != NULL)
       {
         digest_stat->m_warning_count+= da->statement_warn_count();
       }
       break;
     case Diagnostics_area::DA_ERROR:
       stat->m_error_count++;
-      if(digest_stat)
+      if (digest_stat != NULL)
       {
         digest_stat->m_error_count++;
       }

=== modified file 'storage/perfschema/pfs_digest.cc'
--- a/storage/perfschema/pfs_digest.cc	2012-02-21 18:27:58 +0000
+++ b/storage/perfschema/pfs_digest.cc	2012-02-23 23:27:02 +0000
@@ -66,7 +66,7 @@ bool flag_statements_digest= true;
   Current index in Stat array where new record is to be inserted.
   index 0 is reserved for "all else" case when entire array is full.
 */
-unsigned int digest_index= 1;
+volatile uint32 digest_index= 1;
 
 static LF_HASH digest_hash;
 static bool digest_hash_inited= false;
@@ -79,8 +79,6 @@ int init_digest(const PFS_global_param *
 {
   unsigned int index;
 
-  digest_max= param->m_digest_sizing;
-
   /* 
     Allocate memory for statements_digest_stat_array based on 
     performance_schema_digests_size values
@@ -93,13 +91,15 @@ int init_digest(const PFS_global_param *
   statements_digest_stat_array=
     PFS_MALLOC_ARRAY(digest_max, PFS_statements_digest_stat,
                      MYF(MY_ZEROFILL));
+  if (unlikely(statements_digest_stat_array == NULL))
+    return 1;
    
   for (index= 0; index < digest_max; index++)
   {
-    statements_digest_stat_array[index].reset();
+    statements_digest_stat_array[index].reset_data();
   }
 
-  return (statements_digest_stat_array ? 0 : 1);
+  return 0;
 }
 
 /** Cleanup table EVENTS_STATEMENTS_SUMMARY_BY_DIGEST. */
@@ -164,7 +164,7 @@ static LF_PINS* get_digest_hash_pins(PFS
   return thread->m_digest_hash_pins;
 }
 
-PFS_statements_digest_stat* 
+PFS_statement_stat* 
 find_or_create_digest(PFS_thread* thread,
                       PSI_digest_storage* digest_storage)
 {
@@ -180,8 +180,8 @@ find_or_create_digest(PFS_thread* thread
 
   /* Compute MD5 Hash of the tokens received. */
   PFS_digest_hash md5;
-  compute_md5_hash((char*) md5.m_md5,
-                   digest_storage->m_token_array,
+  compute_md5_hash((char *) md5.m_md5,
+                   (char *) digest_storage->m_token_array,
                    digest_storage->m_byte_count);
 
   unsigned char* hash_key= md5.m_md5;
@@ -196,21 +196,45 @@ find_or_create_digest(PFS_thread* thread
     (lf_hash_search(&digest_hash, pins,
                     hash_key, PFS_MD5_SIZE));
 
-  if(!entry)
+  if (entry && (entry != MY_ERRPTR))
+  {
+    /* If digest already exists, update stats and return. */
+    pfs= *entry;
+    pfs->m_last_seen= now;
+    lf_hash_search_unpin(pins);
+    return & pfs->m_stat;
+  }
+
+  if (entry == NULL)
   {
-    if(digest_index == 0)
+    /* Dirty read of digest_index */
+    if (digest_index == 0)
     {
       /*  digest_stat array is full. Add stat at index 0 and return. */
       pfs= &statements_digest_stat_array[0];
 
-      if(pfs->m_first_seen == 0)
+      if (pfs->m_first_seen == 0)
         pfs->m_first_seen= now;
       pfs->m_last_seen= now;
-      return pfs;
+      return & pfs->m_stat;
+    }
+
+    ulong safe_index;
+    safe_index= PFS_atomic::add_u32(& digest_index, 1);
+    if (safe_index >= digest_max)
+    {
+      /* The digest array is now full. */
+      digest_index= 0;
+      pfs= &statements_digest_stat_array[0];
+
+      if (pfs->m_first_seen == 0)
+        pfs->m_first_seen= now;
+      pfs->m_last_seen= now;
+      return & pfs->m_stat;
     }
 
     /* Add a new record in digest stat array. */
-    pfs= &statements_digest_stat_array[digest_index];
+    pfs= &statements_digest_stat_array[safe_index];
     
     /* Copy digest hash/LF Hash search key. */
     memcpy(pfs->m_digest_hash.m_md5, md5.m_md5, PFS_MD5_SIZE);
@@ -224,44 +248,29 @@ find_or_create_digest(PFS_thread* thread
     pfs->m_first_seen= now;
     pfs->m_last_seen= now;
     
-    digest_index++;
-    
-    if(digest_index % digest_max == 0)
-    {
-      /* 
-        Digest stat array is full. Now stat for all further 
-        entries will go into index 0.
-      */
-      digest_index= 0;
-    }
-    
-    /* Add this new digest into LF_HASH */
-    int res;
-    res= lf_hash_insert(&digest_hash, pins, &pfs);
-    lf_hash_search_unpin(pins);
-    if (res > 0)
-    {
-      /* TODO: Handle ERROR CONDITION */
-      return NULL;
-    }
-    return pfs;
-  }
-  else if (entry && (entry != MY_ERRPTR))
-  {
-    /* If digest already exists, update stats and return. */
-    pfs= *entry;
-    pfs->m_last_seen= now;
+    /*
+      Add this new digest into LF_HASH.
+      - duplicate key errors are ignored
+        (not supposed to happen because of the search pin)
+      - OOM errors are ignored
+        (nothing that can be done)
+      If inserting in the hash fails, we might end
+      with 2 entries for the same digest, which is tolerated.
+    */
+    (void) lf_hash_insert(&digest_hash, pins, &pfs);
     lf_hash_search_unpin(pins);
-    return pfs;
+
+    return & pfs->m_stat;
   }
 
+  lf_hash_search_unpin(pins);
   return NULL;
 }
  
 void purge_digest(PFS_thread* thread, unsigned char* hash_key)
 {
   LF_PINS *pins= get_digest_hash_pins(thread);
-  if(unlikely(pins == NULL))
+  if (unlikely(pins == NULL))
     return;
 
   PFS_statements_digest_stat **entry;
@@ -271,7 +280,7 @@ void purge_digest(PFS_thread* thread, un
     (lf_hash_search(&digest_hash, pins,
                     hash_key, PFS_MD5_SIZE));
 
-  if(entry && (entry != MY_ERRPTR))
+  if (entry && (entry != MY_ERRPTR))
   { 
     lf_hash_delete(&digest_hash, pins,
                    hash_key, PFS_MD5_SIZE);
@@ -280,30 +289,39 @@ void purge_digest(PFS_thread* thread, un
   return;
 }
 
-void PFS_statements_digest_stat::reset()
+void PFS_statements_digest_stat::reset_data()
 {
-  PFS_thread *thread= PFS_thread::get_current_thread();
-  if (unlikely(thread == NULL))
-      return;
-
   digest_reset(& m_digest_storage);
   m_stat.reset();
-  purge_digest(thread, m_digest_hash.m_md5);
   m_first_seen= 0;
   m_last_seen= 0;
 }
 
+void PFS_statements_digest_stat::reset_index(PFS_thread *thread)
+{
+  /* Only remove entries that exists in the HASH index. */
+  if (m_digest_storage.m_byte_count > 0)
+  {
+    purge_digest(thread, m_digest_hash.m_md5);
+  }
+}
+
 void reset_esms_by_digest()
 {
   uint index;
 
-  if(statements_digest_stat_array == NULL)
+  if (statements_digest_stat_array == NULL)
+    return;
+
+  PFS_thread *thread= PFS_thread::get_current_thread();
+  if (unlikely(thread == NULL))
     return;
 
   /* Reset statements_digest_stat_array. */
   for (index= 0; index < digest_max; index++)
   {
-    statements_digest_stat_array[index].reset();
+    statements_digest_stat_array[index].reset_index(thread);
+    statements_digest_stat_array[index].reset_data();
   }
 
   /* 
@@ -318,43 +336,72 @@ void reset_esms_by_digest()
 */
 void get_digest_text(char* digest_text, PSI_digest_storage* digest_storage)
 {
+  bool truncated= false;
+  int byte_count= digest_storage->m_byte_count;
+  int need_bytes;
   uint tok= 0;
+  char *id_string;
+  int id_length;
   int current_byte= 0;
-  char *digest_text_start= digest_text;
   lex_token_string *tok_data;
-  char* token_array= digest_storage->m_token_array;
-  int byte_count= digest_storage->m_byte_count;
-  
-  /* -4 is to make sure extra space for ... and a '\0' at the end. */
+  /* -4 is to make sure extra space for '...' and a '\0' at the end. */
   int available_bytes_to_write= COL_DIGEST_TEXT_SIZE - 4;
 
   DBUG_ASSERT(byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
 
-  while(current_byte < byte_count &&
-        available_bytes_to_write > 0)
+  while ((current_byte < byte_count) &&
+         (available_bytes_to_write > 0) &&
+         (! truncated))
   {
-    read_token(&tok, &current_byte, token_array);
+    current_byte= read_token(digest_storage, current_byte, &tok);
     tok_data= & lex_token_array[tok];
     
     switch (tok)
     {
     /* All identifiers are printed with their name. */
     case IDENT:
-      read_identifier(&digest_text, &current_byte,
-                      token_array, (uint)available_bytes_to_write,1);
-      *digest_text= ' ';
-      digest_text++;
+      current_byte= read_identifier(digest_storage, current_byte,
+                                    & id_string, & id_length);
+      need_bytes= id_length + 1; /* <id> space */
+      if (need_bytes <= available_bytes_to_write)
+      {
+        if (id_length > 0)
+        {
+          strncpy(digest_text, id_string, id_length);
+          digest_text+= id_length;
+        }
+        *digest_text= ' ';
+        digest_text++;
+        available_bytes_to_write-= need_bytes;
+      }
+      else
+      {
+        truncated= true;
+      }
       break;
     case IDENT_QUOTED:
-      *digest_text= '`';
-      digest_text++;
-      available_bytes_to_write--;
-      read_identifier(&digest_text, &current_byte,
-                      token_array, (uint)available_bytes_to_write,2);
-      *digest_text= '`';
-      digest_text++;
-      *digest_text= ' ';
-      digest_text++;
+      current_byte= read_identifier(digest_storage, current_byte,
+                                    & id_string, & id_length);
+      need_bytes= id_length + 3; /* quote <id> quote space  */
+      if (need_bytes <= available_bytes_to_write)
+      {
+        *digest_text= '`';
+        digest_text++;
+        if (id_length > 0)
+        {
+          strncpy(digest_text, id_string, id_length);
+          digest_text+= id_length;
+        }
+        *digest_text= '`';
+        digest_text++;
+        *digest_text= ' ';
+        digest_text++;
+        available_bytes_to_write-= need_bytes;
+      }
+      else
+      {
+        truncated= true;
+      }
       break;
 
     /* Everything else is printed as is. */
@@ -362,27 +409,32 @@ void get_digest_text(char* digest_text, 
       /* 
         Make sure not to overflow digest_text buffer while writing
         this token string.
-        +/-1 is to make sure extra space for ' '.
+        +1 is to make sure extra space for ' '.
       */
-      int length= available_bytes_to_write >= tok_data->m_token_length+1?
-                                              tok_data->m_token_length:
-                                              available_bytes_to_write-1;
-      strncpy(digest_text,
-              tok_data->m_token_string,
-              length);
-      digest_text+= length;
-      *digest_text= ' ';
-      digest_text++;
-    }
+      int tok_length= tok_data->m_token_length;
+      need_bytes= tok_length + 1;
 
-    available_bytes_to_write-= digest_text - digest_text_start;
-    digest_text_start= digest_text;
+      if (need_bytes <= available_bytes_to_write)
+      {
+        strncpy(digest_text,
+                tok_data->m_token_string,
+                tok_length);
+        digest_text+= tok_length;
+        *digest_text= ' ';
+        digest_text++;
+        available_bytes_to_write-= need_bytes;
+      }
+      else
+      {
+        truncated= true;
+      }
+    }
   }
 
   /* Truncate digest text in case of long queries. */
-  if(digest_storage->m_full)
+  if (digest_storage->m_full || truncated)
   {
-    strcpy(digest_text,"...");
+    strcpy(digest_text, "...");
     digest_text+= 3;
   }
 
@@ -391,13 +443,13 @@ void get_digest_text(char* digest_text, 
 
 static inline uint peek_token(const PSI_digest_storage *digest, int index)
 {
-  unsigned short sh;
+  uint token;
   DBUG_ASSERT(index >= 0);
   DBUG_ASSERT(index + PFS_SIZE_OF_A_TOKEN <= digest->m_byte_count);
   DBUG_ASSERT(digest->m_byte_count <=  PSI_MAX_DIGEST_STORAGE_SIZE);
 
-  sh= ((0x00ff & digest->m_token_array[index + 1])<<8) | (0x00ff & digest->m_token_array[index]);
-  return (uint) sh;
+  token= ((digest->m_token_array[index + 1])<<8) | digest->m_token_array[index];
+  return token;
 }
 
 /**
@@ -419,7 +471,7 @@ static inline void peek_last_two_tokens(
     *t1= TOK_PFS_UNUSED;
   }
 
-  if(last_id_index <= byte_count - 2*PFS_SIZE_OF_A_TOKEN)
+  if (last_id_index <= byte_count - 2*PFS_SIZE_OF_A_TOKEN)
   {
     /* Take 2nd token from last. */
     *t2= peek_token(digest_storage, byte_count - 2 * PFS_SIZE_OF_A_TOKEN);
@@ -430,8 +482,6 @@ static inline void peek_last_two_tokens(
   }
 }
 
-
-
 struct PSI_digest_locker* pfs_digest_start_v1(PSI_statement_locker *locker)
 {
   PSI_statement_locker_state *statement_state;
@@ -463,12 +513,8 @@ PSI_digest_locker* pfs_digest_add_token_
 
   digest_storage= &state->m_digest_storage;
 
-  if( PSI_MAX_DIGEST_STORAGE_SIZE - digest_storage->m_byte_count <
-      PFS_SIZE_OF_A_TOKEN)
-  {
-    digest_storage->m_full= true;
+  if (digest_storage->m_full)
     return NULL;
-  }
 
   /* 
     Take last_token 2 tokens collected till now. These tokens will be used
@@ -523,8 +569,8 @@ PSI_digest_locker* pfs_digest_add_token_
     }
     case ')':
     {
-      if(last_token == TOK_PFS_GENERIC_VALUE &&
-         last_token2 == '(') 
+      if (last_token == TOK_PFS_GENERIC_VALUE &&
+          last_token2 == '(') 
       { 
         /*
           REDUCE:
@@ -535,11 +581,12 @@ PSI_digest_locker* pfs_digest_add_token_
         token= TOK_PFS_ROW_SINGLE_VALUE;
       
         /* Read last two tokens again */
-        peek_last_two_tokens(digest_storage, state->m_last_id_index, &last_token, &last_token2);
+        peek_last_two_tokens(digest_storage, state->m_last_id_index,
+                             &last_token, &last_token2);
 
-        if((last_token2 == TOK_PFS_ROW_SINGLE_VALUE ||
-            last_token2 == TOK_PFS_ROW_SINGLE_VALUE_LIST) &&
-           (last_token == ','))
+        if ((last_token2 == TOK_PFS_ROW_SINGLE_VALUE ||
+             last_token2 == TOK_PFS_ROW_SINGLE_VALUE_LIST) &&
+            (last_token == ','))
         {
           /*
             REDUCE:
@@ -554,8 +601,8 @@ PSI_digest_locker* pfs_digest_add_token_
           token= TOK_PFS_ROW_SINGLE_VALUE_LIST;
         }
       }
-      else if(last_token == TOK_PFS_GENERIC_VALUE_LIST &&
-              last_token2 == '(') 
+      else if (last_token == TOK_PFS_GENERIC_VALUE_LIST &&
+               last_token2 == '(') 
       {
         /*
           REDUCE:
@@ -566,11 +613,12 @@ PSI_digest_locker* pfs_digest_add_token_
         token= TOK_PFS_ROW_MULTIPLE_VALUE;
 
         /* Read last two tokens again */
-        peek_last_two_tokens(digest_storage, state->m_last_id_index, &last_token, &last_token2);
+        peek_last_two_tokens(digest_storage, state->m_last_id_index,
+                             &last_token, &last_token2);
 
-        if((last_token2 == TOK_PFS_ROW_MULTIPLE_VALUE ||
-            last_token2 == TOK_PFS_ROW_MULTIPLE_VALUE_LIST) &&
-           (last_token == ','))
+        if ((last_token2 == TOK_PFS_ROW_MULTIPLE_VALUE ||
+             last_token2 == TOK_PFS_ROW_MULTIPLE_VALUE_LIST) &&
+            (last_token == ','))
         {
           /*
             REDUCE:
@@ -598,11 +646,8 @@ PSI_digest_locker* pfs_digest_add_token_
       char *yytext= lex_token->lex_str.str;
       int yylen= lex_token->lex_str.length;
 
-      /* Add this token to digest storage. */
-      store_token(digest_storage, token);
-
-      /* Add this identifier's length and string to digest storage. */
-      store_identifier(digest_storage, yylen, yytext);
+      /* Add this token and identifier string to digest storage. */
+      store_token_identifier(digest_storage, token, yylen, yytext);
 
       /* Update the index of last identifier found. */
       state->m_last_id_index= digest_storage->m_byte_count;

=== modified file 'storage/perfschema/pfs_digest.h'
--- a/storage/perfschema/pfs_digest.h	2012-02-21 18:27:58 +0000
+++ b/storage/perfschema/pfs_digest.h	2012-02-23 23:27:02 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -28,8 +28,6 @@
 #define PFS_SIZE_OF_A_TOKEN 2
 
 extern bool flag_statements_digest;
-extern unsigned int statements_digest_size;
-extern unsigned int digest_index;
 extern ulong digest_max;
 struct PFS_thread;
 
@@ -68,7 +66,10 @@ struct PFS_statements_digest_stat
   ulonglong m_first_seen;
   ulonglong m_last_seen;
 
-  void reset();
+  /** Reset data for this record. */
+  void reset_data();
+  /** Reset data and remove index for this record. */
+  void reset_index(PFS_thread *thread);
 };
 
 int init_digest(const PFS_global_param *param);
@@ -76,8 +77,8 @@ void cleanup_digest();
 
 int init_digest_hash(void);
 void cleanup_digest_hash(void);
-PFS_statements_digest_stat* find_or_create_digest(PFS_thread*,
-                                                  PSI_digest_storage*);
+PFS_statement_stat* find_or_create_digest(PFS_thread*,
+                                          PSI_digest_storage*);
 
 void get_digest_text(char* digest_text, PSI_digest_storage*);
 
@@ -101,29 +102,41 @@ static inline void digest_reset(PSI_dige
 
 static inline void digest_copy(PSI_digest_storage *to, const PSI_digest_storage *from)
 {
-  to->m_full= from->m_full;
-  to->m_byte_count= from->m_byte_count;
-  DBUG_ASSERT(to->m_byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
-  memcpy(to->m_token_array, from->m_token_array, to->m_byte_count);
+  if (from->m_byte_count > 0)
+  {
+    to->m_full= from->m_full;
+    to->m_byte_count= from->m_byte_count;
+    DBUG_ASSERT(to->m_byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
+    memcpy(to->m_token_array, from->m_token_array, to->m_byte_count);
+  }
+  else
+  {
+    DBUG_ASSERT(! from->m_full);
+    DBUG_ASSERT(from->m_byte_count == 0);
+    to->m_full= false;
+    to->m_byte_count= 0;
+  }
 }
 
 /** 
   Function to read a single token from token array.
 */
-inline void read_token(uint *tok, int *index, char *src)
+inline int read_token(PSI_digest_storage *digest_storage,
+                      int index, uint *tok)
 {
-  unsigned short sh;
-  int remaining_bytes= PSI_MAX_DIGEST_STORAGE_SIZE - *index;
-  DBUG_ASSERT(remaining_bytes >= 0);
-
-  /* Make sure we have enough space to read a token from.
-   */
-  if(remaining_bytes >= PFS_SIZE_OF_A_TOKEN)
-  {
-    sh= ((0x00ff & src[*index + 1])<<8) | (0x00ff & src[*index]);
-    *tok= (uint)(sh);
-    *index= *index + PFS_SIZE_OF_A_TOKEN;
+  DBUG_ASSERT(index <= digest_storage->m_byte_count);
+  DBUG_ASSERT(digest_storage->m_byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
+
+  if (index + PFS_SIZE_OF_A_TOKEN <= digest_storage->m_byte_count)
+  {
+    unsigned char *src= & digest_storage->m_token_array[index];
+    *tok= src[0] | (src[1] << 8);
+    return index + PFS_SIZE_OF_A_TOKEN;
   }
+
+  /* The input byte stream is exhausted. */
+  *tok= 0;
+  return PSI_MAX_DIGEST_STORAGE_SIZE + 1;
 }
 
 /**
@@ -131,78 +144,76 @@ inline void read_token(uint *tok, int *i
 */
 inline void store_token(PSI_digest_storage* digest_storage, uint token)
 {
-  char* dest= digest_storage->m_token_array;
-  int* index= &digest_storage->m_byte_count;
-  unsigned short sh= (unsigned short)token;
-  int remaining_bytes= PSI_MAX_DIGEST_STORAGE_SIZE - *index;
-  DBUG_ASSERT(remaining_bytes >= 0);
-
-  /* Make sure we have enough space to write a token to. */
-  if(remaining_bytes >= PFS_SIZE_OF_A_TOKEN)
-  {
-    dest[*index]= (sh) & 0xff;
-    *index= *index + 1;
-    dest[*index]= (sh>>8) & 0xff;
-    *index= *index + 1;
+  DBUG_ASSERT(digest_storage->m_byte_count >= 0);
+  DBUG_ASSERT(digest_storage->m_byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
+
+  if (digest_storage->m_byte_count + PFS_SIZE_OF_A_TOKEN <= PSI_MAX_DIGEST_STORAGE_SIZE)
+  {
+    unsigned char* dest= & digest_storage->m_token_array[digest_storage->m_byte_count];
+    dest[0]= token & 0xff;
+    dest[1]= (token >> 8) & 0xff;
+    digest_storage->m_byte_count+= PFS_SIZE_OF_A_TOKEN; 
+  }
+  else
+  {
+    digest_storage->m_full= true;
   }
 }
 
 /**
   Function to read an identifier from token array.
 */
-inline void read_identifier(char **dest, int *index, char *src,
-                            uint available_bytes_to_write, uint offset)
+inline int read_identifier(PSI_digest_storage* digest_storage,
+                           int index, char ** id_string, int *id_length)
 {
-  uint length;
-  int remaining_bytes= PSI_MAX_DIGEST_STORAGE_SIZE - *index;
-  DBUG_ASSERT(remaining_bytes >= 0);
+  int new_index;
+  DBUG_ASSERT(index <= digest_storage->m_byte_count);
+  DBUG_ASSERT(digest_storage->m_byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
+
   /*
-    Read ID's length.
-    Make sure that space to read ID's length from, is available.
+    token + length + string are written in an atomic way,
+    so we do always expect a length + string here
   */
-  if(remaining_bytes >= PFS_SIZE_OF_A_TOKEN &&
-     available_bytes_to_write > offset)
-  {
-    read_token(&length, index, src);
-    /*
-      Make sure not to overflow digest_text buffer while writing
-      identifier name.
-      +/-offset is to make sure extra space for ''' and ' '.
-    */
-    length= available_bytes_to_write >= length+offset ?
-                                        length :
-                                        available_bytes_to_write-offset;
-    strncpy(*dest, src + *index, length);
-    *index= *index + length;
-    *dest= *dest + length;
-  }
+  unsigned char *src= & digest_storage->m_token_array[index];
+  uint length= src[0] | (src[1] << 8);
+  *id_string= (char *) (src + 2);
+  *id_length= length;
+
+  new_index= index + PFS_SIZE_OF_A_TOKEN + length;
+  DBUG_ASSERT(new_index <= digest_storage->m_byte_count);
+  return new_index;
 }
 
 /**
   Function to store an identifier in token array.
 */
-inline void store_identifier(PSI_digest_storage* digest_storage,
-                             uint id_length, char *id_name)
+inline void store_token_identifier(PSI_digest_storage* digest_storage,
+                                   uint token,
+                                   uint id_length, const char *id_name)
 {
-  char* dest= digest_storage->m_token_array;
-  int* index= &digest_storage->m_byte_count;
-  int remaining_bytes= PSI_MAX_DIGEST_STORAGE_SIZE - *index;
-  DBUG_ASSERT(remaining_bytes >= 0);
+  DBUG_ASSERT(digest_storage->m_byte_count >= 0);
+  DBUG_ASSERT(digest_storage->m_byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE);
 
-  /*
-    Store ID's length.
-    Make sure that space, to store ID's length, is available.
-  */
-  if(remaining_bytes >= PFS_SIZE_OF_A_TOKEN)
+  uint bytes_needed= 2 * PFS_SIZE_OF_A_TOKEN + id_length;
+  if (digest_storage->m_byte_count + bytes_needed <= PSI_MAX_DIGEST_STORAGE_SIZE)
+  {
+    unsigned char* dest= & digest_storage->m_token_array[digest_storage->m_byte_count];
+    /* Write the token */
+    dest[0]= token & 0xff;
+    dest[1]= (token >> 8) & 0xff;
+    /* Write the string length */
+    dest[2]= id_length & 0xff;
+    dest[3]= (id_length >> 8) & 0xff;
+    /* Write the string data */
+    if (id_length > 0)
+    {
+      strncpy((char *)(dest + 4), id_name, id_length);
+    }
+    digest_storage->m_byte_count+= bytes_needed; 
+  }
+  else
   {
-    /*
-       Make sure to store ID length/ID as per the space available.
-    */
-    remaining_bytes-= PFS_SIZE_OF_A_TOKEN;
-    id_length= id_length>(uint)remaining_bytes?(uint)remaining_bytes:id_length;
-    store_token(digest_storage, id_length);
-    strncpy(dest + *index, id_name, id_length);
-    *index= *index + id_length;
+    digest_storage->m_full= true;
   }
 }
 

=== modified file 'storage/perfschema/pfs_engine_table.cc'
--- a/storage/perfschema/pfs_engine_table.cc	2012-02-02 12:04:43 +0000
+++ b/storage/perfschema/pfs_engine_table.cc	2012-02-23 23:27:02 +0000
@@ -1322,11 +1322,11 @@ bool pfs_show_status(handlerton *hton, T
       break;
     case 135:
       name= "events_statements_summary_by_digest.row_count";
-      size= statement_digest_max;
+      size= digest_max;
       break;
     case 136:
       name= "events_statements_summary_by_digest.memory";
-      size= statement_digest_max * sizeof(PFS_statements_digest_stat);
+      size= digest_max * sizeof(PFS_statements_digest_stat);
       total_memory+= size;
       break;    
     /*

=== modified file 'storage/perfschema/pfs_instr.cc'
--- a/storage/perfschema/pfs_instr.cc	2012-01-09 09:09:26 +0000
+++ b/storage/perfschema/pfs_instr.cc	2012-02-23 23:27:02 +0000
@@ -82,8 +82,6 @@ uint statement_stack_max;
 ulong locker_lost= 0;
 /** Number of statement lost. @sa STATEMENT_STACK_SIZE. */
 ulong statement_lost= 0;
-/** Digest size **/
-uint statement_digest_max= 0; 
 
 /**
   Mutex instrumentation instances array.
@@ -421,8 +419,6 @@ int init_instruments(const PFS_global_pa
       global_instr_class_statements_array[index].reset();
   }
 
-  statement_digest_max= param->m_digest_sizing;
-
   return 0;
 }
 
@@ -1030,6 +1026,11 @@ void destroy_thread(PFS_thread *pfs)
     lf_hash_put_pins(pfs->m_host_hash_pins);
     pfs->m_host_hash_pins= NULL;
   }
+  if (pfs->m_digest_hash_pins)
+  {
+    lf_hash_put_pins(pfs->m_digest_hash_pins);
+    pfs->m_digest_hash_pins= NULL;
+  }
   pfs->m_lock.allocated_to_free();
 }
 

=== modified file 'storage/perfschema/pfs_instr.h'
--- a/storage/perfschema/pfs_instr.h	2012-01-09 09:09:26 +0000
+++ b/storage/perfschema/pfs_instr.h	2012-02-23 23:27:02 +0000
@@ -568,7 +568,6 @@ extern ulong events_stages_history_per_t
 extern ulong events_statements_history_per_thread;
 extern ulong locker_lost;
 extern ulong statement_lost;
-extern uint statement_digest_max;
 
 /* Exposing the data directly, for iterators. */
 

=== modified file 'storage/perfschema/table_esms_by_digest.cc'
--- a/storage/perfschema/table_esms_by_digest.cc	2012-02-16 14:58:41 +0000
+++ b/storage/perfschema/table_esms_by_digest.cc	2012-02-23 23:27:02 +0000
@@ -225,7 +225,7 @@ int table_esms_by_digest::rnd_next(void)
 {
   PFS_statements_digest_stat* digest_stat;
 
-  if(statements_digest_stat_array == NULL)
+  if (statements_digest_stat_array == NULL)
     return HA_ERR_END_OF_FILE;
 
   for (m_pos.set_at(&m_next_pos);
@@ -233,7 +233,7 @@ int table_esms_by_digest::rnd_next(void)
        m_pos.next())
   {
     digest_stat= &statements_digest_stat_array[m_pos.m_index];
-    if(digest_stat->m_first_seen != 0)
+    if (digest_stat->m_first_seen != 0)
     {
       make_row(digest_stat);
       m_next_pos.set_after(&m_pos);
@@ -249,13 +249,13 @@ table_esms_by_digest::rnd_pos(const void
 {
   PFS_statements_digest_stat* digest_stat;
 
-  if(statements_digest_stat_array == NULL)
+  if (statements_digest_stat_array == NULL)
     return HA_ERR_END_OF_FILE;
 
   set_position(pos);
   digest_stat= &statements_digest_stat_array[m_pos.m_index];
 
-  if(digest_stat->m_first_seen != 0)
+  if (digest_stat->m_first_seen != 0)
   {
     make_row(digest_stat);
     return 0;

=== modified file 'storage/perfschema/table_events_statements.cc'
--- a/storage/perfschema/table_events_statements.cc	2012-02-21 18:27:58 +0000
+++ b/storage/perfschema/table_events_statements.cc	2012-02-23 23:27:02 +0000
@@ -373,9 +373,9 @@ void table_events_statements_common::mak
   if (digest->m_byte_count > 0)
   {
     PFS_digest_hash md5;
-    compute_md5_hash((char*) md5.m_md5,
-                    digest->m_token_array,
-                    digest->m_byte_count);
+    compute_md5_hash((char *) md5.m_md5,
+                     (char *) digest->m_token_array,
+                     digest->m_byte_count);
 
     /* Generate the DIGEST string from the MD5 digest  */
     MD5_HASH_TO_STRING(md5.m_md5,
@@ -392,7 +392,6 @@ void table_events_statements_common::mak
     m_row.m_digest.m_digest_text_length= 0;
   }
 
-
   m_row_exists= true;
   return;
 }
@@ -468,17 +467,17 @@ int table_events_statements_common::read
           f->set_null();
         break;
       case 10: /* DIGEST */
-           if(m_row.m_digest.m_digest_length > 0)
-            set_field_varchar_utf8(f, m_row.m_digest.m_digest,
-                                   m_row.m_digest.m_digest_length);
-         else
+        if (m_row.m_digest.m_digest_length > 0)
+          set_field_varchar_utf8(f, m_row.m_digest.m_digest,
+                                 m_row.m_digest.m_digest_length);
+        else
           f->set_null();
         break;
       case 11: /* DIGEST_TEXT */
-         if(m_row.m_digest.m_digest_text_length > 0)
-            set_field_longtext_utf8(f, m_row.m_digest.m_digest_text,
-                                    m_row.m_digest.m_digest_text_length);
-         else
+        if (m_row.m_digest.m_digest_text_length > 0)
+           set_field_longtext_utf8(f, m_row.m_digest.m_digest_text,
+                                   m_row.m_digest.m_digest_text_length);
+        else
           f->set_null();
         break;
       case 12: /* CURRENT_SCHEMA */

=== modified file 'storage/perfschema/table_events_statements.h'
--- a/storage/perfschema/table_events_statements.h	2012-01-31 06:34:29 +0000
+++ b/storage/perfschema/table_events_statements.h	2012-02-23 23:27:02 +0000
@@ -65,7 +65,7 @@ struct row_events_statements
   /** Column SQL_TEXT. */
   char m_sqltext[COL_INFO_SIZE];
   /** Column DIGEST and DIGEST_TEXT. */
-  struct PFS_digest_row m_digest;
+  PFS_digest_row m_digest;
   /** Length in bytes of @c m_info. */
   uint m_sqltext_length;
   /** Column CURRENT_SCHEMA. */

=== modified file 'storage/perfschema/table_helper.cc'
--- a/storage/perfschema/table_helper.cc	2012-02-21 18:27:58 +0000
+++ b/storage/perfschema/table_helper.cc	2012-02-23 23:27:02 +0000
@@ -108,7 +108,7 @@ int PFS_digest_row::make_row(PFS_stateme
     stats at index 0 of statements_digest_stat_array. So do not calculate
     digest/digest_text as it should always be "NULL".
   */
-  if(pfs->m_digest_storage.m_byte_count != 0)
+  if (pfs->m_digest_storage.m_byte_count != 0)
   {
     /*
       Calculate digest from MD5 HASH collected to be shown as
@@ -123,7 +123,6 @@ int PFS_digest_row::make_row(PFS_stateme
     */ 
     get_digest_text(m_digest_text, &pfs->m_digest_storage);
     m_digest_text_length= strlen(m_digest_text);
-
   }
   else
   {

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl5767 branch (marc.alff:3445 to 3446) Marc Alff24 Feb