From: Marc Alff Date: February 23 2012 11:27pm Subject: bzr push into mysql-trunk-wl5767 branch (marc.alff:3445 to 3446) List-Archive: http://lists.mysql.com/commits/143050 Message-Id: <201202232328.q1NNS5qE009907@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 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, ¤t_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, ¤t_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; /* 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, ¤t_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 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).