From: Christopher Powers Date: February 10 2012 11:39pm Subject: bzr push into mysql-trunk-wl5767 branch (chris.powers:3426 to 3427) WL#5767 List-Archive: http://lists.mysql.com/commits/142839 Message-Id: <201202102335.q1ANZxaU029280@acsmt358.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3427 Christopher Powers 2012-02-10 WL#5767 PERFORMANCE_SCHEMA STATEMENT DIGEST - Added MYSQL_ADD_TOKEN() to PSI interface, replaced macro in sql_lex.cc - Added data flow comments to doxygen LLD in pfs.cc - Minor style changes in pfs_digest.cc modified: include/mysql/psi/mysql_statement.h sql/sql_lex.cc storage/perfschema/pfs.cc storage/perfschema/pfs_digest.cc storage/perfschema/table_events_statements.cc 3426 Christopher Powers 2012-02-10 [merge] WL#5767 PERFORMANCE_SCHEMA STATEMENTS DIGEST Merge with mysql-trunk added: mysql-test/r/debug_sync2.result mysql-test/suite/innodb/r/innodb-index-debug.result mysql-test/suite/innodb/t/innodb-index-debug.test mysql-test/t/debug_sync2-master.opt mysql-test/t/debug_sync2.test modified: mysql-test/extra/rpl_tests/rpl_insert_id_pk.test mysql-test/extra/rpl_tests/rpl_multi_update.test mysql-test/extra/rpl_tests/rpl_multi_update2.test mysql-test/extra/rpl_tests/rpl_multi_update3.test mysql-test/include/icp_tests.inc mysql-test/include/index_merge1.inc mysql-test/include/join_cache.inc mysql-test/include/subquery.inc mysql-test/include/subquery_mat.inc mysql-test/mysql-test-run.pl mysql-test/r/events_restart.result mysql-test/r/heap.result mysql-test/r/index_merge_myisam.result mysql-test/r/innodb_icp.result mysql-test/r/innodb_icp_all.result mysql-test/r/innodb_icp_none.result mysql-test/r/innodb_mysql_sync.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/myisam_icp.result mysql-test/r/myisam_icp_all.result mysql-test/r/myisam_icp_none.result mysql-test/r/ps.result mysql-test/r/read_only.result mysql-test/r/subquery_all.result mysql-test/r/subquery_all_bka.result mysql-test/r/subquery_all_bka_nixbnl.result mysql-test/r/subquery_mat.result mysql-test/r/subquery_mat_all.result mysql-test/r/subquery_mat_none.result mysql-test/r/subquery_nomat_nosj.result mysql-test/r/subquery_nomat_nosj_bka.result mysql-test/r/subquery_nomat_nosj_bka_nixbnl.result mysql-test/r/subquery_none.result mysql-test/r/subquery_none_bka.result mysql-test/r/subquery_none_bka_nixbnl.result mysql-test/r/subquery_sj_all.result mysql-test/r/subquery_sj_all_bka.result mysql-test/r/subquery_sj_all_bka_nixbnl.result mysql-test/r/subquery_sj_all_bkaunique.result mysql-test/r/subquery_sj_mat.result mysql-test/r/subquery_sj_mat_bka.result mysql-test/r/subquery_sj_mat_bka_nixbnl.result mysql-test/r/subquery_sj_mat_bkaunique.result mysql-test/r/subquery_sj_mat_nosj.result mysql-test/r/type_time.result mysql-test/suite/binlog/r/binlog_unsafe.result mysql-test/suite/binlog/t/binlog_unsafe.test mysql-test/suite/innodb/r/innodb_mysql.result mysql-test/suite/innodb/t/innodb-index.test mysql-test/suite/opt_trace/include/general.inc 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/general2_no_prot.result mysql-test/suite/opt_trace/r/general2_ps_prot.result mysql-test/suite/opt_trace/r/general_no_prot_all.result mysql-test/suite/opt_trace/r/general_no_prot_none.result mysql-test/suite/opt_trace/r/general_ps_prot_all.result mysql-test/suite/opt_trace/r/general_ps_prot_none.result mysql-test/suite/opt_trace/r/subquery_no_prot.result mysql-test/suite/opt_trace/r/subquery_ps_prot.result mysql-test/suite/opt_trace/r/temp_table.result mysql-test/suite/opt_trace/t/temp_table.test mysql-test/suite/rpl/r/rpl_auto_increment_11932.result mysql-test/suite/rpl/r/rpl_corruption.result mysql-test/suite/rpl/r/rpl_insert_id_pk.result mysql-test/suite/rpl/r/rpl_multi_update.result mysql-test/suite/rpl/r/rpl_multi_update2.result mysql-test/suite/rpl/r/rpl_multi_update3.result mysql-test/suite/rpl/r/rpl_rotate_logs.result mysql-test/suite/rpl/t/rpl_auto_increment_11932.test mysql-test/suite/rpl/t/rpl_corruption.test mysql-test/suite/rpl/t/rpl_multi_update2.test mysql-test/suite/rpl/t/rpl_multi_update3.test mysql-test/suite/rpl/t/rpl_optimize.test mysql-test/suite/rpl/t/rpl_rotate_logs.test mysql-test/suite/rpl/t/rpl_semi_sync_event.test mysql-test/suite/rpl/t/rpl_timezone.test mysql-test/suite/sys_vars/t/innodb_buffer_pool_filename_basic.test mysql-test/t/events_restart.test mysql-test/t/heap.test mysql-test/t/innodb_mysql_sync.test mysql-test/t/multi_update.test mysql-test/t/ps.test mysql-test/t/read_only.test mysql-test/t/type_time.test sql/debug_sync.cc sql/events.cc sql/item.h sql/item_cmpfunc.cc sql/item_cmpfunc.h sql/item_subselect.cc sql/item_subselect.h sql/opt_range.cc sql/share/errmsg-utf8.txt sql/sql_base.cc sql/sql_class.cc sql/sql_lex.cc sql/sql_lex.h sql/sql_optimizer.cc sql/sql_optimizer.h sql/sql_resolver.cc sql/sql_select.cc sql/sql_show.cc sql/sql_table.cc sql/sql_tmp_table.cc sql/sys_vars.cc storage/heap/hp_hash.c storage/innobase/dict/dict0stats.cc storage/innobase/handler/ha_innodb.cc storage/innobase/include/ha_prototypes.h storage/innobase/row/row0merge.cc storage/innobase/trx/trx0trx.cc unittest/gunit/opt_range-t.cc === modified file 'include/mysql/psi/mysql_statement.h' --- a/include/mysql/psi/mysql_statement.h 2012-02-08 10:30:58 +0000 +++ b/include/mysql/psi/mysql_statement.h 2012-02-10 23:14:57 +0000 @@ -54,6 +54,14 @@ NULL #endif +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE + #define MYSQL_ADD_TOKEN(LOCKER, T, Y) \ + inline_mysql_add_token(LOCKER, T, Y) +#else + #define MYSQL_ADD_TOKEN(LOCKER, T, Y) \ + NULL +#endif + #ifdef HAVE_PSI_STATEMENT_INTERFACE #define MYSQL_START_STATEMENT(STATE, K, DB, DB_LEN) \ inline_mysql_start_statement(STATE, K, DB, DB_LEN, __FILE__, __LINE__) @@ -129,6 +137,18 @@ inline_mysql_digest_start(PSI_statement_ } #endif +#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE +static inline struct PSI_digest_locker * +inline_mysql_add_token(PSI_digest_locker *locker, uint token, + void *yylval) +{ + if (likely(locker != NULL)) + locker= PSI_CALL(digest_add_token)(locker, token, + (OPAQUE_LEX_YYSTYPE*)yylval); + return locker; +} +#endif + static inline struct PSI_statement_locker * inline_mysql_start_statement(PSI_statement_locker_state *state, PSI_statement_key key, === modified file 'sql/sql_lex.cc' --- a/sql/sql_lex.cc 2012-02-10 21:20:10 +0000 +++ b/sql/sql_lex.cc 2012-02-10 23:14:57 +0000 @@ -31,27 +31,7 @@ #include "sql_show.h" // append_identifier #include "sql_select.h" // JOIN #include "sql_optimizer.h" // JOIN - -#ifdef HAVE_PSI_STATEMENT_DIGEST_INTERFACE -#define PSI_ADD_TOKEN(L, T, Y) inline_add_token(L, T, Y) - -static void inline_add_token(Lex_input_stream *lip, - uint token, - YYSTYPE *yylval) -{ - if (lip->m_digest_psi != NULL) - { - /* - Passing token to PS function to calculate statement digest - for this statement. - */ - lip->m_digest_psi= PSI_CALL(digest_add_token) - (lip->m_digest_psi, token, (OPAQUE_LEX_YYSTYPE*) yylval); - } -} -#else -#define PSI_ADD_TOKEN(L, T, Y) do {} while(0) -#endif +#include static int lex_one_token(void *arg, void *yythd); @@ -905,7 +885,7 @@ int MYSQLlex(void *arg, void *yythd) lip->lookahead_token= -1; *yylval= *(lip->lookahead_yylval); lip->lookahead_yylval= NULL; - PSI_ADD_TOKEN(lip, token, yylval); + lip->m_digest_psi= MYSQL_ADD_TOKEN(lip->m_digest_psi, token, yylval); return token; } @@ -923,10 +903,12 @@ int MYSQLlex(void *arg, void *yythd) token= lex_one_token(arg, yythd); switch(token) { case CUBE_SYM: - PSI_ADD_TOKEN(lip, WITH_CUBE_SYM, yylval); + lip->m_digest_psi= MYSQL_ADD_TOKEN(lip->m_digest_psi, WITH_CUBE_SYM, + yylval); return WITH_CUBE_SYM; case ROLLUP_SYM: - PSI_ADD_TOKEN(lip, WITH_ROLLUP_SYM, yylval); + lip->m_digest_psi= MYSQL_ADD_TOKEN(lip->m_digest_psi, WITH_ROLLUP_SYM, + yylval); return WITH_ROLLUP_SYM; default: /* @@ -935,7 +917,7 @@ int MYSQLlex(void *arg, void *yythd) lip->lookahead_yylval= lip->yylval; lip->yylval= NULL; lip->lookahead_token= token; - PSI_ADD_TOKEN(lip, WITH, yylval); + lip->m_digest_psi= MYSQL_ADD_TOKEN(lip->m_digest_psi, WITH, yylval); return WITH; } break; @@ -943,7 +925,7 @@ int MYSQLlex(void *arg, void *yythd) break; } - PSI_ADD_TOKEN(lip, token, yylval); + lip->m_digest_psi= MYSQL_ADD_TOKEN(lip->m_digest_psi, token, yylval); return token; } === modified file 'storage/perfschema/pfs.cc' --- a/storage/perfschema/pfs.cc 2012-02-10 12:55:57 +0000 +++ b/storage/perfschema/pfs.cc 2012-02-10 23:14:57 +0000 @@ -966,53 +966,67 @@ static inline int mysql_mutex_lock(...) - [E] EVENTS_STAGES_SUMMARY_GLOBAL_BY_EVENT_NAME, @c table_esgs_global_by_event_name::make_row() - @section IMPL_STATEMENT Implementation for statements aggregates - - For statements, the tables that contains aggregated data are: - - EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME - - EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME - - EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME - - EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME - - EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME - -@verbatim - statement_locker(T, S) - | - | [1] - | -1a |-> pfs_thread(T).event_name(S) =====>> [A], [B], [C], [D], [E] - | | - | | [2] - | | - | 2a |-> pfs_account(U, H).event_name(S) =====>> [B], [C], [D], [E] - | . | - | . | [3-RESET] - | . | - | 2b .....+-> pfs_user(U).event_name(S) =====>> [C] - | . | - | 2c .....+-> pfs_host(H).event_name(S) =====>> [D], [E] - | . . | - | . . | [4-RESET] - | 2d . . | -1b |----+----+----+-> pfs_stage_class(S) =====>> [E] - -@endverbatim - - Implemented as: - - [1] @c start_statement_v1(), end_statement_v1() - - [2] @c delete_thread_v1(), @c aggregate_thread_statements() - - [3] @c PFS_account::aggregate_statements() - - [4] @c PFS_host::aggregate_statements() - - [A] EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME, - @c table_esms_by_thread_by_event_name::make_row() - - [B] EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME, - @c table_esms_by_account_by_event_name::make_row() - - [C] EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME, - @c table_esms_by_user_by_event_name::make_row() - - [D] EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME, - @c table_esms_by_host_by_event_name::make_row() - - [E] EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME, - @c table_esms_global_by_event_name::make_row() +@section IMPL_STATEMENT Implementation for statements consumers + + For statements, the tables that contains individual event data are: + - EVENTS_STATEMENTS_CURRENT + - EVENTS_STATEMENTS_HISTORY + - EVENTS_STATEMENTS_HISTORY_LONG + + For statements, the tables that contains aggregated data are: + - EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME + - EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME + - EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME + - EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME + - EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME + - EVENTS_STATEMENTS_SUMMARY_BY_DIGEST + +@verbatim + statement_locker(T, S) + | + | [1] + | +1a |-> pfs_thread(T).event_name(S) =====>> [A], [B], [C], [D], [E], [F] + | | + | | [2] + | | + | 2a |-> pfs_account(U, H).event_name(S) =====>> [C], [D], [E], [F] + | . | + | . | [3-RESET] + | . | + | 2b .....+-> pfs_user(U).event_name(S) =====>> [D] + | . | + | 2c .....+-> pfs_host(H).event_name(S) =====>> [E], [F] + | . . | + | . . | [4-RESET] + | 2d . . | +1b |----+----+----+-> pfs_statement_class(S) =====>> [F] + | +1c |-> statement_digest(T, S) =====>> [A], [G] + +@endverbatim + + Implemented as: + - [1] @c start_statement_v1(), end_statement_v1() + - [2] @c delete_thread_v1(), @c aggregate_thread_statements() + - [3] @c PFS_account::aggregate_statements() + - [4] @c PFS_host::aggregate_statements() + - [A] EVENTS_STATEMENTS_CURRENT, EVENTS_STATEMENTS_HISTORY, + EVENTS_STATEMENTS_HISTORY_LONG + @c table_events_statements_common::make_row() + - [B] EVENTS_STATEMENTS_SUMMARY_BY_THREAD_BY_EVENT_NAME, + @c table_esms_by_thread_by_event_name::make_row() + - [C] EVENTS_STATEMENTS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME, + @c table_esms_by_account_by_event_name::make_row() + - [D] EVENTS_STATEMENTS_SUMMARY_BY_USER_BY_EVENT_NAME, + @c table_esms_by_user_by_event_name::make_row() + - [E] EVENTS_STATEMENTS_SUMMARY_BY_HOST_BY_EVENT_NAME, + @c table_esms_by_host_by_event_name::make_row() + - [F] EVENTS_STATEMENTS_SUMMARY_GLOBAL_BY_EVENT_NAME, + @c table_esms_global_by_event_name::make_row() + - [G] EVENTS_STATEMENTS_SUMMARY_BY_DIGEST + @c table_esms_by_digest::make_row() + */ /** === modified file 'storage/perfschema/pfs_digest.cc' --- a/storage/perfschema/pfs_digest.cc 2012-02-10 21:02:01 +0000 +++ b/storage/perfschema/pfs_digest.cc 2012-02-10 23:14:57 +0000 @@ -34,8 +34,8 @@ #include /* Generated code */ -#include "sql_yacc.h" -#include "pfs_lex_token.h" +#include "../sql/sql_yacc.h" +#include "../storage/perfschema/pfs_lex_token.h" /* Name pollution from sql/sql_lex.h */ #ifdef LEX_YYSTYPE @@ -102,16 +102,14 @@ int init_digest(unsigned int statements_ /** Cleanup table EVENTS_STATEMENTS_SUMMARY_BY_DIGEST. */ void cleanup_digest(void) { - /* - Free memory allocated to statements_digest_stat_array. - */ + /* Free memory allocated to statements_digest_stat_array. */ pfs_free(statements_digest_stat_array); statements_digest_stat_array= NULL; } C_MODE_START static uchar *digest_hash_get_key(const uchar *entry, size_t *length, - my_bool) + my_bool) { const PFS_statements_digest_stat * const *typed_entry; const PFS_statements_digest_stat *digest; @@ -143,7 +141,6 @@ int init_digest_hash(void) return 0; } -/** Cleanup the digest hash. */ void cleanup_digest_hash(void) { if (digest_hash_inited) @@ -165,9 +162,9 @@ static LF_PINS* get_digest_hash_pins(PFS } PFS_statements_digest_stat* -find_or_create_digest(PFS_thread* thread, PFS_digest_hash d_hash, PFS_digest_storage* digest_storage) +find_or_create_digest(PFS_thread* thread, PFS_digest_hash d_hash, + PFS_digest_storage* digest_storage) { - /* get digest pin. */ LF_PINS *pins= get_digest_hash_pins(thread); /* There shoulod be at least one token. */ if(unlikely(pins == NULL) || @@ -190,28 +187,18 @@ find_or_create_digest(PFS_thread* thread if(!entry) { - /* - If statement digest entry doesn't exist. - */ if(digest_index == 0) { - /* - digest_stat array is full. Add stat at index 0 and return. - */ + /* digest_stat array is full. Add stat at index 0 and return. */ pfs= &statements_digest_stat_array[0]; - /* - If this is the first entry at index 0, update - first seen information. - */ - if(pfs->m_first_seen==0) + + if(pfs->m_first_seen == 0) pfs->m_first_seen= now; pfs->m_last_seen= now; return pfs; } - /* - Add a new record in digest stat array. - */ + /* Add a new record in digest stat array. */ pfs= &statements_digest_stat_array[digest_index]; /* @@ -230,7 +217,6 @@ find_or_create_digest(PFS_thread* thread pfs->m_first_seen= now; pfs->m_last_seen= now; - /* Increment index. */ digest_index++; if(digest_index%statements_digest_size == 0) @@ -255,9 +241,7 @@ find_or_create_digest(PFS_thread* thread } else if (entry && (entry != MY_ERRPTR)) { - /* - If stmt digest already exists, update stat and return. - */ + /* If digest already exists, update stats and return. */ pfs= *entry; pfs->m_last_seen= now; lf_hash_search_unpin(pins); @@ -269,7 +253,6 @@ find_or_create_digest(PFS_thread* thread void purge_digest(PFS_thread* thread, unsigned char* hash_key) { - /* get digest pin. */ LF_PINS *pins= get_digest_hash_pins(thread); if(unlikely(pins == NULL)) return; @@ -313,9 +296,7 @@ void reset_esms_by_digest() if(statements_digest_stat_array == NULL) return; - /* - Reset statements_digest_stat_array. - */ + /* Reset statements_digest_stat_array. */ for (index= 0; index < statements_digest_size; index++) { statements_digest_stat_array[index].reset(); @@ -329,7 +310,7 @@ void reset_esms_by_digest() } /* - This function, iterates token array and updates digest_text. + Iterate token array and updates digest_text. */ void get_digest_text(char* digest_text, PFS_digest_storage* digest_storage) { @@ -339,13 +320,14 @@ void get_digest_text(char* 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. */ - int available_bytes_to_write= COL_DIGEST_TEXT_SIZE-4; + int available_bytes_to_write= COL_DIGEST_TEXT_SIZE - 4; DBUG_ASSERT(byte_count <= PFS_MAX_DIGEST_STORAGE_SIZE); - while(current_byte0) + while(current_byte < byte_count && + available_bytes_to_write > 0) { read_token(&tok, ¤t_byte, token_array); tok_data= & lex_token_array[tok]; @@ -379,13 +361,11 @@ void get_digest_text(char* digest_text, digest_text++; } - available_bytes_to_write-= digest_text-digest_text_start; + available_bytes_to_write-= digest_text - digest_text_start; digest_text_start= digest_text; } - /* - Truncate digest text in case of long queries. - */ + /* Truncate digest text in case of long queries. */ if(digest_storage->m_full) { strcpy(digest_text,"..."); @@ -412,27 +392,15 @@ struct PSI_digest_locker* pfs_digest_sta return NULL; } - /* - Get statement locker state from statement locker - */ statement_state= reinterpret_cast (locker); DBUG_ASSERT(statement_state != NULL); - /* - Get digest_locker_state from statement_locker_state. - */ state= &statement_state->m_digest_state; DBUG_ASSERT(state != NULL); - /* - Take out thread specific statement record. And then digest - storage information for this statement from it. - */ digest_storage= &state->m_digest_storage; - /* - Initialize token array and token count to 0. - */ + /* Initialize token array and token count. */ digest_storage->m_byte_count= PFS_MAX_DIGEST_STORAGE_SIZE; state->m_last_id_index= 0; while(digest_storage->m_byte_count) @@ -460,9 +428,6 @@ PSI_digest_locker* pfs_digest_add_token_ if( PFS_MAX_DIGEST_STORAGE_SIZE - digest_storage->m_byte_count < PFS_SIZE_OF_A_TOKEN) { - /* - If digest storage record is full. - */ digest_storage->m_full= true; return NULL; } @@ -594,25 +559,19 @@ 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. - */ + /* Add this token to digest storage. */ store_token(digest_storage, token); - /* - Add this identifier's length and string to digest storage. - */ + + /* Add this identifier's length and string to digest storage. */ store_identifier(digest_storage, yylen, yytext); - /* - Update the index of last identifier found. - */ + + /* Update the index of last identifier found. */ state->m_last_id_index= digest_storage->m_byte_count; break; } default: { - /* - Add this token to digest storage. - */ + /* Add this token to digest storage. */ store_token(digest_storage, token); break; } === modified file 'storage/perfschema/table_events_statements.cc' --- a/storage/perfschema/table_events_statements.cc 2012-02-10 12:55:57 +0000 +++ b/storage/perfschema/table_events_statements.cc 2012-02-10 23:14:57 +0000 @@ -371,18 +371,12 @@ void table_events_statements_common::mak PFS_statements_digest_stat *pfs= statement->m_statement_digest_stat_ptr; if(pfs && pfs->m_digest_storage.m_byte_count != 0) { - /* - Calculate digest from MD5 HASH collected to be shown as - DIGEST in this row. - */ + /* Generate the DIGEST text string from the MD5 digest */ MD5_HASH_TO_STRING(pfs->m_digest_hash.m_md5, m_row.m_digest.m_digest); m_row.m_digest.m_digest_length= 16; - /* - Caclulate digest_text information from the token array collected - to be shown as DIGEST_TEXT column. - */ + /* Generate the DIGEST_TEXT string from the token array */ get_digest_text(m_row.m_digest.m_digest_text, &pfs->m_digest_storage); m_row.m_digest.m_digest_text_length= strlen(m_row.m_digest.m_digest_text); } No bundle (reason: useless for push emails).