From: Mayank Prasad Date: October 4 2011 12:18pm Subject: bzr push into mysql-trunk-wl5767 branch (mayank.prasad:3384 to 3385) WL#5767 List-Archive: http://lists.mysql.com/commits/141327 Message-Id: <201110041218.p94CIJm2017972@acsmt356.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3385 Mayank Prasad 2011-10-04 WL#5767 : statement digest, performance schema Details: - Addressed review comments from Marc. modified: sql/sql_lex.cc sql/sql_lex.h storage/perfschema/pfs.cc storage/perfschema/pfs_digest.cc storage/perfschema/pfs_digest.h storage/perfschema/pfs_events_statements.h storage/perfschema/table_esms_by_digest.cc storage/perfschema/table_helper.cc 3384 Mayank Prasad 2011-09-15 wl#5767 : performance schema, statement digest Details: - Code for populating statement_current, statement_history and statement_history_long tables with captured digest information. modified: include/mysql/psi/psi.h include/mysql/psi/psi_abi_v1.h.pp storage/perfschema/pfs.cc storage/perfschema/pfs_digest.cc storage/perfschema/pfs_digest.h storage/perfschema/pfs_events_statements.h storage/perfschema/table_events_statements.cc === modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2011-09-07 21:27:46 +0000 +++ b/sql/sql_lex.cc 2011-10-04 12:16:34 +0000 @@ -29,32 +29,28 @@ #include "sp_head.h" #define PASS_TOKEN_TO_PS(_token,_yychar,_yylen) \ - if(lip->m_digest_psi != NULL) \ - { \ - /* - Passing token to PS function to calculate statement digest - for this statement. - */ \ - if( _token != 0 ) \ - { \ - uint yylen= 0; \ - char *yychar= NULL; \ - if( _token != END_OF_INPUT ) \ - { \ - /* - get the length of processed token and make sure it doesn't exceed - TOCK_NAME_LENGTH. If it does, truncate it to TOCK_NAME_LENGTH. - */ \ - yylen= _yylen!=0 ? _yylen : lip->yyLength_PS(); \ - yylen= yylenget_cpp_tok_start(); \ - } \ - PSI_server->digest_add_token(lip->m_digest_psi,_token,yychar,yylen); \ - } \ + /* + Passing token to PS function to calculate statement digest + for this statement. + */ \ + if( _token != 0 ) \ + { \ + uint yylen= 0; \ + char *yychar= NULL; \ + if( _token != END_OF_INPUT ) \ + { \ + /* + get the length of processed token and make sure it doesn't exceed + TOCK_NAME_LENGTH. If it does, truncate it to TOCK_NAME_LENGTH. + */ \ + yylen= _yylen!=0 ? _yylen : lip->yyLength_PS(); \ + yylen= yylenget_cpp_tok_start(); \ + } \ + PSI_CALL(digest_add_token)(lip->m_digest_psi,_token,yychar,yylen); \ } - static int lex_one_token(void *arg, void *yythd); /* @@ -198,15 +194,8 @@ bool Lex_input_stream::init(THD *thd, reset(buff, length); /* DIGEST_START */ - if( thd->m_statement_psi != NULL ) - { - m_digest_psi= PSI_server->digest_start(thd->m_statement_psi); - } - else - { - m_digest_psi= NULL; - } - + m_digest_psi= PSI_server->digest_start(thd->m_statement_psi); + return FALSE; } === modified file 'sql/sql_lex.h' --- a/sql/sql_lex.h 2011-09-07 10:38:59 +0000 +++ b/sql/sql_lex.h 2011-10-04 12:16:34 +0000 @@ -2600,12 +2600,6 @@ public: { m_lip.reset(found_semicolon, length); m_yacc.reset(); - - if( m_lip.m_digest_psi != NULL ) - { - /* DIGEST_END */ - PSI_server->digest_end(m_lip.m_digest_psi); - } } }; === modified file 'storage/perfschema/pfs.cc' --- a/storage/perfschema/pfs.cc 2011-09-15 12:22:08 +0000 +++ b/storage/perfschema/pfs.cc 2011-10-04 12:16:34 +0000 @@ -1172,13 +1172,6 @@ static enum_operation_type socket_operat }; /** - Structure to store a MD5 hash value (digest) for a statement. -*/ -struct { - unsigned char m_md5[16]; - }typedef PFS_digest_hash; - -/** Build the prefix name of a class of instruments in a category. For example, this function builds the string 'wait/sync/mutex/sql/' from a prefix 'wait/sync/mutex' and a category 'sql'. @@ -4797,7 +4790,7 @@ static struct PSI_digest_locker* digest_ /* If current statement is not instrumented */ - if( !(flag_thread_instrumentation && flag_events_statements_current) ) + if(!locker || !(flag_thread_instrumentation && flag_events_statements_current)) { return NULL; } @@ -4822,9 +4815,10 @@ static struct PSI_digest_locker* digest_ digest_storage= &pfs->m_digest_storage; /* - Initialize token count to 0. - */ - digest_storage->m_token_count= 0; + Initialize token array and token count to 0. + */ + while(digest_storage->m_token_count) + digest_storage->m_token_array[--digest_storage->m_token_count]= 0; /* Set digest_locker_state's digest storage pointer. @@ -4843,6 +4837,9 @@ static void digest_add_token_v1(PSI_dige PFS_events_statements *pfs; PFS_digest_storage *digest_storage; + if(!locker) + return; + state= reinterpret_cast (locker); DBUG_ASSERT(state != NULL); @@ -4855,39 +4852,9 @@ static void digest_add_token_v1(PSI_dige */ if( token == 403 ) { - PFS_digest_hash digest; - char digest_str[COL_DIGEST_SIZE]={'\0'}; - /* - Calculate MD5 Hash of the tokens recieved. - */ - MY_MD5_HASH(digest.m_md5, (unsigned char *)digest_storage, - (uint) sizeof(PFS_digest_storage)); - /* - Write MD5 hash value in a string to be used as DIGEST for the statement. - */ - sprintf(digest_str, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" - "%02x%02x%02x", - digest.m_md5[0], digest.m_md5[1], digest.m_md5[2], - digest.m_md5[3], digest.m_md5[4], digest.m_md5[5], - digest.m_md5[6], digest.m_md5[7], digest.m_md5[8], - digest.m_md5[9], digest.m_md5[10], digest.m_md5[11], - digest.m_md5[12], digest.m_md5[13], digest.m_md5[14], - digest.m_md5[15]); - - /* - TODO: create DIGEST_TEXT from tokens and pass it to - insert_statement_digest() below. Hard coded to - "DIGEST_TEXT" as of now. - */ - - /* - Populate PFS_statements_digest_stat with computed digest information. - */ - PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); - pfs->statement_digest_stat_ptr= - search_insert_statement_digest(pfs_thread, - digest_str, - (char*)"DIGEST_TEXT"); + /* DIGEST_End */ + PSI_CALL(digest_end)(locker); + return; } else if( digest_storage->m_token_count >= PFS_MAX_TOKEN_COUNT ) { @@ -4912,14 +4879,36 @@ static void digest_end_v1(PSI_digest_loc PFS_events_statements *pfs; PFS_digest_storage *digest_storage; + if(!locker) + return; + state= reinterpret_cast (locker); DBUG_ASSERT(state != NULL); pfs= reinterpret_cast(state->m_statement); digest_storage= &pfs->m_digest_storage; - /* reset token count to 0 */ - digest_storage->m_token_count= 0; + //printf("\n statement_text = [%s]\n",pfs->m_sqltext); + + /* + Calculate MD5 Hash of the tokens recieved. + */ + MY_MD5_HASH(digest_storage->m_digest_hash.m_md5, (unsigned char *)digest_storage->m_token_array, + (uint) sizeof(digest_storage->m_token_array)); + + /* + Populate PFS_statements_digest_stat with computed digest information. + */ + PFS_thread *pfs_thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); + pfs->statement_digest_stat_ptr= + search_insert_statement_digest(pfs_thread, + digest_storage->m_digest_hash.m_md5, + pfs->m_sqltext, + pfs->m_sqltext_length); + /* + Not resetting digest_storage->m_token_count to 0 here as it will be done in + digest_start. + */ } /** === modified file 'storage/perfschema/pfs_digest.cc' --- a/storage/perfschema/pfs_digest.cc 2011-09-15 12:22:08 +0000 +++ b/storage/perfschema/pfs_digest.cc 2011-10-04 12:16:34 +0000 @@ -28,8 +28,11 @@ unsigned int statements_digest_size= 0; PFS_statements_digest_stat *statements_digest_stat_array= NULL; /** Consumer flag for table EVENTS_STATEMENTS_SUMMARY_BY_DIGEST. */ bool flag_statements_digest= true; -/** Current index in Stat array where new record is to be inserted. */ -int digest_index= 0; +/** + 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. +*/ +int digest_index= 1; static LF_HASH digest_hash; static bool digest_hash_inited= false; @@ -77,8 +80,8 @@ static uchar *digest_hash_get_key(const DBUG_ASSERT(typed_entry != NULL); digest= *typed_entry; DBUG_ASSERT(digest != NULL); - *length= digest->m_key.m_key_length; - result= digest->m_key.m_hash_key; + *length= 16; + result= digest->m_md5_hash.m_md5; return const_cast (reinterpret_cast (result)); } C_MODE_END @@ -114,34 +117,18 @@ static LF_PINS* get_digest_hash_pins(PFS { if (unlikely(thread->m_digest_hash_pins == NULL)) { - if (! digest_hash_inited) + if (!digest_hash_inited) return NULL; thread->m_digest_hash_pins= lf_hash_get_pins(&digest_hash); } return thread->m_digest_hash_pins; } -static void set_digest_key(PFS_digest_key *key, - const char *digest, uint digest_length) -{ - DBUG_ASSERT(digest_length <= COL_DIGEST_SIZE); - - char *ptr= &key->m_hash_key[0]; - if (digest_length > 0) - { - memcpy(ptr, digest, digest_length); - ptr+= digest_length; - } - ptr[0]= 0; - ptr++; - key->m_key_length= ptr - &key->m_hash_key[0]; -} - - PFS_statements_digest_stat* search_insert_statement_digest(PFS_thread* thread, - char* digest, - char* digest_text) + unsigned char* hash_key, + char* digest_text, + unsigned int digest_text_length) { /* get digest pin. */ LF_PINS *pins= get_digest_hash_pins(thread); @@ -150,42 +137,54 @@ search_insert_statement_digest(PFS_threa return NULL; } - /* make new digest key. */ - PFS_digest_key key; - set_digest_key(&key, digest, strlen(digest)); - PFS_statements_digest_stat **entry; + PFS_statements_digest_stat *pfs; /* Lookup LF_HASH using this new key. */ entry= reinterpret_cast (lf_hash_search(&digest_hash, pins, - key.m_hash_key, key.m_key_length)); + hash_key, 16)); if(!entry) { /* - If statement digest entry doesn't exist, add a new record in the - digest stat array. + If statement digest entry doesn't exist. */ //printf("\n Doesn't Exist. Adding new entry. \n"); - PFS_statements_digest_stat *pfs; + if(digest_index==0) + { + /* + digest_stat array is full. Add stat at index 0 and return. + */ + pfs= &statements_digest_stat_array[0]; + //TODO + return pfs; + } + + /* + Add a new record in digest stat array. + */ pfs= &statements_digest_stat_array[digest_index]; - /* Set digest. */ - memcpy(pfs->m_digest, digest, COL_DIGEST_SIZE); - pfs->m_digest_length= strlen(digest); - /* Set digest text. */ - memcpy(pfs->m_digest_text, digest_text, COL_DIGEST_TEXT_SIZE); - pfs->m_digest_text_length= strlen(digest_text); + memcpy(pfs->m_digest_text, digest_text, digest_text_length); + pfs->m_digest_text_length= digest_text_length; - /* Set digest key. */ - memcpy(pfs->m_key.m_hash_key, key.m_hash_key, COL_DIGEST_SIZE); - pfs->m_key.m_key_length= key.m_key_length; + /* Set digest hash/LF Hash search key. */ + memcpy(pfs->m_md5_hash.m_md5, hash_key, 16); + + /* Increment index. */ + digest_index++; - /* Rounding Buffer. Overwrite first entry if all slots are full. */ - digest_index= (digest_index+1)%statements_digest_size; + if(digest_index%statements_digest_size == 0) + { + /* + Digest stat array is full. Now all stat for all further + entries will go into index 0. + */ + digest_index= 0; + } /* Add this new digest into LF_HASH */ int res; @@ -204,7 +203,6 @@ search_insert_statement_digest(PFS_threa If stmt digest already exists, update stat and return */ //printf("\n Already Exists \n"); - PFS_statements_digest_stat *pfs; pfs= *entry; lf_hash_search_unpin(pins); return pfs; === modified file 'storage/perfschema/pfs_digest.h' --- a/storage/perfschema/pfs_digest.h 2011-09-15 12:22:08 +0000 +++ b/storage/perfschema/pfs_digest.h 2011-10-04 12:16:34 +0000 @@ -28,19 +28,6 @@ extern bool flag_statements_digest; -struct PFS_digest_key -{ - /** - Hash search key. - This has to be a string for LF_HASH, - the format is "<0x00>" - */ - char m_hash_key[COL_DIGEST_SIZE + 1]; - unsigned int m_key_length; -}; - - - /** A statement digest stat record. */ struct PFS_statements_digest_stat { @@ -49,7 +36,10 @@ struct PFS_statements_digest_stat char m_digest_text[COL_DIGEST_TEXT_SIZE]; unsigned int m_digest_text_length; - PFS_digest_key m_key; + /** + Digest hash/LF Hash search key. + */ + PFS_digest_hash m_md5_hash; }; @@ -60,7 +50,8 @@ void cleanup_digest(); int init_digest_hash(void); void cleanup_digest_hash(void); PFS_statements_digest_stat* search_insert_statement_digest(PFS_thread*, - char*, char*); + unsigned char*, char*, + unsigned int); void reset_esms_by_digest(); === modified file 'storage/perfschema/pfs_events_statements.h' --- a/storage/perfschema/pfs_events_statements.h 2011-09-15 12:22:08 +0000 +++ b/storage/perfschema/pfs_events_statements.h 2011-10-04 12:16:34 +0000 @@ -30,14 +30,22 @@ struct PFS_user; struct PFS_host; /** + Structure to store a MD5 hash value (digest) for a statement. +*/ +struct { + unsigned char m_md5[16]; + }typedef PFS_digest_hash; + +/** Structure to store token count/array for a statement on which digest is to be calculated. */ #define PFS_MAX_TOKEN_COUNT 1024 -typedef struct { +struct { uint m_token_count; uint m_token_array[PFS_MAX_TOKEN_COUNT]; - } PFS_digest_storage; + PFS_digest_hash m_digest_hash; + } typedef PFS_digest_storage; /** A statement record. */ === modified file 'storage/perfschema/table_esms_by_digest.cc' --- a/storage/perfschema/table_esms_by_digest.cc 2011-09-13 11:29:39 +0000 +++ b/storage/perfschema/table_esms_by_digest.cc 2011-10-04 12:16:34 +0000 @@ -218,7 +218,11 @@ int table_esms_by_digest::rnd_next(void) m_pos.set_at(&m_next_pos); digest_stat= &statements_digest_stat_array[m_pos.m_index]; - if(digest_stat->m_digest[0] != '\0') + /* + If digest information exist for this record, + make a new row. + */ + if(digest_stat->m_digest_text[0] != '\0') { make_row(digest_stat); m_next_pos.set_after(&m_pos); @@ -236,7 +240,11 @@ table_esms_by_digest::rnd_pos(const void set_position(pos); digest_stat= &statements_digest_stat_array[m_pos.m_index]; - if(digest_stat->m_digest[0] != '\0') + /* + If digest information exist for this record, + make a new row. + */ + if(digest_stat->m_digest_text[0] != '\0') { make_row(digest_stat); return 0; @@ -250,6 +258,7 @@ void table_esms_by_digest::make_row(PFS_ { m_row_exists= false; m_row.m_digest.make_row(digest_stat); + /* TODO Add code for statements stats */ m_row_exists= true; } === modified file 'storage/perfschema/table_helper.cc' --- a/storage/perfschema/table_helper.cc 2011-09-13 11:29:39 +0000 +++ b/storage/perfschema/table_helper.cc 2011-10-04 12:16:34 +0000 @@ -103,11 +103,21 @@ void PFS_account_row::set_field(uint ind int PFS_digest_row::make_row(PFS_statements_digest_stat* pfs) { - m_digest_length= pfs->m_digest_length; - if (m_digest_length > sizeof(m_digest)) - return 1; - if (m_digest_length > 0) - memcpy(m_digest, pfs->m_digest, sizeof(m_digest)); + /* + Write MD5 hash value in a string to be used as DIGEST for the statement. + */ + sprintf(pfs->m_digest, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x", + pfs->m_md5_hash.m_md5[0], pfs->m_md5_hash.m_md5[1], pfs->m_md5_hash.m_md5[2], + pfs->m_md5_hash.m_md5[3], pfs->m_md5_hash.m_md5[4], pfs->m_md5_hash.m_md5[5], + pfs->m_md5_hash.m_md5[6], pfs->m_md5_hash.m_md5[7], pfs->m_md5_hash.m_md5[8], + pfs->m_md5_hash.m_md5[9], pfs->m_md5_hash.m_md5[10], pfs->m_md5_hash.m_md5[11], + pfs->m_md5_hash.m_md5[12], pfs->m_md5_hash.m_md5[13], pfs->m_md5_hash.m_md5[14], + pfs->m_md5_hash.m_md5[15]); + pfs->m_digest_length= 16; + + memcpy(m_digest, pfs->m_digest, sizeof(m_digest)); + m_digest_length= 16; m_digest_text_length= pfs->m_digest_text_length; if (m_digest_text_length > sizeof(m_digest_text)) No bundle (reason: useless for push emails).