diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-07-21 16:39:19 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-07-21 16:39:19 +0200 |
commit | b7b5f6f1ab49948b0e15b762266d4640b3d6b7fb (patch) | |
tree | 7c302c2025184dbd053aa6135f0ff28c8ce6f359 /storage/perfschema | |
parent | 5f6380adde2dac3f32b40339b9b702c0135eb7d6 (diff) | |
parent | c1d6a2d7e194225ccc19a68ea5d0f368632620d0 (diff) | |
download | mariadb-git-b7b5f6f1ab49948b0e15b762266d4640b3d6b7fb.tar.gz |
10.0-monty merge
includes:
* remove some remnants of "Bug#14521864: MYSQL 5.1 TO 5.5 BUGS PARTITIONING"
* introduce LOCK_share, now LOCK_ha_data is strictly for engines
* rea_create_table() always creates .par file (even in "frm-only" mode)
* fix a 5.6 bug, temp file leak on dummy ALTER TABLE
Diffstat (limited to 'storage/perfschema')
81 files changed, 3277 insertions, 1096 deletions
diff --git a/storage/perfschema/CMakeLists.txt b/storage/perfschema/CMakeLists.txt index 0c9713d45d4..ef644030317 100644 --- a/storage/perfschema/CMakeLists.txt +++ b/storage/perfschema/CMakeLists.txt @@ -118,6 +118,10 @@ table_tiws_by_index_usage.h table_tiws_by_table.h table_tlws_by_table.h table_users.h +cursor_by_thread_connect_attr.h +table_session_connect.h +table_session_connect_attrs.h +table_session_account_connect_attrs.h cursor_by_account.cc cursor_by_host.cc cursor_by_thread.cc @@ -126,6 +130,7 @@ ha_perfschema.cc pfs.cc pfs_account.cc pfs_atomic.cc +pfs_autosize.cc pfs_check.cc pfs_column_values.cc pfs_con_slice.cc @@ -189,6 +194,10 @@ table_tiws_by_index_usage.cc table_tiws_by_table.cc table_tlws_by_table.cc table_users.cc +cursor_by_thread_connect_attr.cc +table_session_connect.cc +table_session_connect_attrs.cc +table_session_account_connect_attrs.cc ) MYSQL_ADD_PLUGIN(perfschema ${PERFSCHEMA_SOURCES} STORAGE_ENGINE DEFAULT STATIC_ONLY) diff --git a/storage/perfschema/cursor_by_thread_connect_attr.cc b/storage/perfschema/cursor_by_thread_connect_attr.cc new file mode 100644 index 00000000000..7a0dd04119d --- /dev/null +++ b/storage/perfschema/cursor_by_thread_connect_attr.cc @@ -0,0 +1,71 @@ +/* Copyright (c) 2008, 2011, 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#include "my_global.h" +#include "cursor_by_thread_connect_attr.h" + +cursor_by_thread_connect_attr::cursor_by_thread_connect_attr( + const PFS_engine_table_share *share) : + PFS_engine_table(share, &m_pos), m_row_exists(false) +{} + +int cursor_by_thread_connect_attr::rnd_next(void) +{ + PFS_thread *thread; + + for (m_pos.set_at(&m_next_pos); + m_pos.has_more_thread(); + m_pos.next_thread()) + { + thread= &thread_array[m_pos.m_index_1]; + + if (thread->m_lock.is_populated()) + { + make_row(thread, m_pos.m_index_2); + if (m_row_exists) + { + m_next_pos.set_after(&m_pos); + return 0; + } + } + } + return HA_ERR_END_OF_FILE; +} + + +int cursor_by_thread_connect_attr::rnd_pos(const void *pos) +{ + PFS_thread *thread; + + set_position(pos); + DBUG_ASSERT(m_pos.m_index_1 < thread_max); + + thread= &thread_array[m_pos.m_index_1]; + if (!thread->m_lock.is_populated()) + return HA_ERR_RECORD_DELETED; + + make_row(thread, m_pos.m_index_2); + if (m_row_exists) + return 0; + + return HA_ERR_RECORD_DELETED; +} + + +void cursor_by_thread_connect_attr::reset_position(void) +{ + m_pos.reset(); + m_next_pos.reset(); +} diff --git a/storage/perfschema/cursor_by_thread_connect_attr.h b/storage/perfschema/cursor_by_thread_connect_attr.h new file mode 100644 index 00000000000..fbce56f208d --- /dev/null +++ b/storage/perfschema/cursor_by_thread_connect_attr.h @@ -0,0 +1,81 @@ +/* Copyright (c) 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef CURSOR_BY_THREAD_CONNECT_ATTR_H +#define CURSOR_BY_THREAD_CONNECT_ATTR_H + +#include "pfs_column_types.h" +#include "pfs_engine_table.h" +#include "pfs_instr.h" + +/** + \addtogroup Performance_schema_tables + @{ +*/ + +struct pos_connect_attr_by_thread_by_attr +: public PFS_double_index +{ + pos_connect_attr_by_thread_by_attr() + : PFS_double_index(0, 0) + {} + + inline bool has_more_thread(void) + { + return (m_index_1 < thread_max); + } + + inline void next_thread(void) + { + m_index_1++; + m_index_2= 0; + } + + inline void reset(void) + { + m_index_1= 0; + m_index_2= 0; + } +}; + +/** Cursor CURSOR_BY_THREAD_CONNECT_ATTR. */ +class cursor_by_thread_connect_attr : public PFS_engine_table +{ +public: + virtual int rnd_next(); + virtual int rnd_pos(const void *pos); + virtual void reset_position(void); + +protected: + cursor_by_thread_connect_attr(const PFS_engine_table_share *share); + +public: + ~cursor_by_thread_connect_attr() + {} + +protected: + virtual void make_row(PFS_thread *thread, uint ordinal)= 0; + /** True if row exists */ + bool m_row_exists; + +private: + /** Current position. */ + pos_connect_attr_by_thread_by_attr m_pos; + /** Next position. */ + pos_connect_attr_by_thread_by_attr m_next_pos; +}; + +/** @} */ +#endif diff --git a/storage/perfschema/gen_pfs_lex_token.cc b/storage/perfschema/gen_pfs_lex_token.cc index b7470061de1..7581255b284 100644 --- a/storage/perfschema/gen_pfs_lex_token.cc +++ b/storage/perfschema/gen_pfs_lex_token.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 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 @@ -243,7 +243,7 @@ void print_tokens() int main(int argc,char **argv) { puts("/*"); - puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2011, 2012")); + puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2011")); puts("*/"); printf("/*\n"); diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index aca5ad8c731..2934afefbe6 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -164,6 +164,8 @@ static struct st_mysql_show_var pfs_status_vars[]= (char*) &statement_class_lost, SHOW_LONG}, {"Performance_schema_digest_lost", (char*) &digest_lost, SHOW_LONG}, + {"Performance_schema_session_connect_attrs_lost", + (char*) &session_connect_attrs_lost, SHOW_LONG}, {NullS, NullS, SHOW_LONG} }; @@ -245,12 +247,12 @@ int ha_perfschema::write_row(uchar *buf) int result; DBUG_ENTER("ha_perfschema::write_row"); + if (!pfs_initialized) + DBUG_RETURN(HA_ERR_WRONG_COMMAND); - ha_statistic_increment(&SSV::ha_write_count); DBUG_ASSERT(m_table_share); - + ha_statistic_increment(&SSV::ha_write_count); result= m_table_share->write_row(table, buf, table->field); - DBUG_RETURN(result); } @@ -268,7 +270,9 @@ void ha_perfschema::use_hidden_primary_key(void) int ha_perfschema::update_row(const uchar *old_data, uchar *new_data) { DBUG_ENTER("ha_perfschema::update_row"); - + if (!pfs_initialized) + DBUG_RETURN(HA_ERR_WRONG_COMMAND); + DBUG_ASSERT(m_table); ha_statistic_increment(&SSV::ha_update_count); int result= m_table->update_row(table, old_data, new_data, table->field); @@ -278,6 +282,8 @@ int ha_perfschema::update_row(const uchar *old_data, uchar *new_data) int ha_perfschema::delete_row(const uchar *buf) { DBUG_ENTER("ha_perfschema::delete_row"); + if (!pfs_initialized) + DBUG_RETURN(HA_ERR_WRONG_COMMAND); DBUG_ASSERT(m_table); ha_statistic_increment(&SSV::ha_delete_count); @@ -318,6 +324,8 @@ int ha_perfschema::rnd_end(void) int ha_perfschema::rnd_next(uchar *buf) { DBUG_ENTER("ha_perfschema::rnd_next"); + if (!pfs_initialized) + DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_ASSERT(m_table); ha_statistic_increment(&SSV::ha_read_rnd_next_count); @@ -344,6 +352,8 @@ void ha_perfschema::position(const uchar *record) int ha_perfschema::rnd_pos(uchar *buf, uchar *pos) { DBUG_ENTER("ha_perfschema::rnd_pos"); + if (!pfs_initialized) + DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_ASSERT(m_table); ha_statistic_increment(&SSV::ha_read_rnd_count); @@ -369,6 +379,8 @@ int ha_perfschema::delete_all_rows(void) int result; DBUG_ENTER("ha_perfschema::delete_all_rows"); + if (!pfs_initialized) + DBUG_RETURN(0); DBUG_ASSERT(m_table_share); if (m_table_share->m_delete_all_rows) diff --git a/storage/perfschema/ha_perfschema.h b/storage/perfschema/ha_perfschema.h index e088c79b26f..f8ed3ea52e0 100644 --- a/storage/perfschema/ha_perfschema.h +++ b/storage/perfschema/ha_perfschema.h @@ -70,8 +70,7 @@ public: records. */ return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT | - HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | - HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | HA_HAS_OWN_BINLOGGING); + HA_PRIMARY_KEY_REQUIRED_FOR_DELETE); } /** diff --git a/storage/perfschema/pfs.cc b/storage/perfschema/pfs.cc index d3de38d025c..33b21ee2817 100644 --- a/storage/perfschema/pfs.cc +++ b/storage/perfschema/pfs.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2013, 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 @@ -688,6 +688,7 @@ static inline int mysql_mutex_lock(...) - socket io (MYSQL_SOCKET) - table io - table lock + - idle The flow of data between aggregates tables varies for each instrumentation. @@ -857,24 +858,35 @@ static inline int mysql_mutex_lock(...) @subsection IMPL_WAIT_SOCKET Socket waits @verbatim - socket_locker(T, F) + socket_locker(T, S) | | [1] | - |-> pfs_socket(F) =====>> [A], [B], [C], [D], [E] + |-> pfs_socket(S) =====>> [A], [B], [C], [D], [E] | | [2] | - |-> pfs_socket_class(F.class) =====>> [C], [D] + |-> pfs_socket_class(S.class) =====>> [C], [D] | - |-> pfs_thread(T).event_name(F) =====>> [A] + |-> pfs_thread(T).event_name(S) =====>> [A] | - ... + | [3] + | + 3a |-> pfs_account(U, H).event_name(S) =====>> [F], [G], [H] + . | + . | [4-RESET] + . | + 3b .....+-> pfs_user(U).event_name(S) =====>> [G] + . | + 3c .....+-> pfs_host(H).event_name(S) =====>> [H] @endverbatim Implemented as: - [1] @c start_socket_wait_v1(), @c end_socket_wait_v1(). - [2] @c close_socket_v1() + - [3] @c aggregate_thread_waits() + - [4] @c PFS_account::aggregate_waits() + - [5] @c PFS_host::aggregate_waits() - [A] EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME, @c table_ews_by_thread_by_event_name::make_row() - [B] EVENTS_WAITS_SUMMARY_BY_INSTANCE, @@ -885,37 +897,78 @@ static inline int mysql_mutex_lock(...) @c table_socket_summary_by_event_name::make_row() - [E] SOCKET_SUMMARY_BY_INSTANCE, @c table_socket_summary_by_instance::make_row() + - [F] EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME, + @c table_ews_by_account_by_event_name::make_row() + - [G] EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME, + @c table_ews_by_user_by_event_name::make_row() + - [H] EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME, + @c table_ews_by_host_by_event_name::make_row() @subsection IMPL_WAIT_TABLE Table waits @verbatim - table_locker(T, Tb) + table_locker(Thread Th, Table Tb, Event = io or lock) | | [1] | - |-> pfs_table(Tb) =====>> [B], [C], [D] - | - | [2] - | - |-> pfs_table_share(Tb.share) =====>> [C], [D] - | - |-> pfs_thread(T).event_name(Tb) =====>> [A] - | - ... +1a |-> pfs_table(Tb) =====>> [A], [B], [C] + | | + | | [2] + | | + | |-> pfs_table_share(Tb.share) =====>> [B], [C] + | | + | | [3] + | | + | |-> global_table_io_stat =====>> [C] + | | + | |-> global_table_lock_stat =====>> [C] + | +1b |-> pfs_thread(Th).event_name(E) =====>> [D], [E], [F], [G] + | | + | | [ 4-RESET] + | | + | |-> pfs_account(U, H).event_name(E) =====>> [E], [F], [G] + | . | + | . | [5-RESET] + | . | + | .....+-> pfs_user(U).event_name(E) =====>> [F] + | . | + | .....+-> pfs_host(H).event_name(E) =====>> [G] + | +1c |-> pfs_thread(Th).waits_current(W) =====>> [H] + | +1d |-> pfs_thread(Th).waits_history(W) =====>> [I] + | +1e |-> waits_history_long(W) =====>> [J] @endverbatim Implemented as: - [1] @c start_table_io_wait_v1(), @c end_table_io_wait_v1() - [2] @c close_table_v1() - - [A] EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME, - @c table_ews_by_thread_by_event_name::make_row() - - [B] EVENTS_WAITS_SUMMARY_BY_INSTANCE, + - [3] @c drop_table_share_v1() + - [4] @c TRUNCATE TABLE EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME + - [5] @c TRUNCATE TABLE EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME + - [A] EVENTS_WAITS_SUMMARY_BY_INSTANCE, @c table_events_waits_summary_by_instance::make_table_row() + - [B] OBJECTS_SUMMARY_GLOBAL_BY_TYPE, + @c table_os_global_by_type::make_row() - [C] EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME, @c table_ews_global_by_event_name::make_table_io_row(), @c table_ews_global_by_event_name::make_table_lock_row() - - [D] OBJECTS_SUMMARY_GLOBAL_BY_TYPE, - @c table_os_global_by_type::make_row() + - [D] EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME, + @c table_ews_by_thread_by_event_name::make_row() + - [E] EVENTS_WAITS_SUMMARY_BY_ACCOUNT_BY_EVENT_NAME, + @c table_ews_by_user_by_account_name::make_row() + - [F] EVENTS_WAITS_SUMMARY_BY_USER_BY_EVENT_NAME, + @c table_ews_by_user_by_event_name::make_row() + - [G] EVENTS_WAITS_SUMMARY_BY_HOST_BY_EVENT_NAME, + @c table_ews_by_host_by_event_name::make_row() + - [H] EVENTS_WAITS_CURRENT, + @c table_events_waits_common::make_row() + - [I] EVENTS_WAITS_HISTORY, + @c table_events_waits_common::make_row() + - [J] EVENTS_WAITS_HISTORY_LONG, + @c table_events_waits_common::make_row() @section IMPL_STAGE Implementation for stages aggregates @@ -1594,7 +1647,6 @@ static void unbind_table_v1(PSI_table *table) PFS_table *pfs= reinterpret_cast<PFS_table*> (table); if (likely(pfs != NULL)) { - pfs->aggregate(); pfs->m_thread_owner= NULL; } } @@ -1615,12 +1667,6 @@ rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table) /* The table handle was already instrumented, reuse it for this thread. */ thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); - if (unlikely(thread == NULL)) - { - destroy_table(pfs); - return NULL; - } - if (unlikely(! pfs->m_share->m_enabled)) { destroy_table(pfs); @@ -1660,8 +1706,6 @@ rebind_table_v1(PSI_table_share *share, const void *identity, PSI_table *table) return NULL; PFS_thread *thread= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); - if (unlikely(thread == NULL)) - return NULL; PFS_table *pfs_table= create_table(pfs_table_share, thread, identity); return reinterpret_cast<PSI_table *> (pfs_table); @@ -1681,9 +1725,18 @@ static void close_table_v1(PSI_table *table) } static PSI_socket* -init_socket_v1(PSI_socket_key key, const my_socket *fd) +init_socket_v1(PSI_socket_key key, const my_socket *fd, + const struct sockaddr *addr, socklen_t addr_len) { - INIT_BODY_V1(socket, key, fd); + PFS_socket_class *klass; + PFS_socket *pfs; + klass= find_socket_class(key); + if (unlikely(klass == NULL)) + return NULL; + if (! klass->m_enabled) + return NULL; + pfs= create_socket(klass, fd, addr, addr_len); + return reinterpret_cast<PSI_socket *> (pfs); } static void destroy_socket_v1(PSI_socket *socket) @@ -1731,7 +1784,7 @@ static void create_file_v1(PSI_file_key key, const char *name, File file) } uint len= strlen(name); - PFS_file *pfs_file= find_or_create_file(pfs_thread, klass, name, len); + PFS_file *pfs_file= find_or_create_file(pfs_thread, klass, name, len, true); file_handle_array[index]= pfs_file; } @@ -1835,13 +1888,13 @@ static int spawn_thread_v1(PSI_thread_key key, @sa PSI_v1::new_thread. */ static PSI_thread* -new_thread_v1(PSI_thread_key key, const void *identity, ulong thread_id) +new_thread_v1(PSI_thread_key key, const void *identity, ulonglong processlist_id) { PFS_thread *pfs; PFS_thread_class *klass= find_thread_class(key); if (likely(klass != NULL)) - pfs= create_thread(klass, identity, thread_id); + pfs= create_thread(klass, identity, processlist_id); else pfs= NULL; @@ -1852,12 +1905,12 @@ new_thread_v1(PSI_thread_key key, const void *identity, ulong thread_id) Implementation of the thread instrumentation interface. @sa PSI_v1::set_thread_id. */ -static void set_thread_id_v1(PSI_thread *thread, unsigned long id) +static void set_thread_id_v1(PSI_thread *thread, ulonglong processlist_id) { PFS_thread *pfs= reinterpret_cast<PFS_thread*> (thread); if (unlikely(pfs == NULL)) return; - pfs->m_thread_id= id; + pfs->m_processlist_id= processlist_id; } /** @@ -2045,10 +2098,10 @@ static void set_thread_state_v1(const char* state) { int state_len= state ? strlen(state) : 0; - pfs->m_lock.allocated_to_dirty(); + pfs->m_processlist_lock.allocated_to_dirty(); pfs->m_processlist_state_ptr= state; pfs->m_processlist_state_length= state_len; - pfs->m_lock.dirty_to_allocated(); + pfs->m_processlist_lock.dirty_to_allocated(); } } @@ -2060,12 +2113,14 @@ static void set_thread_info_v1(const char* info, int info_len) { PFS_thread *pfs= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); + DBUG_ASSERT((info != NULL) || (info_len == 0)); + if (likely(pfs != NULL)) { - pfs->m_lock.allocated_to_dirty(); + pfs->m_processlist_lock.allocated_to_dirty(); pfs->m_processlist_info_ptr= info; pfs->m_processlist_info_length= info_len; - pfs->m_lock.dirty_to_allocated(); + pfs->m_processlist_lock.dirty_to_allocated(); } } @@ -2196,7 +2251,7 @@ start_mutex_wait_v1(PSI_mutex_locker_state *state, Complete shortcut. */ /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */ - pfs_mutex->m_wait_stat.aggregate_counted(); + pfs_mutex->m_mutex_stat.m_wait_stat.aggregate_counted(); return NULL; } } @@ -2294,7 +2349,7 @@ start_rwlock_wait_v1(PSI_rwlock_locker_state *state, Complete shortcut. */ /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */ - pfs_rwlock->m_wait_stat.aggregate_counted(); + pfs_rwlock->m_rwlock_stat.m_wait_stat.aggregate_counted(); return NULL; } } @@ -2401,7 +2456,7 @@ start_cond_wait_v1(PSI_cond_locker_state *state, Complete shortcut. */ /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */ - pfs_cond->m_wait_stat.aggregate_counted(); + pfs_cond->m_cond_stat.m_wait_stat.aggregate_counted(); return NULL; } } @@ -2478,8 +2533,6 @@ start_table_io_wait_v1(PSI_table_locker_state *state, return NULL; PFS_thread *pfs_thread= pfs_table->m_thread_owner; - if (unlikely(pfs_thread == NULL)) - return NULL; DBUG_ASSERT(pfs_thread == my_pthread_getspecific_ptr(PFS_thread*, THR_PFS)); @@ -2489,6 +2542,8 @@ start_table_io_wait_v1(PSI_table_locker_state *state, if (flag_thread_instrumentation) { + if (pfs_thread == NULL) + return NULL; if (! pfs_thread->m_enabled) return NULL; state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread); @@ -2538,7 +2593,6 @@ start_table_io_wait_v1(PSI_table_locker_state *state, pfs_thread->m_events_waits_current++; } - /* TODO: consider a shortcut here */ } else { @@ -2585,11 +2639,6 @@ start_table_lock_wait_v1(PSI_table_locker_state *state, return NULL; PFS_thread *pfs_thread= pfs_table->m_thread_owner; - if (unlikely(pfs_thread == NULL)) - return NULL; - - DBUG_ASSERT(pfs_thread == - my_pthread_getspecific_ptr(PFS_thread*, THR_PFS)); PFS_TL_LOCK_TYPE lock_type; @@ -2619,6 +2668,8 @@ start_table_lock_wait_v1(PSI_table_locker_state *state, if (flag_thread_instrumentation) { + if (pfs_thread == NULL) + return NULL; if (! pfs_thread->m_enabled) return NULL; state->m_thread= reinterpret_cast<PSI_thread *> (pfs_thread); @@ -2668,7 +2719,6 @@ start_table_lock_wait_v1(PSI_table_locker_state *state, pfs_thread->m_events_waits_current++; } - /* TODO: consider a shortcut here */ } else { @@ -2729,11 +2779,6 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state, if (klass->m_timed) flags|= STATE_FLAG_TIMED; - uint len= strlen(name); - PFS_file *pfs_file= find_or_create_file(pfs_thread, klass, name, len); - if (unlikely(pfs_file == NULL)) - return NULL; - if (flag_events_waits_current) { if (unlikely(pfs_thread->m_events_waits_current >= @@ -2755,9 +2800,9 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state, wait->m_class= klass; wait->m_timer_start= 0; wait->m_timer_end= 0; - wait->m_object_instance_addr= pfs_file; - wait->m_weak_file= pfs_file; - wait->m_weak_version= pfs_file->get_version(); + wait->m_object_instance_addr= NULL; + wait->m_weak_file= NULL; + wait->m_weak_version= 0; wait->m_event_id= pfs_thread->m_event_id++; wait->m_end_event_id= 0; wait->m_operation= file_operation_map[static_cast<int> (op)]; @@ -2767,7 +2812,9 @@ get_thread_file_name_locker_v1(PSI_file_locker_state *state, } state->m_flags= flags; - state->m_file= reinterpret_cast<PSI_file*> (pfs_file); + state->m_file= NULL; + state->m_name= name; + state->m_class= klass; state->m_operation= op; return reinterpret_cast<PSI_file_locker*> (state); } @@ -2788,6 +2835,7 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state, if (unlikely(pfs_file == NULL)) return NULL; DBUG_ASSERT(pfs_file->m_class != NULL); + PFS_file_class *klass= pfs_file->m_class; if (! pfs_file->m_enabled) return NULL; @@ -2825,7 +2873,7 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state, wait->m_nesting_event_type= parent_event->m_event_type; wait->m_thread= pfs_thread; - wait->m_class= pfs_file->m_class; + wait->m_class= klass; wait->m_timer_start= 0; wait->m_timer_end= 0; wait->m_object_instance_addr= pfs_file; @@ -2856,6 +2904,8 @@ get_thread_file_stream_locker_v1(PSI_file_locker_state *state, state->m_flags= flags; state->m_file= reinterpret_cast<PSI_file*> (pfs_file); state->m_operation= op; + state->m_name= NULL; + state->m_class= klass; return reinterpret_cast<PSI_file_locker*> (state); } @@ -2890,10 +2940,12 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, if (op == PSI_FILE_CLOSE) file_handle_array[index]= NULL; - DBUG_ASSERT(pfs_file->m_class != NULL); if (! pfs_file->m_enabled) return NULL; + DBUG_ASSERT(pfs_file->m_class != NULL); + PFS_file_class *klass= pfs_file->m_class; + register uint flags; if (flag_thread_instrumentation) @@ -2927,7 +2979,7 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, wait->m_nesting_event_type= parent_event->m_event_type; wait->m_thread= pfs_thread; - wait->m_class= pfs_file->m_class; + wait->m_class= klass; wait->m_timer_start= 0; wait->m_timer_end= 0; wait->m_object_instance_addr= pfs_file; @@ -2958,6 +3010,8 @@ get_thread_file_descriptor_locker_v1(PSI_file_locker_state *state, state->m_flags= flags; state->m_file= reinterpret_cast<PSI_file*> (pfs_file); state->m_operation= op; + state->m_name= NULL; + state->m_class= klass; return reinterpret_cast<PSI_file_locker*> (state); } @@ -2991,14 +3045,6 @@ start_socket_wait_v1(PSI_socket_locker_state *state, if (unlikely(pfs_thread == NULL)) return NULL; -#ifdef LATER - /* - Needs refinement, because of KILL. - */ - DBUG_ASSERT(pfs_thread == - my_pthread_getspecific_ptr(PFS_thread*, THR_PFS)); -#endif - if (!pfs_thread->m_enabled) return NULL; @@ -3112,22 +3158,15 @@ static void unlock_mutex_v1(PSI_mutex *mutex) PFS_mutex::m_lock_stat is not exposed in user visible tables currently, so there is no point spending time computing it. */ - PFS_thread *pfs_thread= reinterpret_cast<PFS_thread*> (thread); - DBUG_ASSERT(pfs_thread != NULL); - - if (unlikely(! flag_events_waits_current)) - return; - if (! pfs_mutex->m_class->m_enabled) + if (! pfs_mutex->m_enabled) return; - if (! pfs_thread->m_enabled) + + if (! pfs_mutex->m_timed) return; - if (pfs_mutex->m_class->m_timed) - { - ulonglong locked_time; - locked_time= get_timer_pico_value(wait_timer) - pfs_mutex->m_last_locked; - aggregate_single_stat_chain(&pfs_mutex->m_lock_stat, locked_time); - } + ulonglong locked_time; + locked_time= get_timer_pico_value(wait_timer) - pfs_mutex->m_last_locked; + pfs_mutex->m_mutex_stat.m_lock_stat.aggregate_value(locked_time); #endif } @@ -3185,32 +3224,23 @@ static void unlock_rwlock_v1(PSI_rwlock *rwlock) #ifdef LATER_WL2333 /* See WL#2333: SHOW ENGINE ... LOCK STATUS. */ - PFS_thread *pfs_thread= reinterpret_cast<PFS_thread*> (thread); - DBUG_ASSERT(pfs_thread != NULL); - if (unlikely(! flag_events_waits_current)) - return; - if (! pfs_rwlock->m_class->m_enabled) + if (! pfs_rwlock->m_enabled) return; - if (! pfs_thread->m_enabled) + + if (! pfs_rwlock->m_timed) return; ulonglong locked_time; if (last_writer) { - if (pfs_rwlock->m_class->m_timed) - { - locked_time= get_timer_pico_value(wait_timer) - pfs_rwlock->m_last_written; - aggregate_single_stat_chain(&pfs_rwlock->m_write_lock_stat, locked_time); - } + locked_time= get_timer_pico_value(wait_timer) - pfs_rwlock->m_last_written; + pfs_rwlock->m_rwlock_stat.m_write_lock_stat.aggregate_value(locked_time); } else if (last_reader) { - if (pfs_rwlock->m_class->m_timed) - { - locked_time= get_timer_pico_value(wait_timer) - pfs_rwlock->m_last_read; - aggregate_single_stat_chain(&pfs_rwlock->m_read_lock_stat, locked_time); - } + locked_time= get_timer_pico_value(wait_timer) - pfs_rwlock->m_last_read; + pfs_rwlock->m_rwlock_stat.m_read_lock_stat.aggregate_value(locked_time); } #else (void) last_reader; @@ -3352,17 +3382,16 @@ static void end_idle_wait_v1(PSI_idle_locker* locker) PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread); PFS_single_stat *event_name_array; event_name_array= thread->m_instr_class_waits_stats; - uint index= global_idle_class.m_event_name_index; if (flags & STATE_FLAG_TIMED) { /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (timed) */ - event_name_array[index].aggregate_value(wait_time); + event_name_array[GLOBAL_IDLE_EVENT_INDEX].aggregate_value(wait_time); } else { /* Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME (counted) */ - event_name_array[index].aggregate_counted(); + event_name_array[GLOBAL_IDLE_EVENT_INDEX].aggregate_counted(); } if (flags & STATE_FLAG_EVENT) @@ -3379,6 +3408,17 @@ static void end_idle_wait_v1(PSI_idle_locker* locker) thread->m_events_waits_current--; } } + + if (flags & STATE_FLAG_TIMED) + { + /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME (timed) */ + global_idle_stat.aggregate_value(wait_time); + } + else + { + /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME (counted) */ + global_idle_stat.aggregate_counted(); + } } /** @@ -3404,12 +3444,12 @@ static void end_mutex_wait_v1(PSI_mutex_locker* locker, int rc) timer_end= state->m_timer(); wait_time= timer_end - state->m_timer_start; /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (timed) */ - mutex->m_wait_stat.aggregate_value(wait_time); + mutex->m_mutex_stat.m_wait_stat.aggregate_value(wait_time); } else { /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */ - mutex->m_wait_stat.aggregate_counted(); + mutex->m_mutex_stat.m_wait_stat.aggregate_counted(); } if (likely(rc == 0)) @@ -3471,12 +3511,12 @@ static void end_rwlock_rdwait_v1(PSI_rwlock_locker* locker, int rc) timer_end= state->m_timer(); wait_time= timer_end - state->m_timer_start; /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (timed) */ - rwlock->m_wait_stat.aggregate_value(wait_time); + rwlock->m_rwlock_stat.m_wait_stat.aggregate_value(wait_time); } else { /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */ - rwlock->m_wait_stat.aggregate_counted(); + rwlock->m_rwlock_stat.m_wait_stat.aggregate_counted(); } if (rc == 0) @@ -3551,12 +3591,12 @@ static void end_rwlock_wrwait_v1(PSI_rwlock_locker* locker, int rc) timer_end= state->m_timer(); wait_time= timer_end - state->m_timer_start; /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (timed) */ - rwlock->m_wait_stat.aggregate_value(wait_time); + rwlock->m_rwlock_stat.m_wait_stat.aggregate_value(wait_time); } else { /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */ - rwlock->m_wait_stat.aggregate_counted(); + rwlock->m_rwlock_stat.m_wait_stat.aggregate_counted(); } if (likely(rc == 0)) @@ -3622,12 +3662,12 @@ static void end_cond_wait_v1(PSI_cond_locker* locker, int rc) timer_end= state->m_timer(); wait_time= timer_end - state->m_timer_start; /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (timed) */ - cond->m_wait_stat.aggregate_value(wait_time); + cond->m_cond_stat.m_wait_stat.aggregate_value(wait_time); } else { /* Aggregate to EVENTS_WAITS_SUMMARY_BY_INSTANCE (counted) */ - cond->m_wait_stat.aggregate_counted(); + cond->m_cond_stat.m_wait_stat.aggregate_counted(); } if (state->m_flags & STATE_FLAG_THREAD) @@ -3682,23 +3722,27 @@ static void end_table_io_wait_v1(PSI_table_locker* locker) DBUG_ASSERT(table != NULL); PFS_single_stat *stat; + PFS_table_io_stat *table_io_stat; DBUG_ASSERT((state->m_index < table->m_share->m_key_count) || - (state->m_index == MAX_KEY)); + (state->m_index == MAX_INDEXES)); + + table_io_stat= & table->m_table_stat.m_index_stat[state->m_index]; + table_io_stat->m_has_data= true; switch (state->m_io_operation) { case PSI_TABLE_FETCH_ROW: - stat= & table->m_table_stat.m_index_stat[state->m_index].m_fetch; + stat= & table_io_stat->m_fetch; break; case PSI_TABLE_WRITE_ROW: - stat= & table->m_table_stat.m_index_stat[state->m_index].m_insert; + stat= & table_io_stat->m_insert; break; case PSI_TABLE_UPDATE_ROW: - stat= & table->m_table_stat.m_index_stat[state->m_index].m_update; + stat= & table_io_stat->m_update; break; case PSI_TABLE_DELETE_ROW: - stat= & table->m_table_stat.m_index_stat[state->m_index].m_delete; + stat= & table_io_stat->m_delete; break; default: DBUG_ASSERT(false); @@ -3719,22 +3763,40 @@ static void end_table_io_wait_v1(PSI_table_locker* locker) stat->aggregate_counted(); } - if (flags & STATE_FLAG_EVENT) + if (flags & STATE_FLAG_THREAD) { - DBUG_ASSERT(flags & STATE_FLAG_THREAD); PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread); DBUG_ASSERT(thread != NULL); - PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait); - DBUG_ASSERT(wait != NULL); + PFS_single_stat *event_name_array; + event_name_array= thread->m_instr_class_waits_stats; - wait->m_timer_end= timer_end; - wait->m_end_event_id= thread->m_event_id; - if (flag_events_waits_history) - insert_events_waits_history(thread, wait); - if (flag_events_waits_history_long) - insert_events_waits_history_long(wait); - thread->m_events_waits_current--; + /* + Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME + (for wait/io/table/sql/handler) + */ + if (flags & STATE_FLAG_TIMED) + { + event_name_array[GLOBAL_TABLE_IO_EVENT_INDEX].aggregate_value(wait_time); + } + else + { + event_name_array[GLOBAL_TABLE_IO_EVENT_INDEX].aggregate_counted(); + } + + if (flags & STATE_FLAG_EVENT) + { + PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait); + DBUG_ASSERT(wait != NULL); + + wait->m_timer_end= timer_end; + wait->m_end_event_id= thread->m_event_id; + if (flag_events_waits_history) + insert_events_waits_history(thread, wait); + if (flag_events_waits_history_long) + insert_events_waits_history_long(wait); + thread->m_events_waits_current--; + } } table->m_has_io_stats= true; @@ -3770,22 +3832,40 @@ static void end_table_lock_wait_v1(PSI_table_locker* locker) stat->aggregate_counted(); } - if (flags & STATE_FLAG_EVENT) + if (flags & STATE_FLAG_THREAD) { - DBUG_ASSERT(flags & STATE_FLAG_THREAD); PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread); DBUG_ASSERT(thread != NULL); - PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait); - DBUG_ASSERT(wait != NULL); + PFS_single_stat *event_name_array; + event_name_array= thread->m_instr_class_waits_stats; - wait->m_timer_end= timer_end; - wait->m_end_event_id= thread->m_event_id; - if (flag_events_waits_history) - insert_events_waits_history(thread, wait); - if (flag_events_waits_history_long) - insert_events_waits_history_long(wait); - thread->m_events_waits_current--; + /* + Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME + (for wait/lock/table/sql/handler) + */ + if (flags & STATE_FLAG_TIMED) + { + event_name_array[GLOBAL_TABLE_LOCK_EVENT_INDEX].aggregate_value(wait_time); + } + else + { + event_name_array[GLOBAL_TABLE_LOCK_EVENT_INDEX].aggregate_counted(); + } + + if (flags & STATE_FLAG_EVENT) + { + PFS_events_waits *wait= reinterpret_cast<PFS_events_waits*> (state->m_wait); + DBUG_ASSERT(wait != NULL); + + wait->m_timer_end= timer_end; + wait->m_end_event_id= thread->m_event_id; + if (flag_events_waits_history) + insert_events_waits_history(thread, wait); + if (flag_events_waits_history_long) + insert_events_waits_history_long(wait); + thread->m_events_waits_current--; + } } table->m_has_lock_stats= true; @@ -3803,25 +3883,50 @@ static void end_file_wait_v1(PSI_file_locker *locker, Implementation of the file instrumentation interface. @sa PSI_v1::start_file_open_wait. */ -static PSI_file* start_file_open_wait_v1(PSI_file_locker *locker, - const char *src_file, - uint src_line) +static void start_file_open_wait_v1(PSI_file_locker *locker, + const char *src_file, + uint src_line) { - PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker); - DBUG_ASSERT(state != NULL); - start_file_wait_v1(locker, 0, src_file, src_line); - return state->m_file; + return; } /** Implementation of the file instrumentation interface. @sa PSI_v1::end_file_open_wait. */ -static void end_file_open_wait_v1(PSI_file_locker *locker) +static PSI_file* end_file_open_wait_v1(PSI_file_locker *locker, + void *result) { + PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker); + DBUG_ASSERT(state != NULL); + + switch (state->m_operation) + { + case PSI_FILE_STAT: + break; + case PSI_FILE_STREAM_OPEN: + case PSI_FILE_CREATE: + if (result != NULL) + { + PFS_file_class *klass= reinterpret_cast<PFS_file_class*> (state->m_class); + PFS_thread *thread= reinterpret_cast<PFS_thread*> (state->m_thread); + const char *name= state->m_name; + uint len= strlen(name); + PFS_file *pfs_file= find_or_create_file(thread, klass, name, len, true); + state->m_file= reinterpret_cast<PSI_file*> (pfs_file); + } + break; + case PSI_FILE_OPEN: + default: + DBUG_ASSERT(false); + break; + } + end_file_wait_v1(locker, 0); + + return state->m_file; } /** @@ -3831,25 +3936,33 @@ static void end_file_open_wait_v1(PSI_file_locker *locker) static void end_file_open_wait_and_bind_to_descriptor_v1 (PSI_file_locker *locker, File file) { + PFS_file *pfs_file= NULL; int index= (int) file; PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker); DBUG_ASSERT(state != NULL); - end_file_wait_v1(locker, 0); + if (index >= 0) + { + PFS_file_class *klass= reinterpret_cast<PFS_file_class*> (state->m_class); + PFS_thread *thread= reinterpret_cast<PFS_thread*> (state->m_thread); + const char *name= state->m_name; + uint len= strlen(name); + pfs_file= find_or_create_file(thread, klass, name, len, true); + state->m_file= reinterpret_cast<PSI_file*> (pfs_file); + } - PFS_file *pfs_file= reinterpret_cast<PFS_file*> (state->m_file); - DBUG_ASSERT(pfs_file != NULL); + end_file_wait_v1(locker, 0); if (likely(index >= 0)) { if (likely(index < file_handle_max)) file_handle_array[index]= pfs_file; else + { + if (pfs_file != NULL) + release_file(pfs_file); file_handle_lost++; - } - else - { - release_file(pfs_file); + } } } @@ -3896,7 +4009,7 @@ static void end_file_wait_v1(PSI_file_locker *locker, PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker); DBUG_ASSERT(state != NULL); PFS_file *file= reinterpret_cast<PFS_file *> (state->m_file); - DBUG_ASSERT(file != NULL); + PFS_file_class *klass= reinterpret_cast<PFS_file_class *> (state->m_class); PFS_thread *thread= reinterpret_cast<PFS_thread *> (state->m_thread); ulonglong timer_end= 0; @@ -3905,15 +4018,26 @@ static void end_file_wait_v1(PSI_file_locker *locker, register uint flags= state->m_flags; size_t bytes= ((int)byte_count > -1 ? byte_count : 0); + PFS_file_stat *file_stat; + + if (file != NULL) + { + file_stat= & file->m_file_stat; + } + else + { + file_stat= & klass->m_file_stat; + } + switch (state->m_operation) { /* Group read operations */ case PSI_FILE_READ: - byte_stat= &file->m_file_stat.m_io_stat.m_read; + byte_stat= &file_stat->m_io_stat.m_read; break; /* Group write operations */ case PSI_FILE_WRITE: - byte_stat= &file->m_file_stat.m_io_stat.m_write; + byte_stat= &file_stat->m_io_stat.m_write; break; /* Group remaining operations as miscellaneous */ case PSI_FILE_CREATE: @@ -3931,7 +4055,7 @@ static void end_file_wait_v1(PSI_file_locker *locker, case PSI_FILE_SYNC: case PSI_FILE_STAT: case PSI_FILE_CLOSE: - byte_stat= &file->m_file_stat.m_io_stat.m_misc; + byte_stat= &file_stat->m_io_stat.m_misc; break; default: DBUG_ASSERT(false); @@ -3959,7 +4083,7 @@ static void end_file_wait_v1(PSI_file_locker *locker, PFS_single_stat *event_name_array; event_name_array= thread->m_instr_class_waits_stats; - uint index= file->m_class->m_event_name_index; + uint index= klass->m_event_name_index; if (flags & STATE_FLAG_TIMED) { @@ -3980,6 +4104,9 @@ static void end_file_wait_v1(PSI_file_locker *locker, wait->m_timer_end= timer_end; wait->m_number_of_bytes= bytes; wait->m_end_event_id= thread->m_event_id; + wait->m_object_instance_addr= file; + wait->m_weak_file= file; + wait->m_weak_version= (file ? file->get_version() : 0); if (flag_events_waits_history) insert_events_waits_history(thread, wait); @@ -3988,22 +4115,79 @@ static void end_file_wait_v1(PSI_file_locker *locker, thread->m_events_waits_current--; } } +} - /* Release or destroy the file if necessary */ - switch(state->m_operation) +/** + Implementation of the file instrumentation interface. + @sa PSI_v1::start_file_close_wait. +*/ +static void start_file_close_wait_v1(PSI_file_locker *locker, + const char *src_file, + uint src_line) +{ + PFS_thread *thread; + const char *name; + uint len; + PFS_file *pfs_file; + PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker); + DBUG_ASSERT(state != NULL); + + switch (state->m_operation) { - case PSI_FILE_CLOSE: - case PSI_FILE_STREAM_CLOSE: - case PSI_FILE_STAT: - release_file(file); - break; case PSI_FILE_DELETE: - DBUG_ASSERT(thread != NULL); - destroy_file(thread, file); + thread= reinterpret_cast<PFS_thread*> (state->m_thread); + name= state->m_name; + len= strlen(name); + pfs_file= find_or_create_file(thread, NULL, name, len, false); + state->m_file= reinterpret_cast<PSI_file*> (pfs_file); + break; + case PSI_FILE_STREAM_CLOSE: + case PSI_FILE_CLOSE: break; default: + DBUG_ASSERT(false); break; } + + start_file_wait_v1(locker, 0, src_file, src_line); + + return; +} + +/** + Implementation of the file instrumentation interface. + @sa PSI_v1::end_file_close_wait. +*/ +static void end_file_close_wait_v1(PSI_file_locker *locker, int rc) +{ + PSI_file_locker_state *state= reinterpret_cast<PSI_file_locker_state*> (locker); + DBUG_ASSERT(state != NULL); + + end_file_wait_v1(locker, 0); + + if (rc == 0) + { + PFS_thread *thread= reinterpret_cast<PFS_thread*> (state->m_thread); + PFS_file *file= reinterpret_cast<PFS_file*> (state->m_file); + + /* Release or destroy the file if necessary */ + switch(state->m_operation) + { + case PSI_FILE_CLOSE: + case PSI_FILE_STREAM_CLOSE: + if (file != NULL) + release_file(file); + break; + case PSI_FILE_DELETE: + if (file != NULL) + destroy_file(thread, file); + break; + default: + DBUG_ASSERT(false); + break; + } + } + return; } static void start_stage_v1(PSI_stage_key key, const char *src_file, int src_line) @@ -4165,7 +4349,8 @@ static void end_stage_v1() static PSI_statement_locker* get_thread_statement_locker_v1(PSI_statement_locker_state *state, - PSI_statement_key key) + PSI_statement_key key, + const void *charset) { DBUG_ASSERT(state != NULL); if (! flag_global_instrumentation) @@ -4262,9 +4447,11 @@ get_thread_statement_locker_v1(PSI_statement_locker_state *state, if (flag_statements_digest) { + const CHARSET_INFO *cs= static_cast <const CHARSET_INFO*> (charset); flags|= STATE_FLAG_DIGEST; state->m_digest_state.m_last_id_index= 0; digest_reset(& state->m_digest_state.m_digest_storage); + state->m_digest_state.m_digest_storage.m_charset_number= cs->number; } state->m_discarded= false; @@ -4288,6 +4475,8 @@ get_thread_statement_locker_v1(PSI_statement_locker_state *state, state->m_no_index_used= 0; state->m_no_good_index_used= 0; + state->m_schema_name_length= 0; + return reinterpret_cast<PSI_statement_locker*> (state); } @@ -4352,6 +4541,13 @@ static void start_statement_v1(PSI_statement_locker *locker, state->m_timer_start= timer_start; } + compile_time_assert(PSI_SCHEMA_NAME_LEN == NAME_LEN); + DBUG_ASSERT(db_len <= sizeof(state->m_schema_name)); + + if (db_len > 0) + memcpy(state->m_schema_name, db, db_len); + state->m_schema_name_length= db_len; + if (flags & STATE_FLAG_EVENT) { PFS_events_statements *pfs= reinterpret_cast<PFS_events_statements*> (state->m_statement); @@ -4563,11 +4759,10 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da) if (flags & STATE_FLAG_DIGEST) { 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); + /* Populate PFS_statements_digest_stat with computed digest information.*/ + digest_stat= find_or_create_digest(thread, digest_storage, + state->m_schema_name, + state->m_schema_name_length); } if (flags & STATE_FLAG_EVENT) @@ -4633,11 +4828,10 @@ static void end_statement_v1(PSI_statement_locker *locker, void *stmt_da) { /* 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); + /* Populate statements_digest_stat with computed digest information. */ + digest_stat= find_or_create_digest(thread, digest_storage, + state->m_schema_name, + state->m_schema_name_length); } } @@ -4869,6 +5063,42 @@ static void set_socket_thread_owner_v1(PSI_socket *socket) pfs_socket->m_thread_owner= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); } + +/** + Implementation of the thread attribute connection interface + @sa PSI_v1::set_thread_connect_attr. +*/ +static int set_thread_connect_attrs_v1(const char *buffer, uint length, + const void *from_cs) +{ + + PFS_thread *thd= my_pthread_getspecific_ptr(PFS_thread*, THR_PFS); + + DBUG_ASSERT(buffer != NULL); + + if (likely(thd != NULL) && session_connect_attrs_size_per_thread > 0) + { + /* copy from the input buffer as much as we can fit */ + uint copy_size= (uint)(length < session_connect_attrs_size_per_thread ? + length : session_connect_attrs_size_per_thread); + thd->m_lock.allocated_to_dirty(); + memcpy(thd->m_session_connect_attrs, buffer, copy_size); + thd->m_session_connect_attrs_length= copy_size; + thd->m_session_connect_attrs_cs= (const CHARSET_INFO *) from_cs; + thd->m_lock.dirty_to_allocated(); + + if (copy_size == length) + return 0; + else + { + session_connect_attrs_lost++; + return 1; + } + } + return 0; +} + + /** Implementation of the instrumentation interface. @sa PSI_v1. @@ -4939,6 +5169,8 @@ PSI_v1 PFS_v1= end_file_open_wait_and_bind_to_descriptor_v1, start_file_wait_v1, end_file_wait_v1, + start_file_close_wait_v1, + end_file_close_wait_v1, start_stage_v1, end_stage_v1, get_thread_statement_locker_v1, @@ -4968,7 +5200,8 @@ PSI_v1 PFS_v1= set_socket_info_v1, set_socket_thread_owner_v1, pfs_digest_start_v1, - pfs_digest_add_token_v1 + pfs_digest_add_token_v1, + set_thread_connect_attrs_v1, }; static void* get_interface(int version) diff --git a/storage/perfschema/pfs_account.cc b/storage/perfschema/pfs_account.cc index 18716478681..b91039f6cd7 100644 --- a/storage/perfschema/pfs_account.cc +++ b/storage/perfschema/pfs_account.cc @@ -45,7 +45,7 @@ static PFS_single_stat *account_instr_class_waits_array= NULL; static PFS_stage_stat *account_instr_class_stages_array= NULL; static PFS_statement_stat *account_instr_class_statements_array= NULL; -static LF_HASH account_hash; +LF_HASH account_hash; static bool account_hash_inited= false; /** @@ -149,10 +149,11 @@ C_MODE_END */ int init_account_hash(void) { - if (! account_hash_inited) + if ((! account_hash_inited) && (account_max > 0)) { lf_hash_init(&account_hash, sizeof(PFS_account*), LF_HASH_UNIQUE, 0, 0, account_hash_get_key, &my_charset_bin); + /* account_hash.size= account_max; */ account_hash_inited= true; } return 0; diff --git a/storage/perfschema/pfs_account.h b/storage/perfschema/pfs_account.h index 77a9dfab7ba..1ac379e0fc9 100644 --- a/storage/perfschema/pfs_account.h +++ b/storage/perfschema/pfs_account.h @@ -46,7 +46,7 @@ struct PFS_account_key uint m_key_length; }; -struct PFS_account : PFS_connection_slice +struct PFS_ALIGNED PFS_account : PFS_connection_slice { public: inline void init_refcount(void) @@ -115,6 +115,8 @@ extern ulong account_lost; extern PFS_account *account_array; +extern LF_HASH account_hash; + /** @} */ #endif diff --git a/storage/perfschema/pfs_atomic.h b/storage/perfschema/pfs_atomic.h index ffb4c24ecbf..61b8c2b2804 100644 --- a/storage/perfschema/pfs_atomic.h +++ b/storage/perfschema/pfs_atomic.h @@ -43,6 +43,16 @@ public: } /** Atomic load. */ + static inline int64 load_64(volatile int64 *ptr) + { + int64 result; + rdlock(ptr); + result= my_atomic_load64(ptr); + rdunlock(ptr); + return result; + } + + /** Atomic load. */ static inline uint32 load_u32(volatile uint32 *ptr) { uint32 result; @@ -52,6 +62,16 @@ public: return result; } + /** Atomic load. */ + static inline uint64 load_u64(volatile uint64 *ptr) + { + uint64 result; + rdlock(ptr); + result= (uint64) my_atomic_load64((int64*) ptr); + rdunlock(ptr); + return result; + } + /** Atomic store. */ static inline void store_32(volatile int32 *ptr, int32 value) { @@ -61,6 +81,14 @@ public: } /** Atomic store. */ + static inline void store_64(volatile int64 *ptr, int64 value) + { + wrlock(ptr); + my_atomic_store64(ptr, value); + wrunlock(ptr); + } + + /** Atomic store. */ static inline void store_u32(volatile uint32 *ptr, uint32 value) { wrlock(ptr); @@ -68,6 +96,14 @@ public: wrunlock(ptr); } + /** Atomic store. */ + static inline void store_u64(volatile uint64 *ptr, uint64 value) + { + wrlock(ptr); + my_atomic_store64((int64*) ptr, (int64) value); + wrunlock(ptr); + } + /** Atomic add. */ static inline int32 add_32(volatile int32 *ptr, int32 value) { @@ -79,6 +115,16 @@ public: } /** Atomic add. */ + static inline int64 add_64(volatile int64 *ptr, int64 value) + { + int64 result; + wrlock(ptr); + result= my_atomic_add64(ptr, value); + wrunlock(ptr); + return result; + } + + /** Atomic add. */ static inline uint32 add_u32(volatile uint32 *ptr, uint32 value) { uint32 result; @@ -88,6 +134,16 @@ public: return result; } + /** Atomic add. */ + static inline uint64 add_u64(volatile uint64 *ptr, uint64 value) + { + uint64 result; + wrlock(ptr); + result= (uint64) my_atomic_add64((int64*) ptr, (int64) value); + wrunlock(ptr); + return result; + } + /** Atomic compare and swap. */ static inline bool cas_32(volatile int32 *ptr, int32 *old_value, int32 new_value) @@ -100,6 +156,17 @@ public: } /** Atomic compare and swap. */ + static inline bool cas_64(volatile int64 *ptr, int64 *old_value, + int64 new_value) + { + bool result; + wrlock(ptr); + result= my_atomic_cas64(ptr, old_value, new_value); + wrunlock(ptr); + return result; + } + + /** Atomic compare and swap. */ static inline bool cas_u32(volatile uint32 *ptr, uint32 *old_value, uint32 new_value) { @@ -111,6 +178,18 @@ public: return result; } + /** Atomic compare and swap. */ + static inline bool cas_u64(volatile uint64 *ptr, uint64 *old_value, + uint64 new_value) + { + bool result; + wrlock(ptr); + result= my_atomic_cas64((int64*) ptr, (int64*) old_value, + (uint64) new_value); + wrunlock(ptr); + return result; + } + private: static my_atomic_rwlock_t m_rwlock_array[256]; diff --git a/storage/perfschema/pfs_autosize.cc b/storage/perfschema/pfs_autosize.cc new file mode 100644 index 00000000000..38bd36d8321 --- /dev/null +++ b/storage/perfschema/pfs_autosize.cc @@ -0,0 +1,366 @@ +/* Copyright (c) 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +/** + @file storage/perfschema/pfs_autosize.cc + Private interface for the server (implementation). +*/ + +#include "my_global.h" +#include "sql_const.h" +#include "pfs_server.h" + +#include <algorithm> +using std::min; +using std::max; + +static const ulong fixed_mutex_instances= 500; +static const ulong fixed_rwlock_instances= 200; +static const ulong fixed_cond_instances= 50; +static const ulong fixed_file_instances= 200; +static const ulong fixed_socket_instances= 10; +static const ulong fixed_thread_instances= 50; + +static const ulong mutex_per_connection= 3; +static const ulong rwlock_per_connection= 1; +static const ulong cond_per_connection= 2; +static const ulong file_per_connection= 0; +static const ulong socket_per_connection= 1; +static const ulong thread_per_connection= 1; + +static const ulong mutex_per_handle= 0; +static const ulong rwlock_per_handle= 0; +static const ulong cond_per_handle= 0; +static const ulong file_per_handle= 0; +static const ulong socket_per_handle= 0; +static const ulong thread_per_handle= 0; + +static const ulong mutex_per_share= 5; +static const ulong rwlock_per_share= 3; +static const ulong cond_per_share= 1; +static const ulong file_per_share= 3; +static const ulong socket_per_share= 0; +static const ulong thread_per_share= 0; + +struct PFS_sizing_data +{ + /** Default value for @c PFS_param.m_account_sizing. */ + ulong m_account_sizing; + /** Default value for @c PFS_param.m_user_sizing. */ + ulong m_user_sizing; + /** Default value for @c PFS_param.m_host_sizing. */ + ulong m_host_sizing; + + /** Default value for @c PFS_param.m_events_waits_history_sizing. */ + ulong m_events_waits_history_sizing; + /** Default value for @c PFS_param.m_events_waits_history_long_sizing. */ + ulong m_events_waits_history_long_sizing; + /** Default value for @c PFS_param.m_events_stages_history_sizing. */ + ulong m_events_stages_history_sizing; + /** Default value for @c PFS_param.m_events_stages_history_long_sizing. */ + ulong m_events_stages_history_long_sizing; + /** Default value for @c PFS_param.m_events_statements_history_sizing. */ + ulong m_events_statements_history_sizing; + /** Default value for @c PFS_param.m_events_statements_history_long_sizing. */ + ulong m_events_statements_history_long_sizing; + /** Default value for @c PFS_param.m_digest_sizing. */ + ulong m_digest_sizing; + /** Default value for @c PFS_param.m_session_connect_attrs_sizing. */ + ulong m_session_connect_attrs_sizing; + + /** + Minimum number of tables to keep statistics for. + On small deployments, all the tables can fit into the table definition cache, + and this value can be 0. + On big deployments, the table definition cache is only a subset of all the tables + in the database, which are accounted for here. + */ + ulong m_min_number_of_tables; + + /** + Load factor for 'volatile' objects (mutexes, table handles, ...). + Instrumented objects that: + - use little memory + - are created/destroyed very frequently + should be stored in a low density (mostly empty) memory buffer, + to optimize for speed. + */ + float m_load_factor_volatile; + /** + Load factor for 'normal' objects (files). + Instrumented objects that: + - use a medium amount of memory + - are created/destroyed + should be stored in a medium density memory buffer, + as a trade off between space and speed. + */ + float m_load_factor_normal; + /** + Load factor for 'static' objects (table shares). + Instrumented objects that: + - use a lot of memory + - are created/destroyed very rarely + can be stored in a high density (mostly packed) memory buffer, + to optimize for space. + */ + float m_load_factor_static; +}; + +PFS_sizing_data small_data= +{ + /* Account / user / host */ + 10, 5, 20, + /* History sizes */ + 5, 100, 5, 100, 5, 100, + /* Digests */ + 1000, + /* Session connect attrs. */ + 512, + /* Min tables */ + 200, + /* Load factors */ + 0.90, 0.90, 0.90 +}; + +PFS_sizing_data medium_data= +{ + /* Account / user / host */ + 100, 100, 100, + /* History sizes */ + 10, 1000, 10, 1000, 10, 1000, + /* Digests */ + 5000, + /* Session connect attrs. */ + 512, + /* Min tables */ + 500, + /* Load factors */ + 0.70, 0.80, 0.90 +}; + +PFS_sizing_data large_data= +{ + /* Account / user / host */ + 100, 100, 100, + /* History sizes */ + 10, 10000, 10, 10000, 10, 10000, + /* Digests */ + 10000, + /* Session connect attrs. */ + 512, + /* Min tables */ + 10000, + /* Load factors */ + 0.50, 0.65, 0.80 +}; + +static inline ulong apply_load_factor(ulong raw_value, float factor) +{ + float value = ((float) raw_value) / factor; + return (ulong) ceil(value); +} + +PFS_sizing_data *estimate_hints(PFS_global_param *param) +{ + if ((param->m_hints.m_max_connections <= MAX_CONNECTIONS_DEFAULT) && + (param->m_hints.m_table_definition_cache <= TABLE_DEF_CACHE_DEFAULT) && + (param->m_hints.m_table_open_cache <= TABLE_OPEN_CACHE_DEFAULT)) + { + /* The my.cnf used is either unchanged, or lower than factory defaults. */ + return & small_data; + } + + if ((param->m_hints.m_max_connections <= MAX_CONNECTIONS_DEFAULT * 2) && + (param->m_hints.m_table_definition_cache <= TABLE_DEF_CACHE_DEFAULT * 2) && + (param->m_hints.m_table_open_cache <= TABLE_OPEN_CACHE_DEFAULT * 2)) + { + /* Some defaults have been increased, to "moderate" values. */ + return & medium_data; + } + + /* Looks like a server in production. */ + return & large_data; +} + +static void apply_heuristic(PFS_global_param *p, PFS_sizing_data *h) +{ + ulong count; + ulong con = p->m_hints.m_max_connections; + ulong handle = p->m_hints.m_table_open_cache; + ulong share = p->m_hints.m_table_definition_cache; + ulong file = p->m_hints.m_open_files_limit; + + if (p->m_table_sizing < 0) + { + count= handle; + + p->m_table_sizing= apply_load_factor(count, h->m_load_factor_volatile); + } + + if (p->m_table_share_sizing < 0) + { + count= share; + + count= max<ulong>(count, h->m_min_number_of_tables); + p->m_table_share_sizing= apply_load_factor(count, h->m_load_factor_static); + } + + if (p->m_account_sizing < 0) + { + p->m_account_sizing= h->m_account_sizing; + } + + if (p->m_user_sizing < 0) + { + p->m_user_sizing= h->m_user_sizing; + } + + if (p->m_host_sizing < 0) + { + p->m_host_sizing= h->m_host_sizing; + } + + if (p->m_events_waits_history_sizing < 0) + { + p->m_events_waits_history_sizing= h->m_events_waits_history_sizing; + } + + if (p->m_events_waits_history_long_sizing < 0) + { + p->m_events_waits_history_long_sizing= h->m_events_waits_history_long_sizing; + } + + if (p->m_events_stages_history_sizing < 0) + { + p->m_events_stages_history_sizing= h->m_events_stages_history_sizing; + } + + if (p->m_events_stages_history_long_sizing < 0) + { + p->m_events_stages_history_long_sizing= h->m_events_stages_history_long_sizing; + } + + if (p->m_events_statements_history_sizing < 0) + { + p->m_events_statements_history_sizing= h->m_events_statements_history_sizing; + } + + if (p->m_events_statements_history_long_sizing < 0) + { + p->m_events_statements_history_long_sizing= h->m_events_statements_history_long_sizing; + } + + if (p->m_digest_sizing < 0) + { + p->m_digest_sizing= h->m_digest_sizing; + } + + if (p->m_session_connect_attrs_sizing < 0) + { + p->m_session_connect_attrs_sizing= h->m_session_connect_attrs_sizing; + } + + if (p->m_mutex_sizing < 0) + { + count= fixed_mutex_instances + + con * mutex_per_connection + + handle * mutex_per_handle + + share * mutex_per_share; + + p->m_mutex_sizing= apply_load_factor(count, h->m_load_factor_volatile); + } + + if (p->m_rwlock_sizing < 0) + { + count= fixed_rwlock_instances + + con * rwlock_per_connection + + handle * rwlock_per_handle + + share * rwlock_per_share; + + p->m_rwlock_sizing= apply_load_factor(count, h->m_load_factor_volatile); + } + + if (p->m_cond_sizing < 0) + { + ulong count; + count= fixed_cond_instances + + con * cond_per_connection + + handle * cond_per_handle + + share * cond_per_share; + + p->m_cond_sizing= apply_load_factor(count, h->m_load_factor_volatile); + } + + if (p->m_file_sizing < 0) + { + count= fixed_file_instances + + con * file_per_connection + + handle * file_per_handle + + share * file_per_share; + + count= max<ulong>(count, file); + p->m_file_sizing= apply_load_factor(count, h->m_load_factor_normal); + } + + if (p->m_socket_sizing < 0) + { + count= fixed_socket_instances + + con * socket_per_connection + + handle * socket_per_handle + + share * socket_per_share; + + p->m_socket_sizing= apply_load_factor(count, h->m_load_factor_volatile); + } + + if (p->m_thread_sizing < 0) + { + count= fixed_thread_instances + + con * thread_per_connection + + handle * thread_per_handle + + share * thread_per_share; + + p->m_thread_sizing= apply_load_factor(count, h->m_load_factor_volatile); + } +} + +void pfs_automated_sizing(PFS_global_param *param) +{ + PFS_sizing_data *heuristic; + heuristic= estimate_hints(param); + apply_heuristic(param, heuristic); + + DBUG_ASSERT(param->m_account_sizing >= 0); + DBUG_ASSERT(param->m_digest_sizing >= 0); + DBUG_ASSERT(param->m_host_sizing >= 0); + DBUG_ASSERT(param->m_user_sizing >= 0); + + DBUG_ASSERT(param->m_events_waits_history_sizing >= 0); + DBUG_ASSERT(param->m_events_waits_history_long_sizing >= 0); + DBUG_ASSERT(param->m_events_stages_history_sizing >= 0); + DBUG_ASSERT(param->m_events_stages_history_long_sizing >= 0); + DBUG_ASSERT(param->m_events_statements_history_sizing >= 0); + DBUG_ASSERT(param->m_events_statements_history_long_sizing >= 0); + DBUG_ASSERT(param->m_session_connect_attrs_sizing >= 0); + + DBUG_ASSERT(param->m_mutex_sizing >= 0); + DBUG_ASSERT(param->m_rwlock_sizing >= 0); + DBUG_ASSERT(param->m_cond_sizing >= 0); + DBUG_ASSERT(param->m_file_sizing >= 0); + DBUG_ASSERT(param->m_socket_sizing >= 0); + DBUG_ASSERT(param->m_thread_sizing >= 0); + DBUG_ASSERT(param->m_table_sizing >= 0); + DBUG_ASSERT(param->m_table_share_sizing >= 0); +} + diff --git a/storage/perfschema/pfs_digest.cc b/storage/perfschema/pfs_digest.cc index 92c27b2e85f..6edcba4c013 100644 --- a/storage/perfschema/pfs_digest.cc +++ b/storage/perfschema/pfs_digest.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 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 @@ -30,6 +30,8 @@ #include "table_helper.h" #include "my_md5.h" #include "sql_lex.h" +#include "sql_get_diagnostics.h" +#include "sql_string.h" #include <string.h> /* Generated code */ @@ -58,7 +60,6 @@ ulong digest_max= 0; ulong digest_lost= 0; - /** EVENTS_STATEMENTS_HISTORY_LONG circular buffer. */ PFS_statements_digest_stat *statements_digest_stat_array= NULL; /** Consumer flag for table EVENTS_STATEMENTS_SUMMARY_BY_DIGEST. */ @@ -69,7 +70,7 @@ bool flag_statements_digest= true; */ volatile uint32 digest_index= 1; -static LF_HASH digest_hash; +LF_HASH digest_hash; static bool digest_hash_inited= false; /** @@ -123,8 +124,8 @@ static uchar *digest_hash_get_key(const uchar *entry, size_t *length, DBUG_ASSERT(typed_entry != NULL); digest= *typed_entry; DBUG_ASSERT(digest != NULL); - *length= PFS_MD5_SIZE; - result= digest->m_digest_hash.m_md5; + *length= sizeof (PFS_digest_key); + result= & digest->m_digest_key; return const_cast<uchar*> (reinterpret_cast<const uchar*> (result)); } C_MODE_END @@ -136,11 +137,12 @@ C_MODE_END */ int init_digest_hash(void) { - if (! digest_hash_inited) + if ((! digest_hash_inited) && (digest_max > 0)) { lf_hash_init(&digest_hash, sizeof(PFS_statements_digest_stat*), LF_HASH_UNIQUE, 0, 0, digest_hash_get_key, &my_charset_bin); + /* digest_hash.size= digest_max; */ digest_hash_inited= true; } return 0; @@ -167,8 +169,10 @@ static LF_PINS* get_digest_hash_pins(PFS_thread *thread) } PFS_statement_stat* -find_or_create_digest(PFS_thread* thread, - PSI_digest_storage* digest_storage) +find_or_create_digest(PFS_thread *thread, + PSI_digest_storage *digest_storage, + const char *schema_name, + uint schema_name_length) { if (statements_digest_stat_array == NULL) return NULL; @@ -180,13 +184,21 @@ find_or_create_digest(PFS_thread* thread, if (unlikely(pins == NULL)) return NULL; + /* + Note: the LF_HASH key is a block of memory, + make sure to clean unused bytes, + so that memcmp() can compare keys. + */ + PFS_digest_key hash_key; + memset(& hash_key, 0, sizeof(hash_key)); /* Compute MD5 Hash of the tokens received. */ - PFS_digest_hash md5; - compute_md5_hash((char *) md5.m_md5, + compute_md5_hash((char *) hash_key.m_md5, (char *) digest_storage->m_token_array, digest_storage->m_byte_count); - - unsigned char* hash_key= md5.m_md5; + /* Add the current schema to the key */ + hash_key.m_schema_name_length= schema_name_length; + if (schema_name_length > 0) + memcpy(hash_key.m_schema_name, schema_name, schema_name_length); int res; ulong safe_index; @@ -202,7 +214,7 @@ search: /* Lookup LF_HASH using this new key. */ entry= reinterpret_cast<PFS_statements_digest_stat**> (lf_hash_search(&digest_hash, pins, - hash_key, PFS_MD5_SIZE)); + &hash_key, sizeof(PFS_digest_key))); if (entry && (entry != MY_ERRPTR)) { @@ -244,7 +256,7 @@ search: 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); + memcpy(& pfs->m_digest_key, &hash_key, sizeof(PFS_digest_key)); /* Copy digest storage to statement_digest_stat_array so that it could be @@ -278,7 +290,7 @@ search: return NULL; } -void purge_digest(PFS_thread* thread, unsigned char* hash_key) +void purge_digest(PFS_thread* thread, PFS_digest_key *hash_key) { LF_PINS *pins= get_digest_hash_pins(thread); if (unlikely(pins == NULL)) @@ -289,12 +301,12 @@ void purge_digest(PFS_thread* thread, unsigned char* hash_key) /* Lookup LF_HASH using this new key. */ entry= reinterpret_cast<PFS_statements_digest_stat**> (lf_hash_search(&digest_hash, pins, - hash_key, PFS_MD5_SIZE)); + hash_key, sizeof(PFS_digest_key))); if (entry && (entry != MY_ERRPTR)) - { + { lf_hash_delete(&digest_hash, pins, - hash_key, PFS_MD5_SIZE); + hash_key, sizeof(PFS_digest_key)); } lf_hash_search_unpin(pins); return; @@ -313,7 +325,7 @@ 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); + purge_digest(thread, & m_digest_key); } } @@ -347,98 +359,130 @@ void reset_esms_by_digest() */ void get_digest_text(char* digest_text, PSI_digest_storage* digest_storage) { + DBUG_ASSERT(digest_storage != NULL); bool truncated= false; int byte_count= digest_storage->m_byte_count; - int need_bytes; + int bytes_needed= 0; uint tok= 0; - char *id_string; - int id_length; int current_byte= 0; lex_token_string *tok_data; /* -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 bytes_available= COL_DIGEST_TEXT_SIZE - 4; + + /* Convert text to utf8 */ + const CHARSET_INFO *from_cs= get_charset(digest_storage->m_charset_number, MYF(0)); + const CHARSET_INFO *to_cs= &my_charset_utf8_bin; + + if (from_cs == NULL) + { + /* + Can happen, as we do dirty reads on digest_storage, + which can be written to in another thread. + */ + *digest_text= '\0'; + return; + } + + /* + Max converted size is number of characters * max multibyte length of the + target charset, which is 4 for UTF8. + */ + const uint max_converted_size= PSI_MAX_DIGEST_STORAGE_SIZE * 4; + char id_buffer[max_converted_size]; + char *id_string; + int id_length; + bool convert_text= !my_charset_same(from_cs, to_cs); DBUG_ASSERT(byte_count <= PSI_MAX_DIGEST_STORAGE_SIZE); while ((current_byte < byte_count) && - (available_bytes_to_write > 0) && - (! truncated)) + (bytes_available > 0) && + !truncated) { current_byte= read_token(digest_storage, current_byte, &tok); - tok_data= & lex_token_array[tok]; + tok_data= &lex_token_array[tok]; switch (tok) { /* All identifiers are printed with their name. */ case IDENT: - 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) + case IDENT_QUOTED: { - if (id_length > 0) + char *id_ptr; + int id_len; + uint err_cs= 0; + + /* Get the next identifier from the storage buffer. */ + current_byte= read_identifier(digest_storage, current_byte, + &id_ptr, &id_len); + if (convert_text) { - strncpy(digest_text, id_string, id_length); - digest_text+= id_length; + /* Verify that the converted text will fit. */ + if (to_cs->mbmaxlen*id_len > max_converted_size) + { + truncated= true; + break; + } + /* Convert identifier string into the storage character set. */ + id_length= my_convert(id_buffer, max_converted_size, to_cs, + id_ptr, id_len, from_cs, &err_cs); + id_string= id_buffer; } - *digest_text= ' '; - digest_text++; - available_bytes_to_write-= need_bytes; - } - else - { - truncated= true; - } - break; - case IDENT_QUOTED: - 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) + else { - strncpy(digest_text, id_string, id_length); - digest_text+= id_length; + id_string= id_ptr; + id_length= id_len; + } + + if (id_length == 0 || err_cs != 0) + { + truncated= true; + break; + } + /* Copy the converted identifier into the digest string. */ + bytes_needed= id_length + (tok == IDENT ? 1 : 3); + if (bytes_needed <= bytes_available) + { + if (tok == IDENT_QUOTED) + *digest_text++= '`'; + if (id_length > 0) + { + memcpy(digest_text, id_string, id_length); + digest_text+= id_length; + } + if (tok == IDENT_QUOTED) + *digest_text++= '`'; + *digest_text++= ' '; + bytes_available-= bytes_needed; + } + else + { + truncated= true; } - *digest_text= '`'; - digest_text++; - *digest_text= ' '; - digest_text++; - available_bytes_to_write-= need_bytes; - } - else - { - truncated= true; } break; /* Everything else is printed as is. */ default: /* - Make sure not to overflow digest_text buffer while writing - this token string. + Make sure not to overflow digest_text buffer. +1 is to make sure extra space for ' '. */ int tok_length= tok_data->m_token_length; - need_bytes= tok_length + 1; + bytes_needed= tok_length + 1; - if (need_bytes <= available_bytes_to_write) + if (bytes_needed <= bytes_available) { - strncpy(digest_text, - tok_data->m_token_string, - tok_length); + strncpy(digest_text, tok_data->m_token_string, tok_length); digest_text+= tok_length; - *digest_text= ' '; - digest_text++; - available_bytes_to_write-= need_bytes; + *digest_text++= ' '; + bytes_available-= bytes_needed; } else { truncated= true; } + break; } } @@ -524,7 +568,11 @@ PSI_digest_locker* pfs_digest_add_token_v1(PSI_digest_locker *locker, digest_storage= &state->m_digest_storage; - if (digest_storage->m_full) + /* + Stop collecting further tokens if digest storage is full or + if END token is received. + */ + if (digest_storage->m_full || token == END_OF_INPUT) return NULL; /* @@ -555,19 +603,23 @@ PSI_digest_locker* pfs_digest_add_token_v1(PSI_digest_locker *locker, TOK_PFS_GENERIC_VALUE := BIN_NUM | DECIMAL_NUM | ... | ULONGLONG_NUM */ token= TOK_PFS_GENERIC_VALUE; - + } + /* fall through */ + case NULL_SYM: + { if ((last_token2 == TOK_PFS_GENERIC_VALUE || - last_token2 == TOK_PFS_GENERIC_VALUE_LIST) && + last_token2 == TOK_PFS_GENERIC_VALUE_LIST || + last_token2 == NULL_SYM) && (last_token == ',')) { /* REDUCE: TOK_PFS_GENERIC_VALUE_LIST := - TOK_PFS_GENERIC_VALUE ',' TOK_PFS_GENERIC_VALUE + (TOK_PFS_GENERIC_VALUE|NULL_SYM) ',' (TOK_PFS_GENERIC_VALUE|NULL_SYM) REDUCE: TOK_PFS_GENERIC_VALUE_LIST := - TOK_PFS_GENERIC_VALUE_LIST ',' TOK_PFS_GENERIC_VALUE + TOK_PFS_GENERIC_VALUE_LIST ',' (TOK_PFS_GENERIC_VALUE|NULL_SYM) */ digest_storage->m_byte_count-= 2*PFS_SIZE_OF_A_TOKEN; token= TOK_PFS_GENERIC_VALUE_LIST; diff --git a/storage/perfschema/pfs_digest.h b/storage/perfschema/pfs_digest.h index 2646596171c..d2453dc32c6 100644 --- a/storage/perfschema/pfs_digest.h +++ b/storage/perfschema/pfs_digest.h @@ -38,32 +38,26 @@ struct PFS_thread; /** Structure to store a MD5 hash value (digest) for a statement. */ -struct PFS_digest_hash +struct PFS_digest_key { unsigned char m_md5[PFS_MD5_SIZE]; + char m_schema_name[NAME_LEN]; + uint m_schema_name_length; }; /** A statement digest stat record. */ -struct PFS_statements_digest_stat +struct PFS_ALIGNED PFS_statements_digest_stat { - /** - Digest MD5 Hash. - */ - PFS_digest_hash m_digest_hash; + /** Digest Schema + MD5 Hash. */ + PFS_digest_key m_digest_key; - /** - Digest Storage. - */ + /** Digest Storage. */ PSI_digest_storage m_digest_storage; - /** - Statement stat. - */ + /** Statement stat. */ PFS_statement_stat m_stat; - /** - First Seen/last seen. - */ + /** First and last seen timestamps.*/ ulonglong m_first_seen; ulonglong m_last_seen; @@ -78,10 +72,12 @@ void cleanup_digest(); int init_digest_hash(void); void cleanup_digest_hash(void); -PFS_statement_stat* find_or_create_digest(PFS_thread*, - PSI_digest_storage*); +PFS_statement_stat* find_or_create_digest(PFS_thread *thread, + PSI_digest_storage *digest_storage, + const char *schema_name, + uint schema_name_length); -void get_digest_text(char* digest_text, PSI_digest_storage*); +void get_digest_text(char *digest_text, PSI_digest_storage *digest_storage); void reset_esms_by_digest(); @@ -90,8 +86,8 @@ extern PFS_statements_digest_stat *statements_digest_stat_array; /* Instrumentation callbacks for pfs.cc */ -struct PSI_digest_locker* pfs_digest_start_v1(PSI_statement_locker *locker); -PSI_digest_locker* pfs_digest_add_token_v1(PSI_digest_locker *locker, +struct PSI_digest_locker *pfs_digest_start_v1(PSI_statement_locker *locker); +PSI_digest_locker *pfs_digest_add_token_v1(PSI_digest_locker *locker, uint token, OPAQUE_LEX_YYSTYPE *yylval); @@ -99,6 +95,7 @@ static inline void digest_reset(PSI_digest_storage *digest) { digest->m_full= false; digest->m_byte_count= 0; + digest->m_charset_number= 0; } static inline void digest_copy(PSI_digest_storage *to, const PSI_digest_storage *from) @@ -107,20 +104,21 @@ static inline void digest_copy(PSI_digest_storage *to, const PSI_digest_storage { to->m_full= from->m_full; to->m_byte_count= from->m_byte_count; + to->m_charset_number= from->m_charset_number; 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; + to->m_charset_number= 0; } } /** - Function to read a single token from token array. + Read a single token from token array. */ inline int read_token(PSI_digest_storage *digest_storage, int index, uint *tok) @@ -141,7 +139,7 @@ inline int read_token(PSI_digest_storage *digest_storage, } /** - Function to store a single token in token array. + Store a single token in token array. */ inline void store_token(PSI_digest_storage* digest_storage, uint token) { @@ -162,7 +160,7 @@ inline void store_token(PSI_digest_storage* digest_storage, uint token) } /** - Function to read an identifier from token array. + Read an identifier from token array. */ inline int read_identifier(PSI_digest_storage* digest_storage, int index, char ** id_string, int *id_length) @@ -186,7 +184,7 @@ inline int read_identifier(PSI_digest_storage* digest_storage, } /** - Function to store an identifier in token array. + Store an identifier in token array. */ inline void store_token_identifier(PSI_digest_storage* digest_storage, uint token, @@ -207,9 +205,7 @@ inline void store_token_identifier(PSI_digest_storage* digest_storage, dest[3]= (id_length >> 8) & 0xff; /* Write the string data */ if (id_length > 0) - { - strncpy((char *)(dest + 4), id_name, id_length); - } + memcpy((char *)(dest + 4), id_name, id_length); digest_storage->m_byte_count+= bytes_needed; } else @@ -218,4 +214,6 @@ inline void store_token_identifier(PSI_digest_storage* digest_storage, } } +extern LF_HASH digest_hash; + #endif diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc index c3f29787951..958a2bdd7bd 100644 --- a/storage/perfschema/pfs_engine_table.cc +++ b/storage/perfschema/pfs_engine_table.cc @@ -20,6 +20,7 @@ #include "my_global.h" #include "my_pthread.h" +#include "hostname.h" /* For Host_entry */ #include "pfs_engine_table.h" #include "table_events_waits.h" @@ -69,6 +70,8 @@ #include "table_socket_instances.h" #include "table_socket_summary_by_instance.h" #include "table_socket_summary_by_event_name.h" +#include "table_session_connect_attrs.h" +#include "table_session_account_connect_attrs.h" /* For show status */ #include "pfs_column_values.h" @@ -102,9 +105,7 @@ static PFS_engine_table_share *all_shares[]= &table_file_instances::m_share, &table_file_summary_by_event_name::m_share, &table_file_summary_by_instance::m_share, -#ifdef QQ_NOT_YET &table_host_cache::m_share, -#endif &table_mutex_instances::m_share, &table_os_global_by_type::m_share, &table_performance_timers::m_share, @@ -145,6 +146,8 @@ static PFS_engine_table_share *all_shares[]= &table_socket_instances::m_share, &table_socket_summary_by_instance::m_share, &table_socket_summary_by_event_name::m_share, + &table_session_connect_attrs::m_share, + &table_session_account_connect_attrs::m_share, NULL }; @@ -159,7 +162,7 @@ void PFS_engine_table_share::check_all_tables(THD *thd) DBUG_EXECUTE_IF("tampered_perfschema_table1", { /* Hack SETUP_INSTRUMENT, incompatible change. */ - all_shares[19]->m_field_def->count++; + all_shares[20]->m_field_def->count++; }); for (current= &all_shares[0]; (*current) != NULL; current++) @@ -683,20 +686,22 @@ PFS_unknown_acl pfs_unknown_acl; ACL_internal_access_result PFS_unknown_acl::check(ulong want_access, ulong *save_priv) const { - const ulong always_forbidden= INSERT_ACL | UPDATE_ACL | DELETE_ACL - | CREATE_ACL | REFERENCES_ACL | INDEX_ACL | ALTER_ACL - | CREATE_VIEW_ACL | TRIGGER_ACL | LOCK_TABLES_ACL; + const ulong always_forbidden= CREATE_ACL + | REFERENCES_ACL | INDEX_ACL | ALTER_ACL + | CREATE_VIEW_ACL | TRIGGER_ACL; if (unlikely(want_access & always_forbidden)) return ACL_INTERNAL_ACCESS_DENIED; /* - There is no point in hidding (by enforcing ACCESS_DENIED for SELECT_ACL + There is no point in hiding (by enforcing ACCESS_DENIED for SELECT_ACL on performance_schema.*) tables that do not exist anyway. When SELECT_ACL is granted on performance_schema.* or *.*, SELECT * from performance_schema.wrong_table will fail with a more understandable ER_NO_SUCH_TABLE error, instead of ER_TABLEACCESS_DENIED_ERROR. + The same goes for other DML (INSERT_ACL | UPDATE_ACL | DELETE_ACL), + for ease of use: error messages will be less surprising. */ return ACL_INTERNAL_ACCESS_CHECK_GRANT; } @@ -978,363 +983,441 @@ bool pfs_show_status(handlerton *hton, THD *thd, total_memory+= size; break; case 56: - name= "events_waits_summary_global_by_event_name.row_size"; - size= sizeof(PFS_single_stat); - break; - case 57: - name= "events_waits_summary_global_by_event_name.row_count"; - size= wait_class_max; - break; - case 58: - name= "events_waits_summary_global_by_event_name.memory"; - size= wait_class_max * sizeof(PFS_single_stat); - total_memory+= size; - break; - case 59: name= "(pfs_account).row_size"; size= sizeof(PFS_account); break; - case 60: + case 57: name= "(pfs_account).row_count"; size= account_max; break; - case 61: + case 58: name= "(pfs_account).memory"; size= account_max * sizeof(PFS_account); total_memory+= size; break; - case 62: + case 59: name= "events_waits_summary_by_account_by_event_name.row_size"; size= sizeof(PFS_single_stat); break; - case 63: + case 60: name= "events_waits_summary_by_account_by_event_name.row_count"; size= account_max * wait_class_max; break; - case 64: + case 61: name= "events_waits_summary_by_account_by_event_name.memory"; size= account_max * wait_class_max * sizeof(PFS_single_stat); total_memory+= size; break; - case 65: + case 62: name= "events_waits_summary_by_user_by_event_name.row_size"; size= sizeof(PFS_single_stat); break; - case 66: + case 63: name= "events_waits_summary_by_user_by_event_name.row_count"; size= user_max * wait_class_max; break; - case 67: + case 64: name= "events_waits_summary_by_user_by_event_name.memory"; size= user_max * wait_class_max * sizeof(PFS_single_stat); total_memory+= size; break; - case 68: + case 65: name= "events_waits_summary_by_host_by_event_name.row_size"; size= sizeof(PFS_single_stat); break; - case 69: + case 66: name= "events_waits_summary_by_host_by_event_name.row_count"; size= host_max * wait_class_max; break; - case 70: + case 67: name= "events_waits_summary_by_host_by_event_name.memory"; size= host_max * wait_class_max * sizeof(PFS_single_stat); total_memory+= size; break; - case 71: + case 68: name= "(pfs_user).row_size"; size= sizeof(PFS_user); break; - case 72: + case 69: name= "(pfs_user).row_count"; size= user_max; break; - case 73: + case 70: name= "(pfs_user).memory"; size= user_max * sizeof(PFS_user); total_memory+= size; break; - case 74: + case 71: name= "(pfs_host).row_size"; size= sizeof(PFS_host); break; - case 75: + case 72: name= "(pfs_host).row_count"; size= host_max; break; - case 76: + case 73: name= "(pfs_host).memory"; size= host_max * sizeof(PFS_host); total_memory+= size; break; - case 77: + case 74: name= "(pfs_stage_class).row_size"; size= sizeof(PFS_stage_class); break; - case 78: + case 75: name= "(pfs_stage_class).row_count"; size= stage_class_max; break; - case 79: + case 76: name= "(pfs_stage_class).memory"; size= stage_class_max * sizeof(PFS_stage_class); total_memory+= size; break; - case 80: + case 77: name= "events_stages_history.row_size"; size= sizeof(PFS_events_stages); break; - case 81: + case 78: name= "events_stages_history.row_count"; size= events_stages_history_per_thread * thread_max; break; - case 82: + case 79: name= "events_stages_history.memory"; size= events_stages_history_per_thread * thread_max * sizeof(PFS_events_stages); total_memory+= size; break; - case 83: + case 80: name= "events_stages_history_long.row_size"; size= sizeof(PFS_events_stages); break; - case 84: + case 81: name= "events_stages_history_long.row_count"; size= events_stages_history_long_size; break; - case 85: + case 82: name= "events_stages_history_long.memory"; size= events_stages_history_long_size * sizeof(PFS_events_stages); total_memory+= size; break; - case 86: + case 83: name= "events_stages_summary_by_thread_by_event_name.row_size"; size= sizeof(PFS_stage_stat); break; - case 87: + case 84: name= "events_stages_summary_by_thread_by_event_name.row_count"; size= thread_max * stage_class_max; break; - case 88: + case 85: name= "events_stages_summary_by_thread_by_event_name.memory"; size= thread_max * stage_class_max * sizeof(PFS_stage_stat); total_memory+= size; break; - case 89: + case 86: name= "events_stages_summary_global_by_event_name.row_size"; size= sizeof(PFS_stage_stat); break; - case 90: + case 87: name= "events_stages_summary_global_by_event_name.row_count"; size= stage_class_max; break; - case 91: + case 88: name= "events_stages_summary_global_by_event_name.memory"; size= stage_class_max * sizeof(PFS_stage_stat); total_memory+= size; break; - case 92: + case 89: name= "events_stages_summary_by_account_by_event_name.row_size"; size= sizeof(PFS_stage_stat); break; - case 93: + case 90: name= "events_stages_summary_by_account_by_event_name.row_count"; size= account_max * stage_class_max; break; - case 94: + case 91: name= "events_stages_summary_by_account_by_event_name.memory"; size= account_max * stage_class_max * sizeof(PFS_stage_stat); total_memory+= size; break; - case 95: + case 92: name= "events_stages_summary_by_user_by_event_name.row_size"; size= sizeof(PFS_stage_stat); break; - case 96: + case 93: name= "events_stages_summary_by_user_by_event_name.row_count"; size= user_max * stage_class_max; break; - case 97: + case 94: name= "events_stages_summary_by_user_by_event_name.memory"; size= user_max * stage_class_max * sizeof(PFS_stage_stat); total_memory+= size; break; - case 98: + case 95: name= "events_stages_summary_by_host_by_event_name.row_size"; size= sizeof(PFS_stage_stat); break; - case 99: + case 96: name= "events_stages_summary_by_host_by_event_name.row_count"; size= host_max * stage_class_max; break; - case 100: + case 97: name= "events_stages_summary_by_host_by_event_name.memory"; size= host_max * stage_class_max * sizeof(PFS_stage_stat); total_memory+= size; break; - case 101: + case 98: name= "(pfs_statement_class).row_size"; size= sizeof(PFS_statement_class); break; - case 102: + case 99: name= "(pfs_statement_class).row_count"; size= statement_class_max; break; - case 103: + case 100: name= "(pfs_statement_class).memory"; size= statement_class_max * sizeof(PFS_statement_class); total_memory+= size; break; - case 104: + case 101: name= "events_statements_history.row_size"; size= sizeof(PFS_events_statements); break; - case 105: + case 102: name= "events_statements_history.row_count"; size= events_statements_history_per_thread * thread_max; break; - case 106: + case 103: name= "events_statements_history.memory"; size= events_statements_history_per_thread * thread_max * sizeof(PFS_events_statements); total_memory+= size; break; - case 107: + case 104: name= "events_statements_history_long.row_size"; size= sizeof(PFS_events_statements); break; - case 108: + case 105: name= "events_statements_history_long.row_count"; size= events_statements_history_long_size; break; - case 109: + case 106: name= "events_statements_history_long.memory"; size= events_statements_history_long_size * sizeof(PFS_events_statements); total_memory+= size; break; - case 110: + case 107: name= "events_statements_summary_by_thread_by_event_name.row_size"; size= sizeof(PFS_statement_stat); break; - case 111: + case 108: name= "events_statements_summary_by_thread_by_event_name.row_count"; size= thread_max * statement_class_max; break; - case 112: + case 109: name= "events_statements_summary_by_thread_by_event_name.memory"; size= thread_max * statement_class_max * sizeof(PFS_statement_stat); total_memory+= size; break; - case 113: + case 110: name= "events_statements_summary_global_by_event_name.row_size"; size= sizeof(PFS_statement_stat); break; - case 114: + case 111: name= "events_statements_summary_global_by_event_name.row_count"; size= statement_class_max; break; - case 115: + case 112: name= "events_statements_summary_global_by_event_name.memory"; size= statement_class_max * sizeof(PFS_statement_stat); total_memory+= size; break; - case 116: + case 113: name= "events_statements_summary_by_account_by_event_name.row_size"; size= sizeof(PFS_statement_stat); break; - case 117: + case 114: name= "events_statements_summary_by_account_by_event_name.row_count"; size= account_max * statement_class_max; break; - case 118: + case 115: name= "events_statements_summary_by_account_by_event_name.memory"; size= account_max * statement_class_max * sizeof(PFS_statement_stat); total_memory+= size; break; - case 119: + case 116: name= "events_statements_summary_by_user_by_event_name.row_size"; size= sizeof(PFS_statement_stat); break; - case 120: + case 117: name= "events_statements_summary_by_user_by_event_name.row_count"; size= user_max * statement_class_max; break; - case 121: + case 118: name= "events_statements_summary_by_user_by_event_name.memory"; size= user_max * statement_class_max * sizeof(PFS_statement_stat); total_memory+= size; break; - case 122: + case 119: name= "events_statements_summary_by_host_by_event_name.row_size"; size= sizeof(PFS_statement_stat); break; - case 123: + case 120: name= "events_statements_summary_by_host_by_event_name.row_count"; size= host_max * statement_class_max; break; - case 124: + case 121: name= "events_statements_summary_by_host_by_event_name.memory"; size= host_max * statement_class_max * sizeof(PFS_statement_stat); total_memory+= size; break; - case 125: + case 122: name= "events_statements_current.row_size"; size= sizeof(PFS_events_statements); break; - case 126: + case 123: name= "events_statements_current.row_count"; size= thread_max * statement_stack_max; break; - case 127: + case 124: name= "events_statements_current.memory"; size= thread_max * statement_stack_max * sizeof(PFS_events_statements); total_memory+= size; break; - case 128: + case 125: name= "(pfs_socket_class).row_size"; size= sizeof(PFS_socket_class); break; - case 129: + case 126: name= "(pfs_socket_class).row_count"; size= socket_class_max; break; - case 130: + case 127: name= "(pfs_socket_class).memory"; size= socket_class_max * sizeof(PFS_socket_class); total_memory+= size; break; - case 131: + case 128: name= "socket_instances.row_size"; size= sizeof(PFS_socket); break; - case 132: + case 129: name= "socket_instances.row_count"; size= socket_max; break; - case 133: + case 130: name= "socket_instances.memory"; size= socket_max * sizeof(PFS_socket); total_memory+= size; break; - case 134: + case 131: name= "events_statements_summary_by_digest.row_size"; size= sizeof(PFS_statements_digest_stat); break; - case 135: + case 132: name= "events_statements_summary_by_digest.row_count"; size= digest_max; break; - case 136: + case 133: name= "events_statements_summary_by_digest.memory"; size= digest_max * sizeof(PFS_statements_digest_stat); total_memory+= size; - break; + break; + case 134: + name= "session_connect_attrs.row_size"; + size= thread_max; + break; + case 135: + name= "session_connect_attrs.row_count"; + size= session_connect_attrs_size_per_thread; + break; + case 136: + name= "session_connect_attrs.memory"; + size= thread_max * session_connect_attrs_size_per_thread; + total_memory+= size; + break; + + case 137: + name= "(account_hash).count"; + size= account_hash.count; + break; + case 138: + name= "(account_hash).size"; + size= account_hash.size; + break; + case 139: + name= "(digest_hash).count"; + size= digest_hash.count; + break; + case 140: + name= "(digest_hash).size"; + size= digest_hash.size; + break; + case 141: + name= "(filename_hash).count"; + size= filename_hash.count; + break; + case 142: + name= "(filename_hash).size"; + size= filename_hash.size; + break; + case 143: + name= "(host_hash).count"; + size= host_hash.count; + break; + case 144: + name= "(host_hash).size"; + size= host_hash.size; + break; + case 145: + name= "(setup_actor_hash).count"; + size= setup_actor_hash.count; + break; + case 146: + name= "(setup_actor_hash).size"; + size= setup_actor_hash.size; + break; + case 147: + name= "(setup_object_hash).count"; + size= setup_object_hash.count; + break; + case 148: + name= "(setup_object_hash).size"; + size= setup_object_hash.size; + break; + case 149: + name= "(table_share_hash).count"; + size= table_share_hash.count; + break; + case 150: + name= "(table_share_hash).size"; + size= table_share_hash.size; + break; + case 151: + name= "(user_hash).count"; + size= user_hash.count; + break; + case 152: + name= "(user_hash).size"; + size= user_hash.size; + break; + case 153: + /* + This is not a performance_schema buffer, + the data is maintained in the server, + in hostname_cache. + Print the size only, there are: + - no host_cache.count + - no host_cache.memory + */ + name= "host_cache.size"; + size= sizeof(Host_entry); + break; + /* This case must be last, for aggregation in total_memory. */ - case 137: + case 154: name= "performance_schema.memory"; size= total_memory; /* This will fail if something is not advertised here */ diff --git a/storage/perfschema/pfs_engine_table.h b/storage/perfschema/pfs_engine_table.h index 40f5404d0b7..981d72ee19e 100644 --- a/storage/perfschema/pfs_engine_table.h +++ b/storage/perfschema/pfs_engine_table.h @@ -263,7 +263,7 @@ public: ~PFS_readonly_acl() {} - ACL_internal_access_result check(ulong want_access, ulong *save_priv) const; + virtual ACL_internal_access_result check(ulong want_access, ulong *save_priv) const; }; /** Singleton instance of PFS_readonly_acl. */ diff --git a/storage/perfschema/pfs_events.h b/storage/perfschema/pfs_events.h index c9586df11bd..97fb7e08d63 100644 --- a/storage/perfschema/pfs_events.h +++ b/storage/perfschema/pfs_events.h @@ -29,7 +29,7 @@ struct PFS_instr_class; struct PFS_events { /** THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** EVENT_ID. */ ulonglong m_event_id; /** END_EVENT_ID. */ diff --git a/storage/perfschema/pfs_events_waits.cc b/storage/perfschema/pfs_events_waits.cc index 2ee9ec292a2..c8a9d20a2f1 100644 --- a/storage/perfschema/pfs_events_waits.cc +++ b/storage/perfschema/pfs_events_waits.cc @@ -230,16 +230,6 @@ void reset_events_waits_by_host() } } -/** Reset table EVENTS_WAITS_GLOBAL_BY_EVENT_NAME data. */ -void reset_events_waits_global() -{ - PFS_single_stat *stat= global_instr_class_waits_array; - PFS_single_stat *stat_last= global_instr_class_waits_array + wait_class_max; - - for ( ; stat < stat_last; stat++) - stat->reset(); -} - void reset_table_waits_by_table() { PFS_table_share *pfs= table_share_array; diff --git a/storage/perfschema/pfs_global.cc b/storage/perfschema/pfs_global.cc index 2351b829894..546597ef33e 100644 --- a/storage/perfschema/pfs_global.cc +++ b/storage/perfschema/pfs_global.cc @@ -18,13 +18,16 @@ Miscellaneous global dependencies (implementation). */ -#include "my_global.h" -#include "my_sys.h" #include "pfs_global.h" -#include "my_net.h" +#include <my_sys.h> +#include <my_net.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> /* memalign() may be here */ +#endif -#include <stdlib.h> -#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #ifdef __WIN__ #include <winsock2.h> @@ -45,18 +48,65 @@ void *pfs_malloc(size_t size, myf flags) DBUG_ASSERT(! pfs_initialized); DBUG_ASSERT(size > 0); - void *ptr= malloc(size); - if (likely(ptr != NULL)) - pfs_allocated_memory+= size; - if (likely((ptr != NULL) && (flags & MY_ZEROFILL))) + void *ptr; + +#ifdef PFS_ALIGNEMENT +#ifdef HAVE_POSIX_MEMALIGN + /* Linux */ + if (unlikely(posix_memalign(& ptr, PFS_ALIGNEMENT, size))) + return NULL; +#else +#ifdef HAVE_MEMALIGN + /* Solaris */ + ptr= memalign(PFS_ALIGNEMENT, size); + if (unlikely(ptr == NULL)) + return NULL; +#else +#ifdef HAVE_ALIGNED_MALLOC + /* Windows */ + ptr= _aligned_malloc(size, PFS_ALIGNEMENT); + if (unlikely(ptr == NULL)) + return NULL; +#else +#error "Missing implementation for PFS_ALIGNENT" +#endif /* HAVE_ALIGNED_MALLOC */ +#endif /* HAVE_MEMALIGN */ +#endif /* HAVE_POSIX_MEMALIGN */ +#else /* PFS_ALIGNMENT */ + /* Everything else */ + ptr= malloc(size); + if (unlikely(ptr == NULL)) + return NULL; +#endif + + pfs_allocated_memory+= size; + if (flags & MY_ZEROFILL) memset(ptr, 0, size); return ptr; } void pfs_free(void *ptr) { - if (ptr != NULL) - free(ptr); + if (ptr == NULL) + return; + +#ifdef HAVE_POSIX_MEMALIGN + /* Allocated with posix_memalign() */ + free(ptr); +#else +#ifdef HAVE_MEMALIGN + /* Allocated with memalign() */ + free(ptr); +#else +#ifdef HAVE_ALIGNED_MALLOC + /* Allocated with _aligned_malloc() */ + _aligned_free(ptr); +#else + /* Allocated with malloc() */ + free(ptr); +#endif /* HAVE_ALIGNED_MALLOC */ +#endif /* HAVE_MEMALIGN */ +#endif /* HAVE_POSIX_MEMALIGN */ } void pfs_print_error(const char *format, ...) diff --git a/storage/perfschema/pfs_global.h b/storage/perfschema/pfs_global.h index a0e6c97a406..f9687524cd5 100644 --- a/storage/perfschema/pfs_global.h +++ b/storage/perfschema/pfs_global.h @@ -16,6 +16,9 @@ #ifndef PFS_GLOBAL_H #define PFS_GLOBAL_H +#include "my_global.h" +#include "my_compiler.h" + /** @file storage/perfschema/pfs_global.h Miscellaneous global dependencies (declarations). @@ -27,6 +30,18 @@ extern bool pfs_initialized; /** Total memory allocated by the performance schema, in bytes. */ extern size_t pfs_allocated_memory; +#if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN) || defined(HAVE_ALIGNED_MALLOC) +#define PFS_ALIGNEMENT 64 +#define PFS_ALIGNED MY_ALIGNED(PFS_ALIGNEMENT) +#else +/* + Known platforms that do not provide aligned memory: + - MacOSX Darwin (osx10.5) + For these platforms, compile without the alignment optimization. +*/ +#define PFS_ALIGNED +#endif /* HAVE_POSIX_MEMALIGN || HAVE_MEMALIGN || HAVE_ALIGNED_MALLOC */ + void *pfs_malloc(size_t size, myf flags); /** diff --git a/storage/perfschema/pfs_host.cc b/storage/perfschema/pfs_host.cc index 82b78e19ce8..ac6308ff991 100644 --- a/storage/perfschema/pfs_host.cc +++ b/storage/perfschema/pfs_host.cc @@ -42,7 +42,7 @@ static PFS_single_stat *host_instr_class_waits_array= NULL; static PFS_stage_stat *host_instr_class_stages_array= NULL; static PFS_statement_stat *host_instr_class_statements_array= NULL; -static LF_HASH host_hash; +LF_HASH host_hash; static bool host_hash_inited= false; /** @@ -146,10 +146,11 @@ C_MODE_END */ int init_host_hash(void) { - if (! host_hash_inited) + if ((! host_hash_inited) && (host_max > 0)) { lf_hash_init(&host_hash, sizeof(PFS_host*), LF_HASH_UNIQUE, 0, 0, host_hash_get_key, &my_charset_bin); + /* host_hash.size= host_max; */ host_hash_inited= true; } return 0; diff --git a/storage/perfschema/pfs_host.h b/storage/perfschema/pfs_host.h index d04b88e62f3..eb0ff6efc6f 100644 --- a/storage/perfschema/pfs_host.h +++ b/storage/perfschema/pfs_host.h @@ -44,7 +44,7 @@ struct PFS_host_key uint m_key_length; }; -struct PFS_host : PFS_connection_slice +struct PFS_ALIGNED PFS_host : PFS_connection_slice { public: inline void init_refcount(void) @@ -105,6 +105,8 @@ extern ulong host_lost; extern PFS_host *host_array; +extern LF_HASH host_hash; + /** @} */ #endif diff --git a/storage/perfschema/pfs_instr.cc b/storage/perfschema/pfs_instr.cc index 39caabaf030..7b7340cc713 100644 --- a/storage/perfschema/pfs_instr.cc +++ b/storage/perfschema/pfs_instr.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 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 @@ -82,6 +82,10 @@ uint statement_stack_max; ulong locker_lost= 0; /** Number of statement lost. @sa STATEMENT_STACK_SIZE. */ ulong statement_lost= 0; +/** Size of connection attribute storage per thread */ +ulong session_connect_attrs_size_per_thread; +/** Number of connection attributes lost */ +ulong session_connect_attrs_lost= 0; /** Mutex instrumentation instances array. @@ -140,11 +144,10 @@ PFS_table *table_array= NULL; */ PFS_socket *socket_array= NULL; -PFS_single_stat *global_instr_class_waits_array= NULL; PFS_stage_stat *global_instr_class_stages_array= NULL; PFS_statement_stat *global_instr_class_statements_array= NULL; -static volatile uint32 thread_internal_id_counter= 0; +static volatile uint64 thread_internal_id_counter= 0; static uint thread_instr_class_waits_sizing; static uint thread_instr_class_stages_sizing; @@ -157,9 +160,10 @@ static PFS_events_waits *thread_waits_history_array= NULL; static PFS_events_stages *thread_stages_history_array= NULL; static PFS_events_statements *thread_statements_history_array= NULL; static PFS_events_statements *thread_statements_stack_array= NULL; +static char *thread_session_connect_attrs_array= NULL; /** Hash table for instrumented files. */ -static LF_HASH filename_hash; +LF_HASH filename_hash; /** True if filename_hash is initialized. */ static bool filename_hash_inited= false; @@ -174,6 +178,7 @@ int init_instruments(const PFS_global_param *param) uint thread_stages_history_sizing; uint thread_statements_history_sizing; uint thread_statements_stack_sizing; + uint thread_session_connect_attrs_sizing; uint index; DBUG_ENTER("init_instruments"); @@ -221,6 +226,11 @@ int init_instruments(const PFS_global_param *param) thread_instr_class_statements_sizing= param->m_thread_sizing * param->m_statement_class_sizing; + session_connect_attrs_size_per_thread= param->m_session_connect_attrs_sizing; + thread_session_connect_attrs_sizing= param->m_thread_sizing + * session_connect_attrs_size_per_thread; + session_connect_attrs_lost= 0; + mutex_array= NULL; rwlock_array= NULL; cond_array= NULL; @@ -366,6 +376,14 @@ int init_instruments(const PFS_global_param *param) thread_instr_class_statements_array[index].reset(); } + if (thread_session_connect_attrs_sizing > 0) + { + thread_session_connect_attrs_array= + (char *)pfs_malloc(thread_session_connect_attrs_sizing, MYF(MY_ZEROFILL)); + if (unlikely(thread_session_connect_attrs_array == NULL)) + return 1; + } + for (index= 0; index < thread_max; index++) { thread_array[index].m_waits_history= @@ -382,18 +400,8 @@ int init_instruments(const PFS_global_param *param) &thread_statements_stack_array[index * statement_stack_max]; thread_array[index].m_instr_class_statements_stats= &thread_instr_class_statements_array[index * statement_class_max]; - } - - if (wait_class_max > 0) - { - global_instr_class_waits_array= - PFS_MALLOC_ARRAY(wait_class_max, - PFS_single_stat, MYF(MY_ZEROFILL)); - if (unlikely(global_instr_class_waits_array == NULL)) - DBUG_RETURN(1); - - for (index= 0; index < wait_class_max; index++) - global_instr_class_waits_array[index].reset(); + thread_array[index].m_session_connect_attrs= + &thread_session_connect_attrs_array[index * session_connect_attrs_size_per_thread]; } if (stage_class_max > 0) @@ -461,8 +469,6 @@ void cleanup_instruments(void) thread_statements_stack_array= NULL; pfs_free(thread_instr_class_waits_array); thread_instr_class_waits_array= NULL; - pfs_free(global_instr_class_waits_array); - global_instr_class_waits_array= NULL; pfs_free(global_instr_class_stages_array); global_instr_class_stages_array= NULL; pfs_free(global_instr_class_statements_array); @@ -471,6 +477,9 @@ void cleanup_instruments(void) thread_instr_class_statements_array= NULL; pfs_free(thread_instr_class_stages_array); thread_instr_class_stages_array= NULL; + pfs_free(thread_session_connect_attrs_array); + thread_session_connect_attrs_array=NULL; + DBUG_VOID_RETURN; } @@ -502,10 +511,11 @@ int init_file_hash(void) { DBUG_ENTER("init_file_hash"); - if (! filename_hash_inited) + if ((! filename_hash_inited) && (file_max > 0)) { lf_hash_init(&filename_hash, sizeof(PFS_file*), LF_HASH_UNIQUE, 0, 0, filename_hash_get_key, &my_charset_bin); + /* filename_hash.size= file_max; */ filename_hash_inited= true; } DBUG_RETURN(0); @@ -604,7 +614,7 @@ void PFS_scan::init(uint random, uint max_size) */ PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity) { - static uint mutex_monotonic_index= 0; + static uint PFS_ALIGNED mutex_monotonic_index= 0; uint index; uint attempts= 0; PFS_mutex *pfs; @@ -642,8 +652,7 @@ PFS_mutex* create_mutex(PFS_mutex_class *klass, const void *identity) pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; - pfs->m_wait_stat.reset(); - pfs->m_lock_stat.reset(); + pfs->m_mutex_stat.reset(); pfs->m_owner= NULL; pfs->m_last_locked= 0; pfs->m_lock.dirty_to_allocated(); @@ -667,10 +676,9 @@ void destroy_mutex(PFS_mutex *pfs) DBUG_ENTER("destroy_mutex"); DBUG_ASSERT(pfs != NULL); PFS_mutex_class *klass= pfs->m_class; - /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */ - uint index= klass->m_event_name_index; - global_instr_class_waits_array[index].aggregate(& pfs->m_wait_stat); - pfs->m_wait_stat.reset(); + /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME */ + klass->m_mutex_stat.aggregate(& pfs->m_mutex_stat); + pfs->m_mutex_stat.reset(); if (klass->is_singleton()) klass->m_singleton= NULL; pfs->m_lock.allocated_to_free(); @@ -685,7 +693,7 @@ void destroy_mutex(PFS_mutex *pfs) */ PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity) { - static uint rwlock_monotonic_index= 0; + static uint PFS_ALIGNED rwlock_monotonic_index= 0; uint index; uint attempts= 0; PFS_rwlock *pfs; @@ -705,10 +713,8 @@ PFS_rwlock* create_rwlock(PFS_rwlock_class *klass, const void *identity) pfs->m_class= klass; pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; pfs->m_timed= klass->m_timed; - pfs->m_wait_stat.reset(); + pfs->m_rwlock_stat.reset(); pfs->m_lock.dirty_to_allocated(); - pfs->m_read_lock_stat.reset(); - pfs->m_write_lock_stat.reset(); pfs->m_writer= NULL; pfs->m_readers= 0; pfs->m_last_written= 0; @@ -733,10 +739,9 @@ void destroy_rwlock(PFS_rwlock *pfs) DBUG_ENTER("destroy_rwlock"); DBUG_ASSERT(pfs != NULL); PFS_rwlock_class *klass= pfs->m_class; - /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */ - uint index= klass->m_event_name_index; - global_instr_class_waits_array[index].aggregate(& pfs->m_wait_stat); - pfs->m_wait_stat.reset(); + /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME */ + klass->m_rwlock_stat.aggregate(& pfs->m_rwlock_stat); + pfs->m_rwlock_stat.reset(); if (klass->is_singleton()) klass->m_singleton= NULL; pfs->m_lock.allocated_to_free(); @@ -751,7 +756,7 @@ void destroy_rwlock(PFS_rwlock *pfs) */ PFS_cond* create_cond(PFS_cond_class *klass, const void *identity) { - static uint cond_monotonic_index= 0; + static uint PFS_ALIGNED cond_monotonic_index= 0; uint index; uint attempts= 0; PFS_cond *pfs; @@ -792,13 +797,12 @@ PFS_cond* create_cond(PFS_cond_class *klass, const void *identity) */ void destroy_cond(PFS_cond *pfs) { - DBUG_ENTER("destroy_thread"); + DBUG_ENTER("destroy_cond"); DBUG_ASSERT(pfs != NULL); PFS_cond_class *klass= pfs->m_class; - /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */ - uint index= klass->m_event_name_index; - global_instr_class_waits_array[index].aggregate(& pfs->m_wait_stat); + /* Aggregate to EVENTS_WAITS_SUMMARY_GLOBAL_BY_EVENT_NAME */ + klass->m_cond_stat.aggregate(& pfs->m_cond_stat); pfs->m_wait_stat.reset(); if (klass->is_singleton()) klass->m_singleton= NULL; @@ -812,19 +816,32 @@ PFS_thread* PFS_thread::get_current_thread() return pfs; } +void PFS_thread::reset_session_connect_attrs() +{ + m_session_connect_attrs_length= 0; + m_session_connect_attrs_cs= NULL; + + if ((m_session_connect_attrs != NULL) && + (session_connect_attrs_size_per_thread > 0) ) + { + /* Do not keep user data */ + memset(m_session_connect_attrs, 0, session_connect_attrs_size_per_thread); + } +} + /** Create instrumentation for a thread instance. @param klass the thread class @param identity the thread address, or a value characteristic of this thread - @param thread_id the PROCESSLIST thread id, + @param processlist_id the PROCESSLIST id, or 0 if unknown @return a thread instance, or NULL */ PFS_thread* create_thread(PFS_thread_class *klass, const void *identity, - ulong thread_id) + ulonglong processlist_id) { - static uint thread_monotonic_index= 0; + static uint PFS_ALIGNED thread_monotonic_index= 0; uint index; uint attempts= 0; PFS_thread *pfs; @@ -841,9 +858,9 @@ PFS_thread* create_thread(PFS_thread_class *klass, const void *identity, if (pfs->m_lock.free_to_dirty()) { pfs->m_thread_internal_id= - PFS_atomic::add_u32(&thread_internal_id_counter, 1); + PFS_atomic::add_u64(&thread_internal_id_counter, 1); pfs->m_parent_thread_internal_id= 0; - pfs->m_thread_id= thread_id; + pfs->m_processlist_id= processlist_id; pfs->m_event_id= 1; pfs->m_enabled= true; pfs->m_class= klass; @@ -856,6 +873,7 @@ PFS_thread* create_thread(PFS_thread_class *klass, const void *identity, pfs->m_statements_history_index= 0; pfs->reset_stats(); + pfs->reset_session_connect_attrs(); pfs->m_filename_hash_pins= NULL; pfs->m_table_share_hash_pins= NULL; @@ -871,8 +889,11 @@ PFS_thread* create_thread(PFS_thread_class *klass, const void *identity, pfs->m_dbname_length= 0; pfs->m_command= 0; pfs->m_start_time= 0; + pfs->m_processlist_state_ptr= NULL; pfs->m_processlist_state_length= 0; + pfs->m_processlist_info_ptr= NULL; pfs->m_processlist_info_length= 0; + pfs->m_processlist_lock.set_allocated(); pfs->m_host= NULL; pfs->m_user= NULL; @@ -999,6 +1020,7 @@ PFS_socket *sanitize_socket(PFS_socket *unsafe) void destroy_thread(PFS_thread *pfs) { DBUG_ASSERT(pfs != NULL); + pfs->reset_session_connect_attrs(); if (pfs->m_account != NULL) { pfs->m_account->release(); @@ -1084,11 +1106,12 @@ LF_PINS* get_filename_hash_pins(PFS_thread *thread) @param klass the file class @param filename the file name @param len the length in bytes of filename + @param create create a file instance if none found @return a file instance, or NULL */ PFS_file* find_or_create_file(PFS_thread *thread, PFS_file_class *klass, - const char *filename, uint len) + const char *filename, uint len, bool create) { PFS_file *pfs; LF_PINS *pins; @@ -1096,6 +1119,8 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, const char *safe_filename; DBUG_ENTER("find_or_create_file"); + DBUG_ASSERT(klass != NULL || ! create); + pins= get_filename_hash_pins(thread); if (unlikely(pins == NULL)) { @@ -1171,7 +1196,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, /* Append the unresolved file name to the resolved path */ char *ptr= buffer + strlen(buffer); char *buf_end= &buffer[sizeof(buffer)-1]; - if (buf_end > ptr) + if ((buf_end > ptr) && (*(ptr-1) != FN_LIBCHAR)) *ptr++= FN_LIBCHAR; if (buf_end > ptr) strncpy(ptr, safe_filename + dirlen, buf_end - ptr); @@ -1183,7 +1208,7 @@ find_or_create_file(PFS_thread *thread, PFS_file_class *klass, PFS_file **entry; uint retry_count= 0; const uint retry_max= 3; - static uint file_monotonic_index= 0; + static uint PFS_ALIGNED file_monotonic_index= 0; uint index; uint attempts= 0; @@ -1202,6 +1227,12 @@ search: lf_hash_search_unpin(pins); + if (! create) + { + /* No lost counter, just looking for the file existence. */ + DBUG_RETURN(NULL); + } + while (++attempts <= file_max) { /* See create_mutex() */ @@ -1218,7 +1249,6 @@ search: strncpy(pfs->m_filename, normalized_filename, normalized_length); pfs->m_filename[normalized_length]= '\0'; pfs->m_filename_length= normalized_length; - pfs->m_wait_stat.reset(); pfs->m_file_stat.m_open_count= 1; pfs->m_file_stat.m_io_stat.reset(); pfs->m_identity= (const void *)pfs; @@ -1250,7 +1280,7 @@ search: /* OOM in lf_hash_insert */ file_lost++; - return NULL; + DBUG_RETURN(NULL); } } } @@ -1285,14 +1315,9 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs) DBUG_ASSERT(pfs != NULL); PFS_file_class *klass= pfs->m_class; - /* Aggregate to EVENTS_WAITS_SUMMARY_BY_EVENT_NAME */ - uint index= klass->m_event_name_index; - global_instr_class_waits_array[index].aggregate(& pfs->m_wait_stat); - pfs->m_wait_stat.reset(); - /* Aggregate to FILE_SUMMARY_BY_EVENT_NAME */ - klass->m_file_stat.m_io_stat.aggregate(& pfs->m_file_stat.m_io_stat); - pfs->m_file_stat.m_io_stat.reset(); + klass->m_file_stat.aggregate(& pfs->m_file_stat); + pfs->m_file_stat.reset(); if (klass->is_singleton()) klass->m_singleton= NULL; @@ -1318,7 +1343,7 @@ void destroy_file(PFS_thread *thread, PFS_file *pfs) PFS_table* create_table(PFS_table_share *share, PFS_thread *opening_thread, const void *identity) { - static uint table_monotonic_index= 0; + static uint PFS_ALIGNED table_monotonic_index= 0; uint index; uint attempts= 0; PFS_table *pfs; @@ -1364,23 +1389,33 @@ void PFS_table::sanitized_aggregate(void) and not own the table handle. */ PFS_table_share *safe_share= sanitize_table_share(m_share); - PFS_thread *safe_thread= sanitize_thread(m_thread_owner); - if ((safe_share != NULL && safe_thread != NULL) && - (m_has_io_stats || m_has_lock_stats)) + if (safe_share != NULL) { - safe_aggregate(& m_table_stat, safe_share, safe_thread); - m_has_io_stats= false; - m_has_lock_stats= false; + if (m_has_io_stats && m_has_lock_stats) + { + safe_aggregate(& m_table_stat, safe_share); + m_has_io_stats= false; + m_has_lock_stats= false; + } + else if (m_has_io_stats) + { + safe_aggregate_io(& m_table_stat, safe_share); + m_has_io_stats= false; + } + else if (m_has_lock_stats) + { + safe_aggregate_lock(& m_table_stat, safe_share); + m_has_lock_stats= false; + } } } void PFS_table::sanitized_aggregate_io(void) { PFS_table_share *safe_share= sanitize_table_share(m_share); - PFS_thread *safe_thread= sanitize_thread(m_thread_owner); - if (safe_share != NULL && safe_thread != NULL && m_has_io_stats) + if (safe_share != NULL && m_has_io_stats) { - safe_aggregate_io(& m_table_stat, safe_share, safe_thread); + safe_aggregate_io(& m_table_stat, safe_share); m_has_io_stats= false; } } @@ -1388,96 +1423,44 @@ void PFS_table::sanitized_aggregate_io(void) void PFS_table::sanitized_aggregate_lock(void) { PFS_table_share *safe_share= sanitize_table_share(m_share); - PFS_thread *safe_thread= sanitize_thread(m_thread_owner); - if (safe_share != NULL && safe_thread != NULL && m_has_lock_stats) + if (safe_share != NULL && m_has_lock_stats) { - safe_aggregate_lock(& m_table_stat, safe_share, safe_thread); + safe_aggregate_lock(& m_table_stat, safe_share); m_has_lock_stats= false; } } void PFS_table::safe_aggregate(PFS_table_stat *table_stat, - PFS_table_share *table_share, - PFS_thread *thread) + PFS_table_share *table_share) { DBUG_ASSERT(table_stat != NULL); DBUG_ASSERT(table_share != NULL); - DBUG_ASSERT(thread != NULL); - - if (flag_thread_instrumentation && thread->m_enabled) - { - PFS_single_stat *event_name_array; - uint index; - event_name_array= thread->m_instr_class_waits_stats; - - /* - Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME - (for wait/io/table/sql/handler) - */ - index= global_table_io_class.m_event_name_index; - table_stat->sum_io(& event_name_array[index]); - /* - Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME - (for wait/lock/table/sql/handler) - */ - index= global_table_lock_class.m_event_name_index; - table_stat->sum_lock(& event_name_array[index]); - } + uint key_count= sanitize_index_count(table_share->m_key_count); /* Aggregate to TABLE_IO_SUMMARY, TABLE_LOCK_SUMMARY */ - table_share->m_table_stat.aggregate(table_stat); + table_share->m_table_stat.aggregate(table_stat, key_count); table_stat->fast_reset(); } void PFS_table::safe_aggregate_io(PFS_table_stat *table_stat, - PFS_table_share *table_share, - PFS_thread *thread) + PFS_table_share *table_share) { DBUG_ASSERT(table_stat != NULL); DBUG_ASSERT(table_share != NULL); - DBUG_ASSERT(thread != NULL); - - if (flag_thread_instrumentation && thread->m_enabled) - { - PFS_single_stat *event_name_array; - uint index; - event_name_array= thread->m_instr_class_waits_stats; - /* - Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME - (for wait/io/table/sql/handler) - */ - index= global_table_io_class.m_event_name_index; - table_stat->sum_io(& event_name_array[index]); - } + uint key_count= sanitize_index_count(table_share->m_key_count); /* Aggregate to TABLE_IO_SUMMARY */ - table_share->m_table_stat.aggregate_io(table_stat); + table_share->m_table_stat.aggregate_io(table_stat, key_count); table_stat->fast_reset_io(); } void PFS_table::safe_aggregate_lock(PFS_table_stat *table_stat, - PFS_table_share *table_share, - PFS_thread *thread) + PFS_table_share *table_share) { DBUG_ASSERT(table_stat != NULL); DBUG_ASSERT(table_share != NULL); - DBUG_ASSERT(thread != NULL); - - if (flag_thread_instrumentation && thread->m_enabled) - { - PFS_single_stat *event_name_array; - uint index; - event_name_array= thread->m_instr_class_waits_stats; - - /* - Aggregate to EVENTS_WAITS_SUMMARY_BY_THREAD_BY_EVENT_NAME - (for wait/lock/table/sql/handler) - */ - index= global_table_lock_class.m_event_name_index; - table_stat->sum_lock(& event_name_array[index]); - } /* Aggregate to TABLE_LOCK_SUMMARY */ table_share->m_table_stat.aggregate_lock(table_stat); @@ -1504,47 +1487,59 @@ void destroy_table(PFS_table *pfs) @param identity the socket descriptor @return a socket instance, or NULL */ -PFS_socket* create_socket(PFS_socket_class *klass, const void *identity) +PFS_socket* create_socket(PFS_socket_class *klass, const my_socket *fd, + const struct sockaddr *addr, socklen_t addr_len) { - PFS_scan scan; + static uint PFS_ALIGNED socket_monotonic_index= 0; + uint index; + uint attempts= 0; + PFS_socket *pfs; DBUG_ENTER("create_socket"); - /** - Unlike other instrumented objects, there is no socket 'object' to use as a - unique identifier. Instead, a pointer to the PFS_socket object will be used - to identify this socket instance. The socket descriptor will be used to - seed the the random index assignment. - */ - my_socket fd= likely(identity != NULL) ? - *(reinterpret_cast<const my_socket*>(identity)) : 0; - my_ptrdiff_t ptr= fd; - uint random= randomized_index((const void *)ptr, socket_max); - - for (scan.init(random, socket_max); - scan.has_pass(); - scan.next_pass()) - { - PFS_socket *pfs= socket_array + scan.first(); - PFS_socket *pfs_last= socket_array + scan.last(); - for ( ; pfs < pfs_last; pfs++) + uint fd_used= 0; + uint addr_len_used= addr_len; + + if (fd != NULL) + fd_used= *fd; + + if (addr_len_used > sizeof(sockaddr_storage)) + addr_len_used= sizeof(sockaddr_storage); + + while (++attempts <= socket_max) + { + index= PFS_atomic::add_u32(& socket_monotonic_index, 1) % socket_max; + pfs= socket_array + index; + + if (pfs->m_lock.is_free()) { - if (pfs->m_lock.is_free()) + if (pfs->m_lock.free_to_dirty()) { - if (pfs->m_lock.free_to_dirty()) + pfs->m_fd= fd_used; + /* There is no socket object, so we use the instrumentation. */ + pfs->m_identity= pfs; + pfs->m_class= klass; + pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; + pfs->m_timed= klass->m_timed; + pfs->m_idle= false; + pfs->m_socket_stat.reset(); + pfs->m_thread_owner= NULL; + + pfs->m_addr_len= addr_len_used; + if ((addr != NULL) && (addr_len_used > 0)) { - pfs->m_fd= fd; - pfs->m_identity= pfs; - pfs->m_class= klass; - pfs->m_enabled= klass->m_enabled && flag_global_instrumentation; - pfs->m_timed= klass->m_timed; - pfs->m_idle= false; - pfs->m_socket_stat.reset(); - pfs->m_lock.dirty_to_allocated(); - pfs->m_thread_owner= NULL; - if (klass->is_singleton()) - klass->m_singleton= pfs; - DBUG_RETURN(pfs); + pfs->m_addr_len= addr_len_used; + memcpy(&pfs->m_sock_addr, addr, addr_len_used); } + else + { + pfs->m_addr_len= 0; + } + + pfs->m_lock.dirty_to_allocated(); + + if (klass->is_singleton()) + klass->m_singleton= pfs; + DBUG_RETURN(pfs); } } } @@ -1598,7 +1593,7 @@ static void reset_mutex_waits_by_instance(void) DBUG_ENTER("reset_mutex_waits_by_instance"); for ( ; pfs < pfs_last; pfs++) - pfs->m_wait_stat.reset(); + pfs->m_mutex_stat.reset(); DBUG_VOID_RETURN; } @@ -1609,7 +1604,7 @@ static void reset_rwlock_waits_by_instance(void) DBUG_ENTER("reset_rwlock_waits_by_instance"); for ( ; pfs < pfs_last; pfs++) - pfs->m_wait_stat.reset(); + pfs->m_rwlock_stat.reset(); DBUG_VOID_RETURN; } @@ -1620,7 +1615,7 @@ static void reset_cond_waits_by_instance(void) DBUG_ENTER("reset_cond_waits_by_instance"); for ( ; pfs < pfs_last; pfs++) - pfs->m_wait_stat.reset(); + pfs->m_cond_stat.reset(); DBUG_VOID_RETURN; } @@ -1678,15 +1673,6 @@ void reset_socket_instance_io(void) DBUG_VOID_RETURN; } -void reset_global_wait_stat() -{ - PFS_single_stat *stat= global_instr_class_waits_array; - PFS_single_stat *stat_last= global_instr_class_waits_array + wait_class_max; - - for ( ; stat < stat_last; stat++) - stat->reset(); -} - void aggregate_all_event_names(PFS_single_stat *from_array, PFS_single_stat *to_array) { diff --git a/storage/perfschema/pfs_instr.h b/storage/perfschema/pfs_instr.h index b579c1d7902..2ea44830d2b 100644 --- a/storage/perfschema/pfs_instr.h +++ b/storage/perfschema/pfs_instr.h @@ -34,6 +34,8 @@ struct PFS_socket_class; #else #include <arpa/inet.h> #endif +#include "my_global.h" +#include "my_compiler.h" #include "pfs_lock.h" #include "pfs_stat.h" #include "pfs_instr_class.h" @@ -63,24 +65,17 @@ struct PFS_instr bool m_enabled; /** Timed flag. */ bool m_timed; - /** Instrument wait statistics. */ - PFS_single_stat m_wait_stat; }; /** Instrumented mutex implementation. @see PSI_mutex. */ -struct PFS_mutex : public PFS_instr +struct PFS_ALIGNED PFS_mutex : public PFS_instr { /** Mutex identity, typically a pthread_mutex_t. */ const void *m_identity; /** Mutex class. */ PFS_mutex_class *m_class; - /** Instrument wait statistics. */ - PFS_single_stat m_wait_stat; - /** - Mutex lock usage statistics. - This statistic is not exposed in user visible tables yet. - */ - PFS_single_stat m_lock_stat; + /** Instrument statistics. */ + PFS_mutex_stat m_mutex_stat; /** Current owner. */ PFS_thread *m_owner; /** @@ -91,24 +86,14 @@ struct PFS_mutex : public PFS_instr }; /** Instrumented rwlock implementation. @see PSI_rwlock. */ -struct PFS_rwlock : public PFS_instr +struct PFS_ALIGNED PFS_rwlock : public PFS_instr { /** RWLock identity, typically a pthread_rwlock_t. */ const void *m_identity; /** RWLock class. */ PFS_rwlock_class *m_class; - /** Instrument wait statistics. */ - PFS_single_stat m_wait_stat; - /** - RWLock read lock usage statistics. - This statistic is not exposed in user visible tables yet. - */ - PFS_single_stat m_read_lock_stat; - /** - RWLock write lock usage statistics. - This statistic is not exposed in user visible tables yet. - */ - PFS_single_stat m_write_lock_stat; + /** Instrument statistics. */ + PFS_rwlock_stat m_rwlock_stat; /** Current writer thread. */ PFS_thread *m_writer; /** Current count of readers. */ @@ -126,7 +111,7 @@ struct PFS_rwlock : public PFS_instr }; /** Instrumented cond implementation. @see PSI_cond. */ -struct PFS_cond : public PFS_instr +struct PFS_ALIGNED PFS_cond : public PFS_instr { /** Condition identity, typically a pthread_cond_t. */ const void *m_identity; @@ -139,7 +124,7 @@ struct PFS_cond : public PFS_instr }; /** Instrumented File and FILE implementation. @see PSI_file. */ -struct PFS_file : public PFS_instr +struct PFS_ALIGNED PFS_file : public PFS_instr { uint32 get_version() { return m_lock.get_version(); } @@ -152,14 +137,12 @@ struct PFS_file : public PFS_instr uint m_filename_length; /** File class. */ PFS_file_class *m_class; - /** Instrument wait statistics. */ - PFS_single_stat m_wait_stat; /** File usage statistics. */ PFS_file_stat m_file_stat; }; /** Instrumented table implementation. @see PSI_table. */ -struct PFS_table +struct PFS_ALIGNED PFS_table { /** True if table io instrumentation is enabled. @@ -196,12 +179,22 @@ public: */ void aggregate(void) { - if (likely((m_thread_owner != NULL) && (m_has_io_stats || m_has_lock_stats))) + if (m_has_io_stats && m_has_lock_stats) { - safe_aggregate(& m_table_stat, m_share, m_thread_owner); + safe_aggregate(& m_table_stat, m_share); m_has_io_stats= false; m_has_lock_stats= false; } + else if (m_has_io_stats) + { + safe_aggregate_io(& m_table_stat, m_share); + m_has_io_stats= false; + } + else if (m_has_lock_stats) + { + safe_aggregate_lock(& m_table_stat, m_share); + m_has_lock_stats= false; + } } /** @@ -238,18 +231,15 @@ public: private: static void safe_aggregate(PFS_table_stat *stat, - PFS_table_share *safe_share, - PFS_thread *safe_thread); + PFS_table_share *safe_share); static void safe_aggregate_io(PFS_table_stat *stat, - PFS_table_share *safe_share, - PFS_thread *safe_thread); + PFS_table_share *safe_share); static void safe_aggregate_lock(PFS_table_stat *stat, - PFS_table_share *safe_share, - PFS_thread *safe_thread); + PFS_table_share *safe_share); }; /** Instrumented socket implementation. @see PSI_socket. */ -struct PFS_socket : public PFS_instr +struct PFS_ALIGNED PFS_socket : public PFS_instr { uint32 get_version() { return m_lock.get_version(); } @@ -371,7 +361,7 @@ private: /** Instrumented thread implementation. @see PSI_thread. */ -struct PFS_thread : PFS_connection_slice +struct PFS_ALIGNED PFS_thread : PFS_connection_slice { static PFS_thread* get_current_thread(void); @@ -400,11 +390,11 @@ struct PFS_thread : PFS_connection_slice /** Pins for digest_hash. */ LF_PINS *m_digest_hash_pins; /** Internal thread identifier, unique. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Parent internal thread identifier. */ - ulong m_parent_thread_internal_id; + ulonglong m_parent_thread_internal_id; /** External (SHOW PROCESSLIST) thread identifier, not unique. */ - ulong m_thread_id; + ulong m_processlist_id; /** Thread class. */ PFS_thread_class *m_class; /** @@ -486,6 +476,8 @@ struct PFS_thread : PFS_connection_slice int m_command; /** Start time. */ time_t m_start_time; + /** Lock for Processlist state, Processlist info. */ + pfs_lock m_processlist_lock; /** Processlist state. */ const char *m_processlist_state_ptr; /** Length of @c m_processlist_state_ptr. */ @@ -504,9 +496,18 @@ struct PFS_thread : PFS_connection_slice PFS_host *m_host; PFS_user *m_user; PFS_account *m_account; + + /** Reset session connect attributes */ + void reset_session_connect_attrs(); + + /** a buffer for the connection attributes */ + char *m_session_connect_attrs; + /** length used by @c m_connect_attrs */ + uint m_session_connect_attrs_length; + /** character set in which @c m_connect_attrs are encoded */ + const CHARSET_INFO *m_session_connect_attrs_cs; }; -extern PFS_single_stat *global_instr_class_waits_array; extern PFS_stage_stat *global_instr_class_stages_array; extern PFS_statement_stat *global_instr_class_statements_array; @@ -529,12 +530,12 @@ PFS_cond* create_cond(PFS_cond_class *klass, const void *identity); void destroy_cond(PFS_cond *pfs); PFS_thread* create_thread(PFS_thread_class *klass, const void *identity, - ulong thread_id); + ulonglong processlist_id); void destroy_thread(PFS_thread *pfs); PFS_file* find_or_create_file(PFS_thread *thread, PFS_file_class *klass, - const char *filename, uint len); + const char *filename, uint len, bool create); void release_file(PFS_file *pfs); void destroy_file(PFS_thread *thread, PFS_file *pfs); @@ -542,7 +543,10 @@ PFS_table* create_table(PFS_table_share *share, PFS_thread *opening_thread, const void *identity); void destroy_table(PFS_table *pfs); -PFS_socket* create_socket(PFS_socket_class *socket_class, const void *identity); +PFS_socket* create_socket(PFS_socket_class *socket_class, + const my_socket *fd, + const struct sockaddr *addr, + socklen_t addr_len); void destroy_socket(PFS_socket *pfs); /* For iterators and show status. */ @@ -568,6 +572,8 @@ extern ulong events_stages_history_per_thread; extern ulong events_statements_history_per_thread; extern ulong locker_lost; extern ulong statement_lost; +extern ulong session_connect_attrs_lost; +extern ulong session_connect_attrs_size_per_thread; /* Exposing the data directly, for iterators. */ @@ -624,6 +630,8 @@ void update_socket_derived_flags(); /** Update derived flags for all instruments. */ void update_instruments_derived_flags(); +extern LF_HASH filename_hash; + /** @} */ #endif diff --git a/storage/perfschema/pfs_instr_class.cc b/storage/perfschema/pfs_instr_class.cc index 0a4b47404a4..24a06cf494c 100644 --- a/storage/perfschema/pfs_instr_class.cc +++ b/storage/perfschema/pfs_instr_class.cc @@ -135,9 +135,12 @@ static PFS_thread_class *thread_class_array= NULL; */ PFS_table_share *table_share_array= NULL; -PFS_instr_class global_table_io_class; -PFS_instr_class global_table_lock_class; -PFS_instr_class global_idle_class; +PFS_ALIGNED PFS_single_stat global_idle_stat; +PFS_ALIGNED PFS_table_io_stat global_table_io_stat; +PFS_ALIGNED PFS_table_lock_stat global_table_lock_stat; +PFS_ALIGNED PFS_instr_class global_table_io_class; +PFS_ALIGNED PFS_instr_class global_table_lock_class; +PFS_ALIGNED PFS_instr_class global_idle_class; /** Class-timer map */ enum_timer_name *class_timers[] = @@ -165,7 +168,7 @@ enum_timer_name *class_timers[] = @sa table_share_hash_get_key @sa get_table_share_hash_pins */ -static LF_HASH table_share_hash; +LF_HASH table_share_hash; /** True if table_share_hash is initialized. */ static bool table_share_hash_inited= false; @@ -193,19 +196,17 @@ uint mutex_class_start= 0; uint rwlock_class_start= 0; uint cond_class_start= 0; uint file_class_start= 0; -uint table_class_start= 0; uint wait_class_max= 0; uint socket_class_start= 0; void init_event_name_sizing(const PFS_global_param *param) { - mutex_class_start= 0; + mutex_class_start= 3; /* global table io, table lock, idle */ rwlock_class_start= mutex_class_start + param->m_mutex_class_sizing; cond_class_start= rwlock_class_start + param->m_rwlock_class_sizing; file_class_start= cond_class_start + param->m_cond_class_sizing; socket_class_start= file_class_start + param->m_file_class_sizing; - table_class_start= socket_class_start + param->m_socket_class_sizing; - wait_class_max= table_class_start + 3; /* global table io, lock, idle */ + wait_class_max= socket_class_start + param->m_socket_class_sizing; } void register_global_classes() @@ -213,19 +214,19 @@ void register_global_classes() /* Table IO class */ init_instr_class(&global_table_io_class, "wait/io/table/sql/handler", 25, 0, PFS_CLASS_TABLE_IO); - global_table_io_class.m_event_name_index= table_class_start; + global_table_io_class.m_event_name_index= GLOBAL_TABLE_IO_EVENT_INDEX; configure_instr_class(&global_table_io_class); /* Table lock class */ init_instr_class(&global_table_lock_class, "wait/lock/table/sql/handler", 27, 0, PFS_CLASS_TABLE_LOCK); - global_table_lock_class.m_event_name_index= table_class_start + 1; + global_table_lock_class.m_event_name_index= GLOBAL_TABLE_LOCK_EVENT_INDEX; configure_instr_class(&global_table_lock_class); /* Idle class */ init_instr_class(&global_idle_class, "idle", 4, 0, PFS_CLASS_IDLE); - global_idle_class.m_event_name_index= table_class_start + 2; + global_idle_class.m_event_name_index= GLOBAL_IDLE_EVENT_INDEX; configure_instr_class(&global_idle_class); } @@ -384,6 +385,7 @@ int init_table_share_hash(void) { lf_hash_init(&table_share_hash, sizeof(PFS_table_share*), LF_HASH_UNIQUE, 0, 0, table_share_hash_get_key, &my_charset_bin); + /* table_share_hash.size= table_share_max; */ table_share_hash_inited= true; } return 0; @@ -715,7 +717,7 @@ PFS_sync_key register_mutex_class(const char *name, uint name_length, */ entry= &mutex_class_array[index]; init_instr_class(entry, name, name_length, flags, PFS_CLASS_MUTEX); - entry->m_lock_stat.reset(); + entry->m_mutex_stat.reset(); entry->m_event_name_index= mutex_class_start + index; entry->m_singleton= NULL; entry->m_enabled= false; /* disabled by default */ @@ -781,8 +783,7 @@ PFS_sync_key register_rwlock_class(const char *name, uint name_length, { entry= &rwlock_class_array[index]; init_instr_class(entry, name, name_length, flags, PFS_CLASS_RWLOCK); - entry->m_read_lock_stat.reset(); - entry->m_write_lock_stat.reset(); + entry->m_rwlock_stat.reset(); entry->m_event_name_index= rwlock_class_start + index; entry->m_singleton= NULL; entry->m_enabled= false; /* disabled by default */ @@ -1193,7 +1194,7 @@ static void set_keys(PFS_table_share *pfs, const TABLE_SHARE *share) pfs_key->m_name_length= len; } - pfs_key_last= pfs->m_keys + MAX_KEY; + pfs_key_last= pfs->m_keys + MAX_INDEXES; for ( ; pfs_key < pfs_key_last; pfs_key++) pfs_key->m_name_length= 0; } @@ -1256,7 +1257,7 @@ PFS_table_share* find_or_create_table_share(PFS_thread *thread, const uint retry_max= 3; bool enabled= true; bool timed= true; - static uint table_share_monotonic_index= 0; + static uint PFS_ALIGNED table_share_monotonic_index= 0; uint index; uint attempts= 0; PFS_table_share *pfs; @@ -1299,8 +1300,7 @@ search: while (++attempts <= table_share_max) { /* See create_mutex() */ - PFS_atomic::add_u32(& table_share_monotonic_index, 1); - index= table_share_monotonic_index % table_share_max; + index= PFS_atomic::add_u32(& table_share_monotonic_index, 1) % table_share_max; pfs= table_share_array + index; if (pfs->m_lock.is_free()) @@ -1353,17 +1353,28 @@ search: void PFS_table_share::aggregate_io(void) { - uint index= global_table_io_class.m_event_name_index; - PFS_single_stat *table_io_total= & global_instr_class_waits_array[index]; - m_table_stat.sum_io(table_io_total); + uint safe_key_count= sanitize_index_count(m_key_count); + PFS_table_io_stat *from_stat; + PFS_table_io_stat *from_stat_last; + PFS_table_io_stat sum_io; + + /* Aggregate stats for each index, if any */ + from_stat= & m_table_stat.m_index_stat[0]; + from_stat_last= from_stat + safe_key_count; + for ( ; from_stat < from_stat_last ; from_stat++) + sum_io.aggregate(from_stat); + + /* Aggregate stats for the table */ + sum_io.aggregate(& m_table_stat.m_index_stat[MAX_INDEXES]); + + /* Add this table stats to the global sink. */ + global_table_io_stat.aggregate(& sum_io); m_table_stat.fast_reset_io(); } void PFS_table_share::aggregate_lock(void) { - uint index= global_table_lock_class.m_event_name_index; - PFS_single_stat *table_lock_total= & global_instr_class_waits_array[index]; - m_table_stat.sum_lock(table_lock_total); + global_table_lock_stat.aggregate(& m_table_stat.m_lock_stat); m_table_stat.fast_reset_lock(); } @@ -1418,6 +1429,16 @@ PFS_table_share *sanitize_table_share(PFS_table_share *unsafe) SANITIZE_ARRAY_BODY(PFS_table_share, table_share_array, table_share_max, unsafe); } +/** Reset the wait statistics per instrument class. */ +void reset_events_waits_by_class() +{ + reset_file_class_io(); + reset_socket_class_io(); + global_idle_stat.reset(); + global_table_io_stat.reset(); + global_table_lock_stat.reset(); +} + /** Reset the io statistics per file class. */ void reset_file_class_io(void) { diff --git a/storage/perfschema/pfs_instr_class.h b/storage/perfschema/pfs_instr_class.h index bef25e76467..d0b90734b66 100644 --- a/storage/perfschema/pfs_instr_class.h +++ b/storage/perfschema/pfs_instr_class.h @@ -16,7 +16,10 @@ #ifndef PFS_INSTR_CLASS_H #define PFS_INSTR_CLASS_H +#include "my_global.h" #include "mysql_com.h" /* NAME_LEN */ +#include "lf.h" +#include "pfs_global.h" /** @file storage/perfschema/pfs_instr_class.h @@ -112,7 +115,6 @@ extern uint mutex_class_start; extern uint rwlock_class_start; extern uint cond_class_start; extern uint file_class_start; -extern uint table_class_start; extern uint socket_class_start; extern uint wait_class_max; @@ -166,13 +168,10 @@ struct PFS_instr_class struct PFS_mutex; /** Instrumentation metadata for a MUTEX. */ -struct PFS_mutex_class : public PFS_instr_class +struct PFS_ALIGNED PFS_mutex_class : public PFS_instr_class { - /** - Lock statistics. - This statistic is not exposed in user visible tables yet. - */ - PFS_single_stat m_lock_stat; + /** Mutex usage statistics. */ + PFS_mutex_stat m_mutex_stat; /** Singleton instance. */ PFS_mutex *m_singleton; }; @@ -180,18 +179,10 @@ struct PFS_mutex_class : public PFS_instr_class struct PFS_rwlock; /** Instrumentation metadata for a RWLOCK. */ -struct PFS_rwlock_class : public PFS_instr_class +struct PFS_ALIGNED PFS_rwlock_class : public PFS_instr_class { - /** - Read lock statistics. - This statistic is not exposed in user visible tables yet. - */ - PFS_single_stat m_read_lock_stat; - /** - Write lock statistics. - This statistic is not exposed in user visible tables yet. - */ - PFS_single_stat m_write_lock_stat; + /** Rwlock usage statistics. */ + PFS_rwlock_stat m_rwlock_stat; /** Singleton instance. */ PFS_rwlock *m_singleton; }; @@ -199,7 +190,7 @@ struct PFS_rwlock_class : public PFS_instr_class struct PFS_cond; /** Instrumentation metadata for a COND. */ -struct PFS_cond_class : public PFS_instr_class +struct PFS_ALIGNED PFS_cond_class : public PFS_instr_class { /** Condition usage statistics. @@ -211,7 +202,7 @@ struct PFS_cond_class : public PFS_instr_class }; /** Instrumentation metadata of a thread. */ -struct PFS_thread_class +struct PFS_ALIGNED PFS_thread_class { /** True if this thread instrument is enabled. */ bool m_enabled; @@ -249,7 +240,7 @@ struct PFS_table_key }; /** Instrumentation metadata for a table share. */ -struct PFS_table_share +struct PFS_ALIGNED PFS_table_share { public: uint32 get_version() @@ -318,13 +309,31 @@ public: /** Table statistics. */ PFS_table_stat m_table_stat; /** Index names. */ - PFS_table_key m_keys[MAX_KEY]; + PFS_table_key m_keys[MAX_INDEXES]; private: /** Number of opened table handles. */ int m_refcount; }; +/** Statistics for the IDLE instrument. */ +extern PFS_single_stat global_idle_stat; +/** Statistics for dropped table io. */ +extern PFS_table_io_stat global_table_io_stat; +/** Statistics for dropped table lock. */ +extern PFS_table_lock_stat global_table_lock_stat; + +inline uint sanitize_index_count(uint count) +{ + if (likely(count <= MAX_INDEXES)) + return count; + return 0; +} + +#define GLOBAL_TABLE_IO_EVENT_INDEX 0 +#define GLOBAL_TABLE_LOCK_EVENT_INDEX 1 +#define GLOBAL_IDLE_EVENT_INDEX 2 + /** Instrument controlling all table io. This instrument is used with table SETUP_OBJECTS. @@ -345,7 +354,7 @@ extern PFS_instr_class global_idle_class; struct PFS_file; /** Instrumentation metadata for a file. */ -struct PFS_file_class : public PFS_instr_class +struct PFS_ALIGNED PFS_file_class : public PFS_instr_class { /** File usage statistics. */ PFS_file_stat m_file_stat; @@ -354,21 +363,21 @@ struct PFS_file_class : public PFS_instr_class }; /** Instrumentation metadata for a stage. */ -struct PFS_stage_class : public PFS_instr_class +struct PFS_ALIGNED PFS_stage_class : public PFS_instr_class { /** Stage usage statistics. */ PFS_stage_stat m_stage_stat; }; /** Instrumentation metadata for a statement. */ -struct PFS_statement_class : public PFS_instr_class +struct PFS_ALIGNED PFS_statement_class : public PFS_instr_class { }; struct PFS_socket; /** Instrumentation metadata for a socket. */ -struct PFS_socket_class : public PFS_instr_class +struct PFS_ALIGNED PFS_socket_class : public PFS_instr_class { /** Socket usage statistics. */ PFS_socket_stat m_socket_stat; @@ -483,12 +492,15 @@ extern PFS_cond_class *cond_class_array; extern PFS_file_class *file_class_array; extern PFS_table_share *table_share_array; +void reset_events_waits_by_class(); void reset_file_class_io(); void reset_socket_class_io(); /** Update derived flags for all table shares. */ void update_table_share_derived_flags(PFS_thread *thread); +extern LF_HASH table_share_hash; + /** @} */ #endif diff --git a/storage/perfschema/pfs_lock.h b/storage/perfschema/pfs_lock.h index 65937e94ece..09efecd1c5f 100644 --- a/storage/perfschema/pfs_lock.h +++ b/storage/perfschema/pfs_lock.h @@ -33,7 +33,7 @@ Values of a free record should not be read by a reader. Writers can concurrently attempt to allocate a free record. */ -#define PFS_LOCK_FREE 0 +#define PFS_LOCK_FREE 0x00 /** State of a dirty record. Values of a dirty record should not be read by a reader, @@ -41,14 +41,18 @@ Only one writer, the writer which owns the record, should modify the record content. */ -#define PFS_LOCK_DIRTY 1 +#define PFS_LOCK_DIRTY 0x01 /** State of an allocated record. Values of an allocated record are safe to read by a reader. A writer may modify some but not all properties of the record: only modifying values that can never cause the reader to crash is allowed. */ -#define PFS_LOCK_ALLOCATED 2 +#define PFS_LOCK_ALLOCATED 0x02 + +#define VERSION_MASK 0xFFFFFFFC +#define STATE_MASK 0x00000003 +#define VERSION_INC 4 /** A 'lock' protecting performance schema internal buffers. @@ -60,15 +64,11 @@ struct pfs_lock { /** - The record internal state. + The record internal version and state @sa PFS_LOCK_FREE @sa PFS_LOCK_DIRTY @sa PFS_LOCK_ALLOCATED - */ - volatile int32 m_state; - /** - The record internal version number. - This version number is to transform the 'ABA' problem + The version number is to transform the 'ABA' problem (see http://en.wikipedia.org/wiki/ABA_problem) into an 'A(n)BA(n + 1)' problem, where 'n' is the m_version number. When the performance schema instrumentation deletes a record, @@ -76,21 +76,23 @@ struct pfs_lock the version number is incremented, so that a reader can detect that the record was changed. Note that the version number is never reset to zero when a new record is created. + The version number is stored in the high 30 bits. + The state is stored in the low 2 bits. */ - volatile uint32 m_version; + volatile uint32 m_version_state; /** Returns true if the record is free. */ bool is_free(void) { - /* This is a dirty read */ - return (m_state == PFS_LOCK_FREE); + uint32 copy= m_version_state; /* non volatile copy, and dirty read */ + return ((copy & STATE_MASK) == PFS_LOCK_FREE); } /** Returns true if the record contains values that can be read. */ bool is_populated(void) { - int32 copy= m_state; /* non volatile copy, and dirty read */ - return (copy == PFS_LOCK_ALLOCATED); + uint32 copy= m_version_state; /* non volatile copy, and dirty read */ + return ((copy & STATE_MASK) == PFS_LOCK_ALLOCATED); } /** @@ -101,10 +103,11 @@ struct pfs_lock */ bool free_to_dirty(void) { - int32 old_state= PFS_LOCK_FREE; - int32 new_state= PFS_LOCK_DIRTY; + uint32 copy= m_version_state; /* non volatile copy, and dirty read */ + uint32 old_val= (copy & VERSION_MASK) + PFS_LOCK_FREE; + uint32 new_val= (copy & VERSION_MASK) + PFS_LOCK_DIRTY; - return (PFS_atomic::cas_32(&m_state, &old_state, new_state)); + return (PFS_atomic::cas_u32(&m_version_state, &old_val, new_val)); } /** @@ -114,8 +117,13 @@ struct pfs_lock */ void allocated_to_dirty(void) { - DBUG_ASSERT(m_state == PFS_LOCK_ALLOCATED); - PFS_atomic::store_32(&m_state, PFS_LOCK_DIRTY); + uint32 copy= PFS_atomic::load_u32(&m_version_state); + /* Make sure the record was ALLOCATED. */ + DBUG_ASSERT((copy & STATE_MASK) == PFS_LOCK_ALLOCATED); + /* Keep the same version, set the DIRTY state */ + uint32 new_val= (copy & VERSION_MASK) + PFS_LOCK_DIRTY; + /* We own the record, no need to use compare and swap. */ + PFS_atomic::store_u32(&m_version_state, new_val); } /** @@ -125,9 +133,26 @@ struct pfs_lock */ void dirty_to_allocated(void) { - DBUG_ASSERT(m_state == PFS_LOCK_DIRTY); - PFS_atomic::add_u32(&m_version, 1); - PFS_atomic::store_32(&m_state, PFS_LOCK_ALLOCATED); + uint32 copy= PFS_atomic::load_u32(&m_version_state); + /* Make sure the record was DIRTY. */ + DBUG_ASSERT((copy & STATE_MASK) == PFS_LOCK_DIRTY); + /* Increment the version, set the ALLOCATED state */ + uint32 new_val= (copy & VERSION_MASK) + VERSION_INC + PFS_LOCK_ALLOCATED; + PFS_atomic::store_u32(&m_version_state, new_val); + } + + /** + Initialize a lock to allocated. + This transition should be executed by the writer that owns the record and the lock, + after the record is in a state ready to be read. + */ + void set_allocated(void) + { + /* Do not set the version to 0, read the previous value. */ + uint32 copy= PFS_atomic::load_u32(&m_version_state); + /* Increment the version, set the ALLOCATED state */ + uint32 new_val= (copy & VERSION_MASK) + VERSION_INC + PFS_LOCK_ALLOCATED; + PFS_atomic::store_u32(&m_version_state, new_val); } /** @@ -136,8 +161,12 @@ struct pfs_lock */ void dirty_to_free(void) { - DBUG_ASSERT(m_state == PFS_LOCK_DIRTY); - PFS_atomic::store_32(&m_state, PFS_LOCK_FREE); + uint32 copy= PFS_atomic::load_u32(&m_version_state); + /* Make sure the record was DIRTY. */ + DBUG_ASSERT((copy & STATE_MASK) == PFS_LOCK_DIRTY); + /* Keep the same version, set the FREE state */ + uint32 new_val= (copy & VERSION_MASK) + PFS_LOCK_FREE; + PFS_atomic::store_u32(&m_version_state, new_val); } /** @@ -153,8 +182,12 @@ struct pfs_lock The correct assert to use here to guarantee data integrity is simply: DBUG_ASSERT(m_state == PFS_LOCK_ALLOCATED); */ - DBUG_ASSERT(m_state == PFS_LOCK_ALLOCATED); - PFS_atomic::store_32(&m_state, PFS_LOCK_FREE); + uint32 copy= PFS_atomic::load_u32(&m_version_state); + /* Make sure the record was ALLOCATED. */ + DBUG_ASSERT(((copy & STATE_MASK) == PFS_LOCK_ALLOCATED)); + /* Keep the same version, set the FREE state */ + uint32 new_val= (copy & VERSION_MASK) + PFS_LOCK_FREE; + PFS_atomic::store_u32(&m_version_state, new_val); } /** @@ -163,8 +196,7 @@ struct pfs_lock */ void begin_optimistic_lock(struct pfs_lock *copy) { - copy->m_version= PFS_atomic::load_u32(&m_version); - copy->m_state= PFS_atomic::load_32(&m_state); + copy->m_version_state= PFS_atomic::load_u32(&m_version_state); } /** @@ -174,19 +206,20 @@ struct pfs_lock */ bool end_optimistic_lock(struct pfs_lock *copy) { - /* - return true if: - - the version + state has not changed - - and there was valid data to look at - */ - return ((copy->m_version == PFS_atomic::load_u32(&m_version)) && - (copy->m_state == PFS_atomic::load_32(&m_state)) && - (copy->m_state == PFS_LOCK_ALLOCATED)); + /* Check there was valid data to look at. */ + if ((copy->m_version_state & STATE_MASK) != PFS_LOCK_ALLOCATED) + return false; + + /* Check the version + state has not changed. */ + if (copy->m_version_state != PFS_atomic::load_u32(&m_version_state)) + return false; + + return true; } uint32 get_version() { - return PFS_atomic::load_u32(&m_version); + return (PFS_atomic::load_u32(&m_version_state) & VERSION_MASK); } }; diff --git a/storage/perfschema/pfs_server.cc b/storage/perfschema/pfs_server.cc index 3df0f27f652..383a46785fb 100644 --- a/storage/perfschema/pfs_server.cc +++ b/storage/perfschema/pfs_server.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 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 @@ -50,11 +50,16 @@ static void cleanup_performance_schema(void); void cleanup_instrument_config(void); struct PSI_bootstrap* -initialize_performance_schema(const PFS_global_param *param) +initialize_performance_schema(PFS_global_param *param) { pfs_initialized= false; PFS_table_stat::g_reset_template.reset(); + global_idle_stat.reset(); + global_table_io_stat.reset(); + global_table_lock_stat.reset(); + + pfs_automated_sizing(param); if (! param->m_enabled) { diff --git a/storage/perfschema/pfs_server.h b/storage/perfschema/pfs_server.h index f65febdeb6d..e0c782fde58 100644 --- a/storage/perfschema/pfs_server.h +++ b/storage/perfschema/pfs_server.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 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 @@ -24,96 +24,50 @@ #ifndef PFS_MAX_MUTEX_CLASS #define PFS_MAX_MUTEX_CLASS 200 #endif -#ifndef PFS_MAX_MUTEX - #define PFS_MAX_MUTEX 1000000 -#endif #ifndef PFS_MAX_RWLOCK_CLASS #define PFS_MAX_RWLOCK_CLASS 30 #endif -#ifndef PFS_MAX_RWLOCK - #define PFS_MAX_RWLOCK 1000000 -#endif #ifndef PFS_MAX_COND_CLASS #define PFS_MAX_COND_CLASS 80 #endif -#ifndef PFS_MAX_COND - #define PFS_MAX_COND 1000 -#endif #ifndef PFS_MAX_THREAD_CLASS #define PFS_MAX_THREAD_CLASS 50 #endif -#ifndef PFS_MAX_THREAD - #define PFS_MAX_THREAD 1000 -#endif #ifndef PFS_MAX_FILE_CLASS #define PFS_MAX_FILE_CLASS 50 #endif -#ifndef PFS_MAX_FILE - #define PFS_MAX_FILE 10000 -#endif #ifndef PFS_MAX_FILE_HANDLE #define PFS_MAX_FILE_HANDLE 32768 #endif -#ifndef PFS_MAX_SOCKETS - #define PFS_MAX_SOCKETS 1000 -#endif #ifndef PFS_MAX_SOCKET_CLASS #define PFS_MAX_SOCKET_CLASS 10 #endif -#ifndef PFS_MAX_TABLE_SHARE - #define PFS_MAX_TABLE_SHARE 1000 -#endif -#ifndef PFS_MAX_TABLE - #define PFS_MAX_TABLE 10000 -#endif -#ifndef PFS_WAITS_HISTORY_SIZE - #define PFS_WAITS_HISTORY_SIZE 10 -#endif -#ifndef PFS_WAITS_HISTORY_LONG_SIZE - #define PFS_WAITS_HISTORY_LONG_SIZE 10000 -#endif #ifndef PFS_MAX_SETUP_ACTOR #define PFS_MAX_SETUP_ACTOR 100 #endif #ifndef PFS_MAX_SETUP_OBJECT #define PFS_MAX_SETUP_OBJECT 100 #endif -#ifndef PFS_MAX_HOST - #define PFS_MAX_HOST 100 -#endif -#ifndef PFS_MAX_USER - #define PFS_MAX_USER 100 -#endif -#ifndef PFS_MAX_ACCOUNT - #define PFS_MAX_ACCOUNT 100 -#endif #ifndef PFS_MAX_STAGE_CLASS #define PFS_MAX_STAGE_CLASS 150 #endif -#ifndef PFS_STAGES_HISTORY_SIZE - #define PFS_STAGES_HISTORY_SIZE 10 -#endif -#ifndef PFS_STAGES_HISTORY_LONG_SIZE - #define PFS_STAGES_HISTORY_LONG_SIZE 10000 -#endif -#ifndef PFS_STATEMENTS_HISTORY_SIZE - #define PFS_STATEMENTS_HISTORY_SIZE 10 -#endif -#ifndef PFS_STATEMENTS_HISTORY_LONG_SIZE - #define PFS_STATEMENTS_HISTORY_LONG_SIZE 10000 -#endif #ifndef PFS_STATEMENTS_STACK_SIZE #define PFS_STATEMENTS_STACK_SIZE 10 #endif -#ifndef PFS_DIGEST_SIZE - #define PFS_DIGEST_SIZE 200 -#endif + +struct PFS_sizing_hints +{ + long m_table_definition_cache; + long m_table_open_cache; + long m_max_connections; + long m_open_files_limit; +}; /** Performance schema global sizing parameters. */ struct PFS_global_param { /** True if the performance schema is enabled. */ - bool m_enabled; + bool m_enabled; /** Default values for SETUP_CONSUMERS. */ bool m_consumer_events_stages_current_enabled; bool m_consumer_events_stages_history_enabled; @@ -155,7 +109,7 @@ struct PFS_global_param Maximum number of instrumented table share. @sa table_share_lost. */ - ulong m_table_share_sizing; + long m_table_share_sizing; /** Maximum number of instrumented file classes. @sa file_class_lost. @@ -165,81 +119,86 @@ struct PFS_global_param Maximum number of instrumented mutex instances. @sa mutex_lost. */ - ulong m_mutex_sizing; + long m_mutex_sizing; /** Maximum number of instrumented rwlock instances. @sa rwlock_lost. */ - ulong m_rwlock_sizing; + long m_rwlock_sizing; /** Maximum number of instrumented cond instances. @sa cond_lost. */ - ulong m_cond_sizing; + long m_cond_sizing; /** Maximum number of instrumented thread instances. @sa thread_lost. */ - ulong m_thread_sizing; + long m_thread_sizing; /** Maximum number of instrumented table handles. @sa table_lost. */ - ulong m_table_sizing; + long m_table_sizing; /** Maximum number of instrumented file instances. @sa file_lost. */ - ulong m_file_sizing; + long m_file_sizing; /** Maximum number of instrumented file handles. @sa file_handle_lost. */ - ulong m_file_handle_sizing; + long m_file_handle_sizing; /** Maxium number of instrumented socket instances @sa socket_lost */ - ulong m_socket_sizing; + long m_socket_sizing; /** Maximum number of instrumented socket classes. @sa socket_class_lost. */ ulong m_socket_class_sizing; /** Maximum number of rows per thread in table EVENTS_WAITS_HISTORY. */ - ulong m_events_waits_history_sizing; + long m_events_waits_history_sizing; /** Maximum number of rows in table EVENTS_WAITS_HISTORY_LONG. */ - ulong m_events_waits_history_long_sizing; + long m_events_waits_history_long_sizing; /** Maximum number of rows in table SETUP_ACTORS. */ ulong m_setup_actor_sizing; /** Maximum number of rows in table SETUP_OBJECTS. */ ulong m_setup_object_sizing; /** Maximum number of rows in table HOSTS. */ - ulong m_host_sizing; + long m_host_sizing; /** Maximum number of rows in table USERS. */ - ulong m_user_sizing; + long m_user_sizing; /** Maximum number of rows in table ACCOUNTS. */ - ulong m_account_sizing; + long m_account_sizing; /** Maximum number of instrumented stage classes. @sa stage_class_lost. */ ulong m_stage_class_sizing; /** Maximum number of rows per thread in table EVENTS_STAGES_HISTORY. */ - ulong m_events_stages_history_sizing; + long m_events_stages_history_sizing; /** Maximum number of rows in table EVENTS_STAGES_HISTORY_LONG. */ - ulong m_events_stages_history_long_sizing; + long m_events_stages_history_long_sizing; /** Maximum number of instrumented statement classes. @sa statement_class_lost. */ ulong m_statement_class_sizing; /** Maximum number of rows per thread in table EVENTS_STATEMENT_HISTORY. */ - ulong m_events_statements_history_sizing; + long m_events_statements_history_sizing; /** Maximum number of rows in table EVENTS_STATEMENTS_HISTORY_LONG. */ - ulong m_events_statements_history_long_sizing; + long m_events_statements_history_long_sizing; /** Maximum number of digests to be captured */ - ulong m_digest_sizing; + long m_digest_sizing; + /** Maximum number of session attribute strings per thread */ + long m_session_connect_attrs_sizing; + + /** Sizing hints, for auto tuning. */ + PFS_sizing_hints m_hints; }; /** @@ -254,7 +213,9 @@ extern PFS_global_param pfs_param; @return A boostrap handle, or NULL. */ struct PSI_bootstrap* -initialize_performance_schema(const PFS_global_param *param); +initialize_performance_schema(PFS_global_param *param); + +void pfs_automated_sizing(PFS_global_param *param); /** Initialize the performance schema ACL. diff --git a/storage/perfschema/pfs_setup_actor.cc b/storage/perfschema/pfs_setup_actor.cc index a587d3643d2..ff45e4a0971 100644 --- a/storage/perfschema/pfs_setup_actor.cc +++ b/storage/perfschema/pfs_setup_actor.cc @@ -43,7 +43,7 @@ ulong setup_actor_max; PFS_setup_actor *setup_actor_array= NULL; /** Hash table for setup_actor records. */ -static LF_HASH setup_actor_hash; +LF_HASH setup_actor_hash; /** True if @c setup_actor_hash is initialized. */ static bool setup_actor_hash_inited= false; @@ -100,10 +100,11 @@ C_MODE_END */ int init_setup_actor_hash(void) { - if (! setup_actor_hash_inited) + if ((! setup_actor_hash_inited) && (setup_actor_max > 0)) { lf_hash_init(&setup_actor_hash, sizeof(PFS_setup_actor*), LF_HASH_UNIQUE, 0, 0, setup_actor_hash_get_key, &my_charset_bin); + /* setup_actor_hash.size= setup_actor_max; */ setup_actor_hash_inited= true; } return 0; @@ -167,7 +168,7 @@ int insert_setup_actor(const String *user, const String *host, const String *rol if (unlikely(pins == NULL)) return HA_ERR_OUT_OF_MEM; - static uint setup_actor_monotonic_index= 0; + static uint PFS_ALIGNED setup_actor_monotonic_index= 0; uint index; uint attempts= 0; PFS_setup_actor *pfs; @@ -175,8 +176,7 @@ int insert_setup_actor(const String *user, const String *host, const String *rol while (++attempts <= setup_actor_max) { /* See create_mutex() */ - PFS_atomic::add_u32(& setup_actor_monotonic_index, 1); - index= setup_actor_monotonic_index % setup_actor_max; + index= PFS_atomic::add_u32(& setup_actor_monotonic_index, 1) % setup_actor_max; pfs= setup_actor_array + index; if (pfs->m_lock.is_free()) diff --git a/storage/perfschema/pfs_setup_actor.h b/storage/perfschema/pfs_setup_actor.h index 8b0ee8a485c..baebd27f0ad 100644 --- a/storage/perfschema/pfs_setup_actor.h +++ b/storage/perfschema/pfs_setup_actor.h @@ -49,7 +49,7 @@ struct PFS_setup_actor_key }; /** A setup_actor record. */ -struct PFS_setup_actor +struct PFS_ALIGNED PFS_setup_actor { /** Internal lock. */ pfs_lock m_lock; @@ -92,6 +92,8 @@ extern ulong setup_actor_max; extern PFS_setup_actor *setup_actor_array; +extern LF_HASH setup_actor_hash; + /** @} */ #endif diff --git a/storage/perfschema/pfs_setup_object.cc b/storage/perfschema/pfs_setup_object.cc index a9e9bb7881b..535dd53bfc7 100644 --- a/storage/perfschema/pfs_setup_object.cc +++ b/storage/perfschema/pfs_setup_object.cc @@ -39,7 +39,7 @@ ulong setup_object_max; PFS_setup_object *setup_object_array= NULL; -static LF_HASH setup_object_hash; +LF_HASH setup_object_hash; static bool setup_object_hash_inited= false; /** @@ -95,10 +95,11 @@ C_MODE_END */ int init_setup_object_hash(void) { - if (! setup_object_hash_inited) + if ((! setup_object_hash_inited) && (setup_object_max > 0)) { lf_hash_init(&setup_object_hash, sizeof(PFS_setup_object*), LF_HASH_UNIQUE, 0, 0, setup_object_hash_get_key, &my_charset_bin); + /* setup_object_hash.size= setup_object_max; */ setup_object_hash_inited= true; } return 0; @@ -109,8 +110,8 @@ void cleanup_setup_object_hash(void) { if (setup_object_hash_inited) { - lf_hash_destroy(&setup_object_hash); setup_object_hash_inited= false; + lf_hash_destroy(&setup_object_hash); } } @@ -161,7 +162,7 @@ int insert_setup_object(enum_object_type object_type, const String *schema, if (unlikely(pins == NULL)) return HA_ERR_OUT_OF_MEM; - static uint setup_object_monotonic_index= 0; + static uint PFS_ALIGNED setup_object_monotonic_index= 0; uint index; uint attempts= 0; PFS_setup_object *pfs; @@ -169,8 +170,7 @@ int insert_setup_object(enum_object_type object_type, const String *schema, while (++attempts <= setup_object_max) { /* See create_mutex() */ - PFS_atomic::add_u32(& setup_object_monotonic_index, 1); - index= setup_object_monotonic_index % setup_object_max; + index= PFS_atomic::add_u32(& setup_object_monotonic_index, 1) % setup_object_max; pfs= setup_object_array + index; if (pfs->m_lock.is_free()) diff --git a/storage/perfschema/pfs_setup_object.h b/storage/perfschema/pfs_setup_object.h index 44d2b76c627..2615802fe01 100644 --- a/storage/perfschema/pfs_setup_object.h +++ b/storage/perfschema/pfs_setup_object.h @@ -45,7 +45,7 @@ struct PFS_setup_object_key }; /** A setup_object record. */ -struct PFS_setup_object +struct PFS_ALIGNED PFS_setup_object { enum_object_type get_object_type() { @@ -96,6 +96,8 @@ extern ulong setup_object_max; extern PFS_setup_object *setup_object_array; +extern LF_HASH setup_object_hash; + /** @} */ #endif diff --git a/storage/perfschema/pfs_stat.h b/storage/perfschema/pfs_stat.h index 32c462b8ba2..2a255a9e5b2 100644 --- a/storage/perfschema/pfs_stat.h +++ b/storage/perfschema/pfs_stat.h @@ -140,13 +140,90 @@ struct PFS_byte_stat : public PFS_single_stat } }; +/** Statistics for mutex usage. */ +struct PFS_mutex_stat +{ + /** Wait statistics. */ + PFS_single_stat m_wait_stat; + /** + Lock statistics. + This statistic is not exposed in user visible tables yet. + */ + PFS_single_stat m_lock_stat; + + inline void aggregate(const PFS_mutex_stat *stat) + { + m_wait_stat.aggregate(&stat->m_wait_stat); + m_lock_stat.aggregate(&stat->m_lock_stat); + } + + inline void reset(void) + { + m_wait_stat.reset(); + m_lock_stat.reset(); + } +}; + +/** Statistics for rwlock usage. */ +struct PFS_rwlock_stat +{ + /** Wait statistics. */ + PFS_single_stat m_wait_stat; + /** + RWLock read lock usage statistics. + This statistic is not exposed in user visible tables yet. + */ + PFS_single_stat m_read_lock_stat; + /** + RWLock write lock usage statistics. + This statistic is not exposed in user visible tables yet. + */ + PFS_single_stat m_write_lock_stat; + + inline void aggregate(const PFS_rwlock_stat *stat) + { + m_wait_stat.aggregate(&stat->m_wait_stat); + m_read_lock_stat.aggregate(&stat->m_read_lock_stat); + m_write_lock_stat.aggregate(&stat->m_write_lock_stat); + } + + inline void reset(void) + { + m_wait_stat.reset(); + m_read_lock_stat.reset(); + m_write_lock_stat.reset(); + } +}; + /** Statistics for COND usage. */ struct PFS_cond_stat { - /** Number of times a condition was signalled. */ + /** Wait statistics. */ + PFS_single_stat m_wait_stat; + /** + Number of times a condition was signalled. + This statistic is not exposed in user visible tables yet. + */ ulonglong m_signal_count; - /** Number of times a condition was broadcasted. */ + /** + Number of times a condition was broadcast. + This statistic is not exposed in user visible tables yet. + */ ulonglong m_broadcast_count; + + inline void aggregate(const PFS_cond_stat *stat) + { + m_wait_stat.aggregate(&stat->m_wait_stat); + m_signal_count+= stat->m_signal_count; + m_broadcast_count+= stat->m_broadcast_count; + } + + inline void reset(void) + { + m_wait_stat.reset(); + m_signal_count= 0; + m_broadcast_count= 0; + } }; /** Statistics for FILE IO. Used for both waits and byte counts. */ @@ -198,6 +275,11 @@ struct PFS_file_stat /** File IO statistics. */ PFS_file_io_stat m_io_stat; + inline void aggregate(const PFS_file_stat *stat) + { + m_io_stat.aggregate(&stat->m_io_stat); + } + /** Reset file statistics. */ inline void reset(void) { @@ -329,6 +411,7 @@ struct PFS_statement_stat /** Single table io statistic. */ struct PFS_table_io_stat { + bool m_has_data; /** FETCH statistics */ PFS_single_stat m_fetch; /** INSERT statistics */ @@ -338,8 +421,14 @@ struct PFS_table_io_stat /** DELETE statistics */ PFS_single_stat m_delete; + PFS_table_io_stat() + { + m_has_data= false; + } + inline void reset(void) { + m_has_data= false; m_fetch.reset(); m_insert.reset(); m_update.reset(); @@ -348,18 +437,25 @@ struct PFS_table_io_stat inline void aggregate(const PFS_table_io_stat *stat) { - m_fetch.aggregate(&stat->m_fetch); - m_insert.aggregate(&stat->m_insert); - m_update.aggregate(&stat->m_update); - m_delete.aggregate(&stat->m_delete); + if (stat->m_has_data) + { + m_has_data= true; + m_fetch.aggregate(&stat->m_fetch); + m_insert.aggregate(&stat->m_insert); + m_update.aggregate(&stat->m_update); + m_delete.aggregate(&stat->m_delete); + } } inline void sum(PFS_single_stat *result) { - result->aggregate(& m_fetch); - result->aggregate(& m_insert); - result->aggregate(& m_update); - result->aggregate(& m_delete); + if (m_has_data) + { + result->aggregate(& m_fetch); + result->aggregate(& m_insert); + result->aggregate(& m_update); + result->aggregate(& m_delete); + } } }; @@ -419,10 +515,10 @@ struct PFS_table_stat { /** Statistics, per index. - Each index stat is in [0, MAX_KEY-1], - stats when using no index are in [MAX_KEY]. + Each index stat is in [0, MAX_INDEXES-1], + stats when using no index are in [MAX_INDEXES]. */ - PFS_table_io_stat m_index_stat[MAX_KEY + 1]; + PFS_table_io_stat m_index_stat[MAX_INDEXES + 1]; /** Statistics, per lock type. @@ -433,7 +529,7 @@ struct PFS_table_stat inline void reset_io(void) { PFS_table_io_stat *stat= & m_index_stat[0]; - PFS_table_io_stat *stat_last= & m_index_stat[MAX_KEY + 1]; + PFS_table_io_stat *stat_last= & m_index_stat[MAX_INDEXES + 1]; for ( ; stat < stat_last ; stat++) stat->reset(); } @@ -466,13 +562,25 @@ struct PFS_table_stat memcpy(this, & g_reset_template, sizeof(*this)); } - inline void aggregate_io(const PFS_table_stat *stat) + inline void aggregate_io(const PFS_table_stat *stat, uint key_count) { - PFS_table_io_stat *to_stat= & m_index_stat[0]; - PFS_table_io_stat *to_stat_last= & m_index_stat[MAX_KEY + 1]; - const PFS_table_io_stat *from_stat= & stat->m_index_stat[0]; + PFS_table_io_stat *to_stat; + PFS_table_io_stat *to_stat_last; + const PFS_table_io_stat *from_stat; + + DBUG_ASSERT(key_count <= MAX_INDEXES); + + /* Aggregate stats for each index, if any */ + to_stat= & m_index_stat[0]; + to_stat_last= to_stat + key_count; + from_stat= & stat->m_index_stat[0]; for ( ; to_stat < to_stat_last ; from_stat++, to_stat++) to_stat->aggregate(from_stat); + + /* Aggregate stats for the table */ + to_stat= & m_index_stat[MAX_INDEXES]; + from_stat= & stat->m_index_stat[MAX_INDEXES]; + to_stat->aggregate(from_stat); } inline void aggregate_lock(const PFS_table_stat *stat) @@ -480,18 +588,27 @@ struct PFS_table_stat m_lock_stat.aggregate(& stat->m_lock_stat); } - inline void aggregate(const PFS_table_stat *stat) + inline void aggregate(const PFS_table_stat *stat, uint key_count) { - aggregate_io(stat); + aggregate_io(stat, key_count); aggregate_lock(stat); } - inline void sum_io(PFS_single_stat *result) + inline void sum_io(PFS_single_stat *result, uint key_count) { - PFS_table_io_stat *stat= & m_index_stat[0]; - PFS_table_io_stat *stat_last= & m_index_stat[MAX_KEY + 1]; + PFS_table_io_stat *stat; + PFS_table_io_stat *stat_last; + + DBUG_ASSERT(key_count <= MAX_INDEXES); + + /* Sum stats for each index, if any */ + stat= & m_index_stat[0]; + stat_last= stat + key_count; for ( ; stat < stat_last ; stat++) stat->sum(result); + + /* Sum stats for the table */ + m_index_stat[MAX_INDEXES].sum(result); } inline void sum_lock(PFS_single_stat *result) @@ -499,9 +616,9 @@ struct PFS_table_stat m_lock_stat.sum(result); } - inline void sum(PFS_single_stat *result) + inline void sum(PFS_single_stat *result, uint key_count) { - sum_io(result); + sum_io(result, key_count); sum_lock(result); } diff --git a/storage/perfschema/pfs_timer.cc b/storage/perfschema/pfs_timer.cc index 3d8d2e07ce5..8c3553db2b2 100644 --- a/storage/perfschema/pfs_timer.cc +++ b/storage/perfschema/pfs_timer.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 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 @@ -117,6 +117,75 @@ void init_timers(void) to_pico_data[TIMER_NAME_TICK].m_v0= tick_v0; to_pico_data[TIMER_NAME_TICK].m_factor= tick_to_pico; + + /* + Depending on the platform and build options, + some timers may not be available. + Pick best replacements. + */ + + /* + For STAGE and STATEMENT, a timer with a fixed frequency is better. + The prefered timer is nanosecond, or lower resolutions. + */ + + if (nanosec_to_pico != 0) + { + /* Normal case. */ + stage_timer= TIMER_NAME_NANOSEC; + statement_timer= TIMER_NAME_NANOSEC; + } + else if (microsec_to_pico != 0) + { + /* Windows. */ + stage_timer= TIMER_NAME_MICROSEC; + statement_timer= TIMER_NAME_MICROSEC; + } + else if (millisec_to_pico != 0) + { + /* Robustness, no known cases. */ + stage_timer= TIMER_NAME_MILLISEC; + statement_timer= TIMER_NAME_MILLISEC; + } + else if (tick_to_pico != 0) + { + /* Robustness, no known cases. */ + stage_timer= TIMER_NAME_TICK; + statement_timer= TIMER_NAME_TICK; + } + else + { + /* Robustness, no known cases. */ + stage_timer= TIMER_NAME_CYCLE; + statement_timer= TIMER_NAME_CYCLE; + } + + /* + For IDLE, a timer with a fixed frequency is critical, + as the CPU clock may slow down a lot if the server is completely idle. + The prefered timer is microsecond, or lower resolutions. + */ + + if (microsec_to_pico != 0) + { + /* Normal case. */ + idle_timer= TIMER_NAME_MICROSEC; + } + else if (millisec_to_pico != 0) + { + /* Robustness, no known cases. */ + idle_timer= TIMER_NAME_MILLISEC; + } + else if (tick_to_pico != 0) + { + /* Robustness, no known cases. */ + idle_timer= TIMER_NAME_TICK; + } + else + { + /* Robustness, no known cases. */ + idle_timer= TIMER_NAME_CYCLE; + } } ulonglong get_timer_raw_value(enum_timer_name timer_name) diff --git a/storage/perfschema/pfs_user.cc b/storage/perfschema/pfs_user.cc index d7794a131a1..60d6a2e99f6 100644 --- a/storage/perfschema/pfs_user.cc +++ b/storage/perfschema/pfs_user.cc @@ -42,7 +42,7 @@ static PFS_single_stat *user_instr_class_waits_array= NULL; static PFS_stage_stat *user_instr_class_stages_array= NULL; static PFS_statement_stat *user_instr_class_statements_array= NULL; -static LF_HASH user_hash; +LF_HASH user_hash; static bool user_hash_inited= false; /** @@ -146,10 +146,11 @@ C_MODE_END */ int init_user_hash(void) { - if (! user_hash_inited) + if ((! user_hash_inited) && (user_max > 0)) { lf_hash_init(&user_hash, sizeof(PFS_user*), LF_HASH_UNIQUE, 0, 0, user_hash_get_key, &my_charset_bin); + /* user_hash.size= user_max; */ user_hash_inited= true; } return 0; diff --git a/storage/perfschema/pfs_user.h b/storage/perfschema/pfs_user.h index 0f937c6c927..dda7e221ca8 100644 --- a/storage/perfschema/pfs_user.h +++ b/storage/perfschema/pfs_user.h @@ -44,7 +44,7 @@ struct PFS_user_key uint m_key_length; }; -struct PFS_user : public PFS_connection_slice +struct PFS_ALIGNED PFS_user : public PFS_connection_slice { public: inline void init_refcount(void) @@ -108,6 +108,8 @@ extern ulong user_lost; extern PFS_user *user_array; +extern LF_HASH user_hash; + /** @} */ #endif diff --git a/storage/perfschema/pfs_visitor.cc b/storage/perfschema/pfs_visitor.cc index fe2b16a2f76..616bc27900a 100644 --- a/storage/perfschema/pfs_visitor.cc +++ b/storage/perfschema/pfs_visitor.cc @@ -666,7 +666,7 @@ void PFS_connection_wait_visitor::visit_global() it is more efficient. */ DBUG_ASSERT(m_index == global_idle_class.m_event_name_index); - m_stat.aggregate(& global_instr_class_waits_array[m_index]); + m_stat.aggregate(& global_idle_stat); } void PFS_connection_wait_visitor::visit_host(PFS_host *pfs) @@ -883,54 +883,44 @@ PFS_instance_wait_visitor::PFS_instance_wait_visitor() PFS_instance_wait_visitor::~PFS_instance_wait_visitor() {} -void PFS_instance_wait_visitor::visit_mutex_class(PFS_mutex_class *pfs) +void PFS_instance_wait_visitor::visit_mutex_class(PFS_mutex_class *pfs) { - uint index= pfs->m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); + m_stat.aggregate(&pfs->m_mutex_stat.m_wait_stat); } -void PFS_instance_wait_visitor::visit_rwlock_class(PFS_rwlock_class *pfs) +void PFS_instance_wait_visitor::visit_rwlock_class(PFS_rwlock_class *pfs) { - uint index= pfs->m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); + m_stat.aggregate(&pfs->m_rwlock_stat.m_wait_stat); } -void PFS_instance_wait_visitor::visit_cond_class(PFS_cond_class *pfs) +void PFS_instance_wait_visitor::visit_cond_class(PFS_cond_class *pfs) { - uint index= pfs->m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); + m_stat.aggregate(&pfs->m_cond_stat.m_wait_stat); } -void PFS_instance_wait_visitor::visit_file_class(PFS_file_class *pfs) +void PFS_instance_wait_visitor::visit_file_class(PFS_file_class *pfs) { - uint index= pfs->m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); + pfs->m_file_stat.m_io_stat.sum_waits(&m_stat); } -void PFS_instance_wait_visitor::visit_socket_class(PFS_socket_class *pfs) +void PFS_instance_wait_visitor::visit_socket_class(PFS_socket_class *pfs) { - /* Collect global wait stats */ - uint index= pfs->m_event_name_index; - m_stat.aggregate(&global_instr_class_waits_array[index]); - - /* If deferred, then pull wait stats directly from the socket class. */ - if (pfs->is_deferred()) - pfs->m_socket_stat.m_io_stat.sum_waits(&m_stat); + pfs->m_socket_stat.m_io_stat.sum_waits(&m_stat); } -void PFS_instance_wait_visitor::visit_mutex(PFS_mutex *pfs) +void PFS_instance_wait_visitor::visit_mutex(PFS_mutex *pfs) { - m_stat.aggregate(& pfs->m_wait_stat); + m_stat.aggregate(& pfs->m_mutex_stat.m_wait_stat); } -void PFS_instance_wait_visitor::visit_rwlock(PFS_rwlock *pfs) +void PFS_instance_wait_visitor::visit_rwlock(PFS_rwlock *pfs) { - m_stat.aggregate(& pfs->m_wait_stat); + m_stat.aggregate(& pfs->m_rwlock_stat.m_wait_stat); } -void PFS_instance_wait_visitor::visit_cond(PFS_cond *pfs) +void PFS_instance_wait_visitor::visit_cond(PFS_cond *pfs) { - m_stat.aggregate(& pfs->m_wait_stat); + m_stat.aggregate(& pfs->m_cond_stat.m_wait_stat); } void PFS_instance_wait_visitor::visit_file(PFS_file *pfs) @@ -959,23 +949,24 @@ PFS_object_wait_visitor::~PFS_object_wait_visitor() void PFS_object_wait_visitor::visit_global() { - uint index; - - index= global_table_io_class.m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); - - index= global_table_lock_class.m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); + global_table_io_stat.sum(& m_stat); + global_table_lock_stat.sum(& m_stat); } void PFS_object_wait_visitor::visit_table_share(PFS_table_share *pfs) { - pfs->m_table_stat.sum(& m_stat); + uint safe_key_count= sanitize_index_count(pfs->m_key_count); + pfs->m_table_stat.sum(& m_stat, safe_key_count); } void PFS_object_wait_visitor::visit_table(PFS_table *pfs) { - pfs->m_table_stat.sum(& m_stat); + PFS_table_share *table_share= sanitize_table_share(pfs->m_share); + if (table_share != NULL) + { + uint safe_key_count= sanitize_index_count(table_share->m_key_count); + pfs->m_table_stat.sum(& m_stat, safe_key_count); + } } PFS_table_io_wait_visitor::PFS_table_io_wait_visitor() @@ -986,21 +977,21 @@ PFS_table_io_wait_visitor::~PFS_table_io_wait_visitor() void PFS_table_io_wait_visitor::visit_global() { - uint index= global_table_io_class.m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); + global_table_io_stat.sum(& m_stat); } void PFS_table_io_wait_visitor::visit_table_share(PFS_table_share *pfs) { PFS_table_io_stat io_stat; + uint safe_key_count= sanitize_index_count(pfs->m_key_count); uint index; /* Aggregate index stats */ - for (index= 0; index < pfs->m_key_count; index++) + for (index= 0; index < safe_key_count; index++) io_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]); /* Aggregate global stats */ - io_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]); + io_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_INDEXES]); io_stat.sum(& m_stat); } @@ -1012,14 +1003,15 @@ void PFS_table_io_wait_visitor::visit_table(PFS_table *pfs) if (likely(safe_share != NULL)) { PFS_table_io_stat io_stat; + uint safe_key_count= sanitize_index_count(safe_share->m_key_count); uint index; /* Aggregate index stats */ - for (index= 0; index < safe_share->m_key_count; index++) + for (index= 0; index < safe_key_count; index++) io_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]); /* Aggregate global stats */ - io_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]); + io_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_INDEXES]); io_stat.sum(& m_stat); } @@ -1035,14 +1027,15 @@ PFS_table_io_stat_visitor::~PFS_table_io_stat_visitor() void PFS_table_io_stat_visitor::visit_table_share(PFS_table_share *pfs) { + uint safe_key_count= sanitize_index_count(pfs->m_key_count); uint index; /* Aggregate index stats */ - for (index= 0; index < pfs->m_key_count; index++) + for (index= 0; index < safe_key_count; index++) m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]); /* Aggregate global stats */ - m_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]); + m_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_INDEXES]); } void PFS_table_io_stat_visitor::visit_table(PFS_table *pfs) @@ -1051,14 +1044,15 @@ void PFS_table_io_stat_visitor::visit_table(PFS_table *pfs) if (likely(safe_share != NULL)) { + uint safe_key_count= sanitize_index_count(safe_share->m_key_count); uint index; /* Aggregate index stats */ - for (index= 0; index < safe_share->m_key_count; index++) + for (index= 0; index < safe_key_count; index++) m_stat.aggregate(& pfs->m_table_stat.m_index_stat[index]); /* Aggregate global stats */ - m_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_KEY]); + m_stat.aggregate(& pfs->m_table_stat.m_index_stat[MAX_INDEXES]); } } @@ -1090,8 +1084,7 @@ PFS_table_lock_wait_visitor::~PFS_table_lock_wait_visitor() void PFS_table_lock_wait_visitor::visit_global() { - uint index= global_table_lock_class.m_event_name_index; - m_stat.aggregate(& global_instr_class_waits_array[index]); + global_table_lock_stat.sum(& m_stat); } void PFS_table_lock_wait_visitor::visit_table_share(PFS_table_share *pfs) diff --git a/storage/perfschema/table_esgs_by_thread_by_event_name.cc b/storage/perfschema/table_esgs_by_thread_by_event_name.cc index 2a69ec24277..eeef6c3fbb2 100644 --- a/storage/perfschema/table_esgs_by_thread_by_event_name.cc +++ b/storage/perfschema/table_esgs_by_thread_by_event_name.cc @@ -33,7 +33,7 @@ static const TABLE_FIELD_TYPE field_types[]= { { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -212,7 +212,7 @@ int table_esgs_by_thread_by_event_name switch(f->field_index) { case 0: /* THREAD_ID */ - set_field_ulong(f, m_row.m_thread_internal_id); + set_field_ulonglong(f, m_row.m_thread_internal_id); break; case 1: /* NAME */ m_row.m_event_name.set_field(f); diff --git a/storage/perfschema/table_esgs_by_thread_by_event_name.h b/storage/perfschema/table_esgs_by_thread_by_event_name.h index 049c8997396..5295a9eacdf 100644 --- a/storage/perfschema/table_esgs_by_thread_by_event_name.h +++ b/storage/perfschema/table_esgs_by_thread_by_event_name.h @@ -39,7 +39,7 @@ struct row_esgs_by_thread_by_event_name { /** Column THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Column EVENT_NAME. */ PFS_event_name_row m_event_name; /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */ diff --git a/storage/perfschema/table_esgs_global_by_event_name.cc b/storage/perfschema/table_esgs_global_by_event_name.cc index 2ac22fb1551..276ac8d7704 100644 --- a/storage/perfschema/table_esgs_global_by_event_name.cc +++ b/storage/perfschema/table_esgs_global_by_event_name.cc @@ -95,6 +95,9 @@ int table_esgs_global_by_event_name::delete_all_rows(void) { reset_events_stages_by_thread(); + reset_events_stages_by_account(); + reset_events_stages_by_user(); + reset_events_stages_by_host(); reset_events_stages_global(); return 0; } diff --git a/storage/perfschema/table_esms_by_digest.cc b/storage/perfschema/table_esms_by_digest.cc index dac8d3b01dc..d0250c14e5d 100644 --- a/storage/perfschema/table_esms_by_digest.cc +++ b/storage/perfschema/table_esms_by_digest.cc @@ -36,6 +36,11 @@ THR_LOCK table_esms_by_digest::m_table_lock; static const TABLE_FIELD_TYPE field_types[]= { { + { C_STRING_WITH_LEN("SCHEMA_NAME") }, + { C_STRING_WITH_LEN("varchar(64)") }, + { NULL, 0} + }, + { { C_STRING_WITH_LEN("DIGEST") }, { C_STRING_WITH_LEN("varchar(32)") }, { NULL, 0} @@ -45,7 +50,7 @@ static const TABLE_FIELD_TYPE field_types[]= { C_STRING_WITH_LEN("longtext") }, { NULL, 0} }, - { + { { C_STRING_WITH_LEN("COUNT_STAR") }, { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} @@ -170,7 +175,7 @@ static const TABLE_FIELD_TYPE field_types[]= { C_STRING_WITH_LEN("timestamp") }, { NULL, 0} }, - { + { { C_STRING_WITH_LEN("LAST_SEEN") }, { C_STRING_WITH_LEN("timestamp") }, { NULL, 0} @@ -179,7 +184,7 @@ static const TABLE_FIELD_TYPE field_types[]= TABLE_FIELD_DEF table_esms_by_digest::m_field_def= -{ 28, field_types }; +{ 29, field_types }; PFS_engine_table_share table_esms_by_digest::m_share= @@ -303,18 +308,19 @@ int table_esms_by_digest { switch(f->field_index) { - case 0: /* DIGEST */ - case 1: /* DIGEST_TEXT */ + case 0: /* SCHEMA_NAME */ + case 1: /* DIGEST */ + case 2: /* DIGEST_TEXT */ m_row.m_digest.set_field(f->field_index, f); break; - case 26: /* FIRST_SEEN */ + case 27: /* FIRST_SEEN */ set_field_timestamp(f, m_row.m_first_seen); break; - case 27: /* LAST_SEEN */ + case 28: /* LAST_SEEN */ set_field_timestamp(f, m_row.m_last_seen); break; - default: /* 1, ... COUNT/SUM/MIN/AVG/MAX */ - m_row.m_stat.set_field(f->field_index - 2, f); + default: /* 3, ... COUNT/SUM/MIN/AVG/MAX */ + m_row.m_stat.set_field(f->field_index - 3, f); break; } } diff --git a/storage/perfschema/table_esms_by_thread_by_event_name.cc b/storage/perfschema/table_esms_by_thread_by_event_name.cc index 5a7faca1b79..fccdf5dea60 100644 --- a/storage/perfschema/table_esms_by_thread_by_event_name.cc +++ b/storage/perfschema/table_esms_by_thread_by_event_name.cc @@ -33,7 +33,7 @@ static const TABLE_FIELD_TYPE field_types[]= { { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -308,7 +308,7 @@ int table_esms_by_thread_by_event_name switch(f->field_index) { case 0: /* THREAD_ID */ - set_field_ulong(f, m_row.m_thread_internal_id); + set_field_ulonglong(f, m_row.m_thread_internal_id); break; case 1: /* EVENT_NAME */ m_row.m_event_name.set_field(f); diff --git a/storage/perfschema/table_esms_by_thread_by_event_name.h b/storage/perfschema/table_esms_by_thread_by_event_name.h index 2f36606a5e1..9fb9f7c58dc 100644 --- a/storage/perfschema/table_esms_by_thread_by_event_name.h +++ b/storage/perfschema/table_esms_by_thread_by_event_name.h @@ -39,7 +39,7 @@ struct row_esms_by_thread_by_event_name { /** Column THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Column EVENT_NAME. */ PFS_event_name_row m_event_name; /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */ diff --git a/storage/perfschema/table_esms_global_by_event_name.cc b/storage/perfschema/table_esms_global_by_event_name.cc index 22c87f09137..efcb5b6fa7c 100644 --- a/storage/perfschema/table_esms_global_by_event_name.cc +++ b/storage/perfschema/table_esms_global_by_event_name.cc @@ -190,6 +190,9 @@ int table_esms_global_by_event_name::delete_all_rows(void) { reset_events_statements_by_thread(); + reset_events_statements_by_account(); + reset_events_statements_by_user(); + reset_events_statements_by_host(); reset_events_statements_global(); return 0; } diff --git a/storage/perfschema/table_events_stages.cc b/storage/perfschema/table_events_stages.cc index e438249fbd3..854e1be15cd 100644 --- a/storage/perfschema/table_events_stages.cc +++ b/storage/perfschema/table_events_stages.cc @@ -32,7 +32,7 @@ static const TABLE_FIELD_TYPE field_types[]= { { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -207,7 +207,7 @@ int table_events_stages_common::read_row_values(TABLE *table, switch(f->field_index) { case 0: /* THREAD_ID */ - set_field_ulong(f, m_row.m_thread_internal_id); + set_field_ulonglong(f, m_row.m_thread_internal_id); break; case 1: /* EVENT_ID */ set_field_ulonglong(f, m_row.m_event_id); diff --git a/storage/perfschema/table_events_stages.h b/storage/perfschema/table_events_stages.h index 6bc712c15a5..09c555c80fd 100644 --- a/storage/perfschema/table_events_stages.h +++ b/storage/perfschema/table_events_stages.h @@ -36,7 +36,7 @@ struct PFS_thread; struct row_events_stages { /** Column THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Column EVENT_ID. */ ulonglong m_event_id; /** Column END_EVENT_ID. */ diff --git a/storage/perfschema/table_events_statements.cc b/storage/perfschema/table_events_statements.cc index d453b14470f..fb2b4b242d4 100644 --- a/storage/perfschema/table_events_statements.cc +++ b/storage/perfschema/table_events_statements.cc @@ -35,7 +35,7 @@ static const TABLE_FIELD_TYPE field_types[]= { { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -372,7 +372,7 @@ void table_events_statements_common::make_row(PFS_events_statements *statement) PSI_digest_storage *digest= & statement->m_digest_storage; if (digest->m_byte_count > 0) { - PFS_digest_hash md5; + PFS_digest_key md5; compute_md5_hash((char *) md5.m_md5, (char *) digest->m_token_array, digest->m_byte_count); @@ -420,7 +420,7 @@ int table_events_statements_common::read_row_values(TABLE *table, switch(f->field_index) { case 0: /* THREAD_ID */ - set_field_ulong(f, m_row.m_thread_internal_id); + set_field_ulonglong(f, m_row.m_thread_internal_id); break; case 1: /* EVENT_ID */ set_field_ulonglong(f, m_row.m_event_id); diff --git a/storage/perfschema/table_events_statements.h b/storage/perfschema/table_events_statements.h index acd82de4fcf..dcc6611f555 100644 --- a/storage/perfschema/table_events_statements.h +++ b/storage/perfschema/table_events_statements.h @@ -37,7 +37,7 @@ struct PFS_thread; struct row_events_statements { /** Column THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Column EVENT_ID. */ ulonglong m_event_id; /** Column END_EVENT_ID. */ diff --git a/storage/perfschema/table_events_waits.cc b/storage/perfschema/table_events_waits.cc index 245abc34695..8fb7ca91c44 100644 --- a/storage/perfschema/table_events_waits.cc +++ b/storage/perfschema/table_events_waits.cc @@ -34,7 +34,7 @@ static const TABLE_FIELD_TYPE field_types[]= { { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -239,7 +239,8 @@ int table_events_waits_common::make_table_object_columns(volatile PFS_events_wai /* INDEX NAME */ safe_index= wait->m_index; - if (safe_index < MAX_KEY && safe_index < safe_table_share->m_key_count) + uint safe_key_count= sanitize_index_count(safe_table_share->m_key_count); + if (safe_index < safe_key_count) { PFS_table_key *key= & safe_table_share->m_keys[safe_index]; m_row.m_index_name_length= key->m_name_length; @@ -602,7 +603,7 @@ int table_events_waits_common::read_row_values(TABLE *table, switch(f->field_index) { case 0: /* THREAD_ID */ - set_field_ulong(f, m_row.m_thread_internal_id); + set_field_ulonglong(f, m_row.m_thread_internal_id); break; case 1: /* EVENT_ID */ set_field_ulonglong(f, m_row.m_event_id); diff --git a/storage/perfschema/table_events_waits.h b/storage/perfschema/table_events_waits.h index 72065c765ca..065bf95e5a6 100644 --- a/storage/perfschema/table_events_waits.h +++ b/storage/perfschema/table_events_waits.h @@ -36,7 +36,7 @@ struct PFS_thread; struct row_events_waits { /** Column THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Column EVENT_ID. */ ulonglong m_event_id; /** Column END_EVENT_ID. */ diff --git a/storage/perfschema/table_events_waits_summary.cc b/storage/perfschema/table_events_waits_summary.cc index 2a144a07344..f437e83f3ff 100644 --- a/storage/perfschema/table_events_waits_summary.cc +++ b/storage/perfschema/table_events_waits_summary.cc @@ -139,7 +139,7 @@ void table_events_waits_summary_by_instance::make_mutex_row(PFS_mutex *pfs) if (unlikely(safe_class == NULL)) return; - make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_wait_stat); + make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_mutex_stat.m_wait_stat); } /** @@ -153,7 +153,7 @@ void table_events_waits_summary_by_instance::make_rwlock_row(PFS_rwlock *pfs) if (unlikely(safe_class == NULL)) return; - make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_wait_stat); + make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_rwlock_stat.m_wait_stat); } /** @@ -167,7 +167,7 @@ void table_events_waits_summary_by_instance::make_cond_row(PFS_cond *pfs) if (unlikely(safe_class == NULL)) return; - make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_wait_stat); + make_instr_row(pfs, safe_class, pfs->m_identity, &pfs->m_cond_stat.m_wait_stat); } /** @@ -181,11 +181,13 @@ void table_events_waits_summary_by_instance::make_file_row(PFS_file *pfs) if (unlikely(safe_class == NULL)) return; + PFS_single_stat sum; + pfs->m_file_stat.m_io_stat.sum_waits(& sum); /* Files don't have a in memory structure associated to it, so we use the address of the PFS_file buffer as object_instance_begin */ - make_instr_row(pfs, safe_class, pfs, &pfs->m_wait_stat); + make_instr_row(pfs, safe_class, pfs, & sum); } /** diff --git a/storage/perfschema/table_ews_by_thread_by_event_name.cc b/storage/perfschema/table_ews_by_thread_by_event_name.cc index 25e3cf395c4..4db97b1c98c 100644 --- a/storage/perfschema/table_ews_by_thread_by_event_name.cc +++ b/storage/perfschema/table_ews_by_thread_by_event_name.cc @@ -33,7 +33,7 @@ static const TABLE_FIELD_TYPE field_types[]= { { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -282,7 +282,7 @@ int table_ews_by_thread_by_event_name switch(f->field_index) { case 0: /* THREAD_ID */ - set_field_ulong(f, m_row.m_thread_internal_id); + set_field_ulonglong(f, m_row.m_thread_internal_id); break; case 1: /* EVENT_NAME */ m_row.m_event_name.set_field(f); diff --git a/storage/perfschema/table_ews_by_thread_by_event_name.h b/storage/perfschema/table_ews_by_thread_by_event_name.h index b0710bb8a57..989356be646 100644 --- a/storage/perfschema/table_ews_by_thread_by_event_name.h +++ b/storage/perfschema/table_ews_by_thread_by_event_name.h @@ -39,7 +39,7 @@ struct row_ews_by_thread_by_event_name { /** Column THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Column EVENT_NAME. */ PFS_event_name_row m_event_name; /** Columns COUNT_STAR, SUM/MIN/AVG/MAX TIMER_WAIT. */ diff --git a/storage/perfschema/table_ews_global_by_event_name.cc b/storage/perfschema/table_ews_global_by_event_name.cc index 3f8997b8c77..bc5c3780ecf 100644 --- a/storage/perfschema/table_ews_global_by_event_name.cc +++ b/storage/perfschema/table_ews_global_by_event_name.cc @@ -97,7 +97,7 @@ table_ews_global_by_event_name::delete_all_rows(void) reset_events_waits_by_instance(); reset_table_waits_by_table_handle(); reset_table_waits_by_table(); - reset_events_waits_global(); + reset_events_waits_by_class(); return 0; } @@ -121,9 +121,6 @@ int table_ews_global_by_event_name::rnd_next(void) PFS_socket_class *socket_class; PFS_instr_class *instr_class; - if (global_instr_class_waits_array == NULL) - return HA_ERR_END_OF_FILE; - for (m_pos.set_at(&m_next_pos); m_pos.has_more_view(); m_pos.next_view()) @@ -218,9 +215,6 @@ table_ews_global_by_event_name::rnd_pos(const void *pos) set_position(pos); - if (global_instr_class_waits_array == NULL) - return HA_ERR_END_OF_FILE; - switch (m_pos.m_index_1) { case pos_ews_global_by_event_name::VIEW_MUTEX: diff --git a/storage/perfschema/table_helper.cc b/storage/perfschema/table_helper.cc index d3954179539..9f803434ab6 100644 --- a/storage/perfschema/table_helper.cc +++ b/storage/perfschema/table_helper.cc @@ -110,26 +110,30 @@ int PFS_digest_row::make_row(PFS_statements_digest_stat* pfs) */ if (pfs->m_digest_storage.m_byte_count != 0) { + m_schema_name_length= pfs->m_digest_key.m_schema_name_length; + if (m_schema_name_length > 0) + memcpy(m_schema_name, pfs->m_digest_key.m_schema_name, m_schema_name_length); /* Calculate digest from MD5 HASH collected to be shown as DIGEST in this row. */ - MD5_HASH_TO_STRING(pfs->m_digest_hash.m_md5, m_digest); + MD5_HASH_TO_STRING(pfs->m_digest_key.m_md5, m_digest); m_digest_length= MD5_HASH_TO_STRING_LENGTH; - /* - Caclulate digest_text information from the token array collected + /* + Calculate digest_text information from the token array collected to be shown as DIGEST_TEXT column. - */ + */ get_digest_text(m_digest_text, &pfs->m_digest_storage); m_digest_text_length= strlen(m_digest_text); } else { + m_schema_name_length= 0; m_digest_length= 0; m_digest_text_length= 0; } - + return 0; } @@ -137,14 +141,21 @@ void PFS_digest_row::set_field(uint index, Field *f) { switch (index) { - case 0: /* DIGEST */ + case 0: /* SCHEMA_NAME */ + if (m_schema_name_length > 0) + PFS_engine_table::set_field_varchar_utf8(f, m_schema_name, + m_schema_name_length); + else + f->set_null(); + break; + case 1: /* DIGEST */ if (m_digest_length > 0) PFS_engine_table::set_field_varchar_utf8(f, m_digest, m_digest_length); else f->set_null(); break; - case 1: /* DIGEST_TEXT */ + case 2: /* DIGEST_TEXT */ if (m_digest_text_length > 0) PFS_engine_table::set_field_longtext_utf8(f, m_digest_text, m_digest_text_length); @@ -199,7 +210,7 @@ int PFS_index_row::make_row(PFS_table_share *pfs, uint table_index) if (m_object_row.make_row(pfs)) return 1; - if (table_index < MAX_KEY) + if (table_index < MAX_INDEXES) { PFS_table_key *key= &pfs->m_keys[table_index]; m_index_name_length= key->m_name_length; diff --git a/storage/perfschema/table_helper.h b/storage/perfschema/table_helper.h index 798ff16f4e5..769122570eb 100644 --- a/storage/perfschema/table_helper.h +++ b/storage/perfschema/table_helper.h @@ -127,6 +127,10 @@ struct PFS_account_row /** Row fragment for columns DIGEST, DIGEST_TEXT. */ struct PFS_digest_row { + /** Column SCHEMA_NAME. */ + char m_schema_name[NAME_LEN]; + /** Length in bytes of @c m_schema_name. */ + uint m_schema_name_length; /** Column DIGEST. */ char m_digest[COL_DIGEST_SIZE]; /** Length in bytes of @c m_digest. */ diff --git a/storage/perfschema/table_host_cache.cc b/storage/perfschema/table_host_cache.cc index d243204ddcd..02c7f72140a 100644 --- a/storage/perfschema/table_host_cache.cc +++ b/storage/perfschema/table_host_cache.cc @@ -23,8 +23,6 @@ #include "table_host_cache.h" #include "hostname.h" -#ifdef NOT_YET_PORTED - THR_LOCK table_host_cache::m_table_lock; static const TABLE_FIELD_TYPE field_types[]= @@ -266,9 +264,6 @@ void table_host_cache::materialize(THD *thd) index++; row++; current= current->next(); - /* Host cache is a circular linked list. */ - if (current == first) - break; } m_all_rows= rows; @@ -481,4 +476,3 @@ int table_host_cache::read_row_values(TABLE *table, return 0; } -#endif /* NOT_YET_PORTED */ diff --git a/storage/perfschema/table_os_global_by_type.cc b/storage/perfschema/table_os_global_by_type.cc index 82d176cd5b2..70d9d6819ac 100644 --- a/storage/perfschema/table_os_global_by_type.cc +++ b/storage/perfschema/table_os_global_by_type.cc @@ -174,6 +174,7 @@ void table_os_global_by_type::make_row(PFS_table_share *share) { pfs_lock lock; PFS_single_stat cumulated_stat; + uint safe_key_count; m_row_exists= false; @@ -184,7 +185,11 @@ void table_os_global_by_type::make_row(PFS_table_share *share) m_row.m_schema_name_length= share->m_schema_name_length; memcpy(m_row.m_object_name, share->m_table_name, share->m_table_name_length); m_row.m_object_name_length= share->m_table_name_length; - share->m_table_stat.sum(& cumulated_stat); + + /* This is a dirty read, some thread can write data while we are reading it */ + safe_key_count= sanitize_index_count(share->m_key_count); + + share->m_table_stat.sum(& cumulated_stat, safe_key_count); if (! share->m_lock.end_optimistic_lock(&lock)) return; @@ -204,7 +209,7 @@ void table_os_global_by_type::make_row(PFS_table_share *share) If the opened table handle is for this table share, aggregate the table handle statistics. */ - table->m_table_stat.sum(& cumulated_stat); + table->m_table_stat.sum(& cumulated_stat, safe_key_count); } } } diff --git a/storage/perfschema/table_session_account_connect_attrs.cc b/storage/perfschema/table_session_account_connect_attrs.cc new file mode 100644 index 00000000000..4a3fcc22341 --- /dev/null +++ b/storage/perfschema/table_session_account_connect_attrs.cc @@ -0,0 +1,70 @@ +/* Copyright (c) 2008, 2011, 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#include "table_session_account_connect_attrs.h" + +THR_LOCK table_session_account_connect_attrs::m_table_lock; + +PFS_engine_table_share +table_session_account_connect_attrs::m_share= +{ + { C_STRING_WITH_LEN("session_account_connect_attrs") }, + &pfs_readonly_acl, + &table_session_account_connect_attrs::create, + NULL, /* write_row */ + NULL, /* delete_all_rows */ + NULL, /* get_row_count */ + 1000, /* records */ + sizeof(pos_connect_attr_by_thread_by_attr), /* ref length */ + &m_table_lock, + &m_field_def, + false /* checked */ +}; + +PFS_engine_table* table_session_account_connect_attrs::create() +{ + return new table_session_account_connect_attrs(); +} + +table_session_account_connect_attrs::table_session_account_connect_attrs() + : table_session_connect(&m_share) +{} + +bool +table_session_account_connect_attrs::thread_fits(PFS_thread *thread) +{ + PFS_thread *current_thread= PFS_thread::get_current_thread(); + /* The current thread may not have instrumentation attached. */ + if (current_thread == NULL) + return false; + + /* The thread we compare to, by definition, has some instrumentation. */ + DBUG_ASSERT(thread != NULL); + + uint username_length= current_thread->m_username_length; + uint hostname_length= current_thread->m_hostname_length; + + if ( (thread->m_username_length != username_length) + || (thread->m_hostname_length != hostname_length)) + return false; + + if (memcmp(thread->m_username, current_thread->m_username, username_length) != 0) + return false; + + if (memcmp(thread->m_hostname, current_thread->m_hostname, hostname_length) != 0) + return false; + + return true; +} diff --git a/storage/perfschema/table_session_account_connect_attrs.h b/storage/perfschema/table_session_account_connect_attrs.h new file mode 100644 index 00000000000..ba8893e7cad --- /dev/null +++ b/storage/perfschema/table_session_account_connect_attrs.h @@ -0,0 +1,50 @@ +/* Copyright (c) 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef TABLE_SESSION_ACCOUNT_CONNECT_ATTRS_H +#define TABLE_SESSION_ACCOUNT_CONNECT_ATTRS_H + +#include "table_session_connect.h" +/** + \addtogroup Performance_schema_tables + @{ +*/ + +/** Table PERFORMANCE_SCHEMA.SESSION_ACCOUNT_CONNECT_ATTRS. */ +class table_session_account_connect_attrs : public table_session_connect +{ +public: + /** Table share */ + static PFS_engine_table_share m_share; + /** Table builder */ + static PFS_engine_table* create(); + +protected: + table_session_account_connect_attrs(); + +public: + ~table_session_account_connect_attrs() + {} + +protected: + virtual bool thread_fits(PFS_thread *thread); + +private: + /** Table share lock. */ + static THR_LOCK m_table_lock; +}; + +/** @} */ +#endif diff --git a/storage/perfschema/table_session_connect.cc b/storage/perfschema/table_session_connect.cc new file mode 100644 index 00000000000..bd905b5756c --- /dev/null +++ b/storage/perfschema/table_session_connect.cc @@ -0,0 +1,268 @@ +/* Copyright (c) 2008, 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#include "table_session_connect.h" + +static const TABLE_FIELD_TYPE field_types[]= +{ + { + { C_STRING_WITH_LEN("PROCESSLIST_ID") }, + { C_STRING_WITH_LEN("int(11)") }, + { NULL, 0} + }, + { + { C_STRING_WITH_LEN("ATTR_NAME") }, + { C_STRING_WITH_LEN("varchar(32)") }, + { NULL, 0} + }, + { + { C_STRING_WITH_LEN("ATTR_VALUE") }, + { C_STRING_WITH_LEN("varchar(1024)") }, + { NULL, 0} + }, + { + { C_STRING_WITH_LEN("ORDINAL_POSITION") }, + { C_STRING_WITH_LEN("int(11)") }, + { NULL, 0} + } +}; + +TABLE_FIELD_DEF table_session_connect::m_field_def= +{ 4, field_types }; + +table_session_connect::table_session_connect(const PFS_engine_table_share *share) : + cursor_by_thread_connect_attr(share) +{} + +/** + Take a length encoded string + + @arg ptr inout the input string array + @arg dest where to store the result + @arg dest_size max size of @c dest + @arg copied_len the actual length of the data copied + @arg start_ptr pointer to the start of input + @arg input_length the length of the incoming data + @arg copy_data copy the data or just skip the input + @arg from_cs character set in which @c ptr is encoded + @arg nchars_max maximum number of characters to read + @return status + @retval true parsing failed + @retval false parsing succeeded +*/ +bool parse_length_encoded_string(const char **ptr, + char *dest, uint dest_size, + uint *copied_len, + const char *start_ptr, uint input_length, + bool copy_data, + const CHARSET_INFO *from_cs, + uint nchars_max) +{ + ulong copy_length, data_length; + const char *well_formed_error_pos= NULL, *cannot_convert_error_pos= NULL, + *from_end_pos= NULL; + + copy_length= data_length= net_field_length((uchar **) ptr); + + /* we don't tolerate NULL as a length */ + if (data_length == NULL_LENGTH) + return true; + + if (*ptr - start_ptr + data_length > input_length) + return true; + + copy_length= well_formed_copy_nchars(&my_charset_utf8_bin, dest, dest_size, + from_cs, *ptr, data_length, nchars_max, + &well_formed_error_pos, + &cannot_convert_error_pos, + &from_end_pos); + *copied_len= copy_length; + (*ptr)+= data_length; + + return false; +} + +/** + Take the nth attribute name/value pair + + Parse the attributes blob form the beginning, skipping the attributes + whose number is lower than the one we seek. + When we reach the attribute at an index we're looking for the values + are copied to the output parameters. + If parsing fails or no more attributes are found the function stops + and returns an error code. + + @arg connect_attrs pointer to the connect attributes blob + @arg connect_attrs_length length of @c connect_attrs + @arg connect_attrs_cs character set used to encode @c connect_attrs + @arg ordinal index of the attribute we need + @arg attr_name [out] buffer to receive the attribute name + @arg max_attr_name max size of @c attr_name in bytes + @arg attr_name_length [out] number of bytes written in @attr_name + @arg attr_value [out] buffer to receive the attribute name + @arg max_attr_value max size of @c attr_value in bytes + @arg attr_value_length [out] number of bytes written in @attr_value + @return status + @retval true requested attribute pair is found and copied + @retval false error. Either because of parsing or too few attributes. +*/ +bool read_nth_attr(const char *connect_attrs, + uint connect_attrs_length, + const CHARSET_INFO *connect_attrs_cs, + uint ordinal, + char *attr_name, uint max_attr_name, + uint *attr_name_length, + char *attr_value, uint max_attr_value, + uint *attr_value_length) +{ + uint idx; + const char *ptr; + + for (ptr= connect_attrs, idx= 0; + (uint)(ptr - connect_attrs) < connect_attrs_length && idx <= ordinal; + idx++) + { + uint copy_length; + /* do the copying only if we absolutely have to */ + bool fill_in_attr_name= idx == ordinal; + bool fill_in_attr_value= idx == ordinal; + + /* read the key */ + if (parse_length_encoded_string(&ptr, + attr_name, max_attr_name, ©_length, + connect_attrs, + connect_attrs_length, + fill_in_attr_name, + connect_attrs_cs, 32) || + !copy_length + ) + return false; + + if (idx == ordinal) + *attr_name_length= copy_length; + + /* read the value */ + if (parse_length_encoded_string(&ptr, + attr_value, max_attr_value, ©_length, + connect_attrs, + connect_attrs_length, + fill_in_attr_value, + connect_attrs_cs, 1024)) + return false; + + if (idx == ordinal) + *attr_value_length= copy_length; + + if (idx == ordinal) + return true; + } + + return false; +} + +void table_session_connect::make_row(PFS_thread *pfs, uint ordinal) +{ + pfs_lock lock; + PFS_thread_class *safe_class; + + m_row_exists= false; + + /* Protect this reader against thread termination */ + pfs->m_lock.begin_optimistic_lock(&lock); + safe_class= sanitize_thread_class(pfs->m_class); + if (unlikely(safe_class == NULL)) + return; + + /* Filtering threads must be done under the protection of the optimistic lock. */ + if (! thread_fits(pfs)) + return; + + /* populate the row */ + if (read_nth_attr(pfs->m_session_connect_attrs, + pfs->m_session_connect_attrs_length, + pfs->m_session_connect_attrs_cs, + ordinal, + m_row.m_attr_name, (uint) sizeof(m_row.m_attr_name), + &m_row.m_attr_name_length, + m_row.m_attr_value, (uint) sizeof(m_row.m_attr_value), + &m_row.m_attr_value_length)) + { + /* we don't expect internal threads to have connection attributes */ + DBUG_ASSERT(pfs->m_processlist_id != 0); + + m_row.m_ordinal_position= ordinal; + m_row.m_process_id= pfs->m_processlist_id; + } + else + return; + + if (pfs->m_lock.end_optimistic_lock(& lock)) + m_row_exists= true; +} + +int table_session_connect::read_row_values(TABLE *table, + unsigned char *buf, + Field **fields, + bool read_all) +{ + Field *f; + + if (unlikely(!m_row_exists)) + return HA_ERR_RECORD_DELETED; + + /* Set the null bits */ + DBUG_ASSERT(table->s->null_bytes == 1); + buf[0]= 0; + + for (; (f= *fields) ; fields++) + { + if (read_all || bitmap_is_set(table->read_set, f->field_index)) + { + switch(f->field_index) + { + case FO_PROCESS_ID: + if (m_row.m_process_id != 0) + set_field_ulong(f, m_row.m_process_id); + else + f->set_null(); + break; + case FO_ATTR_NAME: + set_field_varchar_utf8(f, m_row.m_attr_name, + m_row.m_attr_name_length); + break; + case FO_ATTR_VALUE: + if (m_row.m_attr_value_length) + set_field_varchar_utf8(f, m_row.m_attr_value, + m_row.m_attr_value_length); + else + f->set_null(); + break; + case FO_ORDINAL_POSITION: + set_field_ulong(f, m_row.m_ordinal_position); + break; + default: + DBUG_ASSERT(false); + } + } + } + return 0; +} + +bool +table_session_connect::thread_fits(PFS_thread *thread) +{ + return true; +} + diff --git a/storage/perfschema/table_session_connect.h b/storage/perfschema/table_session_connect.h new file mode 100644 index 00000000000..097623d2c80 --- /dev/null +++ b/storage/perfschema/table_session_connect.h @@ -0,0 +1,77 @@ +/* Copyright (c) 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef TABLE_SESSION_CONNECT_H +#define TABLE_SESSION_CONNECT_H + +#include "pfs_column_types.h" +#include "cursor_by_thread_connect_attr.h" +#include "table_helper.h" + +#define MAX_ATTR_NAME_CHARS 32 +#define MAX_ATTR_VALUE_CHARS 1024 +#define MAX_UTF8_BYTES 6 + +/** symbolic names for field offsets, keep in sync with field_types */ +enum field_offsets { + FO_PROCESS_ID, + FO_ATTR_NAME, + FO_ATTR_VALUE, + FO_ORDINAL_POSITION +}; + +/** + A row of PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS and + PERFORMANCE_SCHEMA.SESSION_ACCOUNT_CONNECT_ATTRS. +*/ +struct row_session_connect_attrs +{ + /** Column PROCESS_ID. */ + ulong m_process_id; + /** Column ATTR_NAME. In UTF-8 */ + char m_attr_name[MAX_ATTR_NAME_CHARS * MAX_UTF8_BYTES]; + /** Length in bytes of @c m_attr_name. */ + uint m_attr_name_length; + /** Column ATTR_VALUE. In UTF-8 */ + char m_attr_value[MAX_ATTR_VALUE_CHARS * MAX_UTF8_BYTES]; + /** Length in bytes of @c m_attr_name. */ + uint m_attr_value_length; + /** Column ORDINAL_POSITION. */ + ulong m_ordinal_position; +}; + +class table_session_connect : public cursor_by_thread_connect_attr +{ +protected: + table_session_connect(const PFS_engine_table_share *share); + +public: + ~table_session_connect() + {} + +protected: + virtual void make_row(PFS_thread *pfs, uint ordinal); + virtual bool thread_fits(PFS_thread *thread); + virtual int read_row_values(TABLE *table, unsigned char *buf, + Field **fields, bool read_all); +protected: + /** Fields definition. */ + static TABLE_FIELD_DEF m_field_def; + /** Current row. */ + row_session_connect_attrs m_row; +}; + +/** @} */ +#endif diff --git a/storage/perfschema/table_session_connect_attrs.cc b/storage/perfschema/table_session_connect_attrs.cc new file mode 100644 index 00000000000..9e1804b7294 --- /dev/null +++ b/storage/perfschema/table_session_connect_attrs.cc @@ -0,0 +1,43 @@ +/* Copyright (c) 2008, 2011, 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#include "table_session_connect_attrs.h" + +THR_LOCK table_session_connect_attrs::m_table_lock; + +PFS_engine_table_share +table_session_connect_attrs::m_share= +{ + { C_STRING_WITH_LEN("session_connect_attrs") }, + &pfs_readonly_acl, + &table_session_connect_attrs::create, + NULL, /* write_row */ + NULL, /* delete_all_rows */ + NULL, /* get_row_count */ + 1000, /* records */ + sizeof(pos_connect_attr_by_thread_by_attr), /* ref length */ + &m_table_lock, + &m_field_def, + false /* checked */ +}; + +PFS_engine_table* table_session_connect_attrs::create() +{ + return new table_session_connect_attrs(); +} + +table_session_connect_attrs::table_session_connect_attrs() + : table_session_connect(&m_share) +{} diff --git a/storage/perfschema/table_session_connect_attrs.h b/storage/perfschema/table_session_connect_attrs.h new file mode 100644 index 00000000000..b10b106ba0d --- /dev/null +++ b/storage/perfschema/table_session_connect_attrs.h @@ -0,0 +1,47 @@ +/* Copyright (c) 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#ifndef TABLE_SESSION_CONNECT_ATTRS_H +#define TABLE_SESSION_CONNECT_ATTRS_H + +#include "table_session_connect.h" +/** + \addtogroup Performance_schema_tables + @{ +*/ + +/** Table PERFORMANCE_SCHEMA.SESSION_CONNECT_ATTRS. */ +class table_session_connect_attrs : public table_session_connect +{ +public: + /** Table share */ + static PFS_engine_table_share m_share; + /** Table builder */ + static PFS_engine_table* create(); + +protected: + table_session_connect_attrs(); + +public: + ~table_session_connect_attrs() + {} + +private: + /** Table share lock. */ + static THR_LOCK m_table_lock; +}; + +/** @} */ +#endif diff --git a/storage/perfschema/table_setup_actors.cc b/storage/perfschema/table_setup_actors.cc index 15d3d9d22a8..91dbb942ead 100644 --- a/storage/perfschema/table_setup_actors.cc +++ b/storage/perfschema/table_setup_actors.cc @@ -105,6 +105,9 @@ int table_setup_actors::write_row(TABLE *table, unsigned char *buf, } } + if (user->length() == 0 || host->length() == 0 || role->length() == 0) + return HA_ERR_WRONG_COMMAND; + return insert_setup_actor(user, host, role); } @@ -264,39 +267,13 @@ int table_setup_actors::delete_row_values(TABLE *table, const unsigned char *buf, Field **fields) { - Field *f; - String user_data("", 0, &my_charset_utf8_bin); - String host_data("", 0, &my_charset_utf8_bin); - String role_data("", 0, &my_charset_utf8_bin); - String *user= NULL; - String *host= NULL; - String *role= NULL; - - for (; (f= *fields) ; fields++) - { - if (bitmap_is_set(table->read_set, f->field_index)) - { - switch(f->field_index) - { - case 0: /* HOST */ - host= get_field_char_utf8(f, &host_data); - break; - case 1: /* USER */ - user= get_field_char_utf8(f, &user_data); - break; - case 2: /* ROLE */ - role= get_field_char_utf8(f, &role_data); - break; - default: - DBUG_ASSERT(false); - } - } - } + DBUG_ASSERT(m_row_exists); - DBUG_ASSERT(user != NULL); - DBUG_ASSERT(host != NULL); - DBUG_ASSERT(role != NULL); + CHARSET_INFO *cs= &my_charset_utf8_bin; + String user(m_row.m_username, m_row.m_username_length, cs); + String role(m_row.m_rolename, m_row.m_rolename_length, cs); + String host(m_row.m_hostname, m_row.m_hostname_length, cs); - return delete_setup_actor(user, host, role); + return delete_setup_actor(&user, &host, &role); } diff --git a/storage/perfschema/table_setup_objects.cc b/storage/perfschema/table_setup_objects.cc index 33e360e989b..11fab913ac4 100644 --- a/storage/perfschema/table_setup_objects.cc +++ b/storage/perfschema/table_setup_objects.cc @@ -339,42 +339,15 @@ int table_setup_objects::delete_row_values(TABLE *table, const unsigned char *buf, Field **fields) { - int result; - Field *f; - enum_object_type object_type= OBJECT_TYPE_TABLE; - String object_schema_data("", 0, &my_charset_utf8_bin); - String object_name_data("", 0, &my_charset_utf8_bin); - String *object_schema= NULL; - String *object_name= NULL; + DBUG_ASSERT(m_row_exists); - for (; (f= *fields) ; fields++) - { - if (bitmap_is_set(table->read_set, f->field_index)) - { - switch(f->field_index) - { - case 0: /* OBJECT_TYPE */ - object_type= (enum_object_type) get_field_enum(f); - break; - case 1: /* OBJECT_SCHEMA */ - object_schema= get_field_varchar_utf8(f, &object_schema_data); - break; - case 2: /* OBJECT_NAME */ - object_name= get_field_varchar_utf8(f, &object_name_data); - break; - case 3: /* ENABLED */ - case 4: /* TIMED */ - break; - default: - DBUG_ASSERT(false); - } - } - } + CHARSET_INFO *cs= &my_charset_utf8_bin; + enum_object_type object_type= OBJECT_TYPE_TABLE; + String object_schema(m_row.m_schema_name, m_row.m_schema_name_length, cs); + String object_name(m_row.m_object_name, m_row.m_object_name_length, cs); - DBUG_ASSERT(object_schema != NULL); - DBUG_ASSERT(object_name != NULL); + int result= delete_setup_object(object_type, &object_schema, &object_name); - result= delete_setup_object(object_type, object_schema, object_name); if (result == 0) result= update_derived_flags(); return result; diff --git a/storage/perfschema/table_socket_instances.cc b/storage/perfschema/table_socket_instances.cc index f913c8fcc65..0fa1d2b1a3a 100644 --- a/storage/perfschema/table_socket_instances.cc +++ b/storage/perfschema/table_socket_instances.cc @@ -42,7 +42,7 @@ static const TABLE_FIELD_TYPE field_types[]= }, { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -205,7 +205,7 @@ int table_socket_instances::read_row_values(TABLE *table, break; case 2: /* THREAD_ID */ if (m_row.m_thread_id_set) - set_field_ulong(f, m_row.m_thread_id); + set_field_ulonglong(f, m_row.m_thread_id); else f->set_null(); break; diff --git a/storage/perfschema/table_socket_instances.h b/storage/perfschema/table_socket_instances.h index 2a80aeaa76a..080f11c1ba8 100644 --- a/storage/perfschema/table_socket_instances.h +++ b/storage/perfschema/table_socket_instances.h @@ -39,7 +39,7 @@ struct row_socket_instances /** Column OBJECT_INSTANCE_BEGIN */ const void *m_identity; /** Column THREAD_ID */ - uint m_thread_id; + ulonglong m_thread_id; /** True if thread_is is set */ bool m_thread_id_set; /** Column SOCKET_ID */ diff --git a/storage/perfschema/table_sync_instances.cc b/storage/perfschema/table_sync_instances.cc index 06889e735ba..9b53eb3ce57 100644 --- a/storage/perfschema/table_sync_instances.cc +++ b/storage/perfschema/table_sync_instances.cc @@ -43,7 +43,7 @@ static const TABLE_FIELD_TYPE mutex_field_types[]= }, { { C_STRING_WITH_LEN("LOCKED_BY_THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} } }; @@ -178,7 +178,7 @@ int table_mutex_instances::read_row_values(TABLE *table, break; case 2: /* LOCKED_BY_THREAD_ID */ if (m_row.m_locked) - set_field_ulong(f, m_row.m_locked_by_thread_id); + set_field_ulonglong(f, m_row.m_locked_by_thread_id); else f->set_null(); break; @@ -207,7 +207,7 @@ static const TABLE_FIELD_TYPE rwlock_field_types[]= }, { { C_STRING_WITH_LEN("WRITE_LOCKED_BY_THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -351,7 +351,7 @@ int table_rwlock_instances::read_row_values(TABLE *table, break; case 2: /* WRITE_LOCKED_BY_THREAD_ID */ if (m_row.m_write_locked) - set_field_ulong(f, m_row.m_write_locked_by_thread_id); + set_field_ulonglong(f, m_row.m_write_locked_by_thread_id); else f->set_null(); break; diff --git a/storage/perfschema/table_sync_instances.h b/storage/perfschema/table_sync_instances.h index b6fc78e1cd5..ff7b2765a11 100644 --- a/storage/perfschema/table_sync_instances.h +++ b/storage/perfschema/table_sync_instances.h @@ -45,7 +45,7 @@ struct row_mutex_instances /** True if column LOCKED_BY_THREAD_ID is not null. */ bool m_locked; /** Column LOCKED_BY_THREAD_ID. */ - ulong m_locked_by_thread_id; + ulonglong m_locked_by_thread_id; }; /** Table PERFORMANCE_SCHEMA.MUTEX_INSTANCES. */ @@ -102,7 +102,7 @@ struct row_rwlock_instances /** True if column WRITE_LOCKED_BY_THREAD_ID is not null. */ bool m_write_locked; /** Column WRITE_LOCKED_BY_THREAD_ID. */ - ulong m_write_locked_by_thread_id; + ulonglong m_write_locked_by_thread_id; /** Column READ_LOCKED_BY_COUNT. */ ulong m_readers; }; diff --git a/storage/perfschema/table_threads.cc b/storage/perfschema/table_threads.cc index 2104c24b65c..ef6c272c0a2 100644 --- a/storage/perfschema/table_threads.cc +++ b/storage/perfschema/table_threads.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2008, 2013, 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 @@ -26,7 +26,7 @@ static const TABLE_FIELD_TYPE field_types[]= { { { C_STRING_WITH_LEN("THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -41,7 +41,7 @@ static const TABLE_FIELD_TYPE field_types[]= }, { { C_STRING_WITH_LEN("PROCESSLIST_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -81,7 +81,7 @@ static const TABLE_FIELD_TYPE field_types[]= }, { { C_STRING_WITH_LEN("PARENT_THREAD_ID") }, - { C_STRING_WITH_LEN("int(11)") }, + { C_STRING_WITH_LEN("bigint(20)") }, { NULL, 0} }, { @@ -129,6 +129,7 @@ table_threads::table_threads() void table_threads::make_row(PFS_thread *pfs) { pfs_lock lock; + pfs_lock processlist_lock; PFS_thread_class *safe_class; m_row_exists= false; @@ -142,7 +143,7 @@ void table_threads::make_row(PFS_thread *pfs) m_row.m_thread_internal_id= pfs->m_thread_internal_id; m_row.m_parent_thread_internal_id= pfs->m_parent_thread_internal_id; - m_row.m_thread_id= pfs->m_thread_id; + m_row.m_processlist_id= pfs->m_processlist_id; m_row.m_name= safe_class->m_name; m_row.m_name_length= safe_class->m_name_length; @@ -166,12 +167,30 @@ void table_threads::make_row(PFS_thread *pfs) m_row.m_command= pfs->m_command; m_row.m_start_time= pfs->m_start_time; + + /* Protect this reader against attribute changes. */ + pfs->m_processlist_lock.begin_optimistic_lock(&processlist_lock); + /* FIXME: need to copy it ? */ m_row.m_processlist_state_ptr= pfs->m_processlist_state_ptr; m_row.m_processlist_state_length= pfs->m_processlist_state_length; /* FIXME: need to copy it ? */ m_row.m_processlist_info_ptr= pfs->m_processlist_info_ptr; m_row.m_processlist_info_length= pfs->m_processlist_info_length; + + if (! pfs->m_processlist_lock.end_optimistic_lock(& processlist_lock)) + { + /* + Columns PROCESSLIST_STATE or PROCESSLIST_INFO are being + updated while we read them, and are unsafe to use. + Do not discard the entire row. + Do not loop waiting for a stable value. + Just return NULL values for these columns. + */ + m_row.m_processlist_state_length= 0; + m_row.m_processlist_info_length= 0; + } + m_row.m_enabled_ptr= &pfs->m_enabled; if (pfs->m_lock.end_optimistic_lock(& lock)) @@ -200,20 +219,20 @@ int table_threads::read_row_values(TABLE *table, switch(f->field_index) { case 0: /* THREAD_ID */ - set_field_ulong(f, m_row.m_thread_internal_id); + set_field_ulonglong(f, m_row.m_thread_internal_id); break; case 1: /* NAME */ set_field_varchar_utf8(f, m_row.m_name, m_row.m_name_length); break; case 2: /* TYPE */ - if (m_row.m_thread_id != 0) + if (m_row.m_processlist_id != 0) set_field_varchar_utf8(f, "FOREGROUND", 10); else set_field_varchar_utf8(f, "BACKGROUND", 10); break; case 3: /* PROCESSLIST_ID */ - if (m_row.m_thread_id != 0) - set_field_ulong(f, m_row.m_thread_id); + if (m_row.m_processlist_id != 0) + set_field_ulonglong(f, m_row.m_processlist_id); else f->set_null(); break; @@ -239,7 +258,7 @@ int table_threads::read_row_values(TABLE *table, f->set_null(); break; case 7: /* PROCESSLIST_COMMAND */ - if (m_row.m_thread_id != 0) + if (m_row.m_processlist_id != 0) set_field_varchar_utf8(f, command_name[m_row.m_command].str, command_name[m_row.m_command].length); else @@ -271,7 +290,7 @@ int table_threads::read_row_values(TABLE *table, break; case 11: /* PARENT_THREAD_ID */ if (m_row.m_parent_thread_internal_id != 0) - set_field_ulong(f, m_row.m_parent_thread_internal_id); + set_field_ulonglong(f, m_row.m_parent_thread_internal_id); else f->set_null(); break; diff --git a/storage/perfschema/table_threads.h b/storage/perfschema/table_threads.h index 9819822f8c8..bce45c0cbce 100644 --- a/storage/perfschema/table_threads.h +++ b/storage/perfschema/table_threads.h @@ -32,9 +32,9 @@ struct PFS_thread; struct row_threads { /** Column THREAD_ID. */ - ulong m_thread_internal_id; + ulonglong m_thread_internal_id; /** Column PROCESSLIST_ID. */ - ulong m_thread_id; + ulonglong m_processlist_id; /** Column NAME. */ const char* m_name; /** Length in bytes of @c m_name. */ @@ -66,7 +66,7 @@ struct row_threads /** Column INSTRUMENTED. */ bool *m_enabled_ptr; /** Column PARENT_THREAD_ID. */ - ulong m_parent_thread_internal_id; + ulonglong m_parent_thread_internal_id; }; /** Table PERFORMANCE_SCHEMA.THREADS. */ diff --git a/storage/perfschema/table_tiws_by_index_usage.cc b/storage/perfschema/table_tiws_by_index_usage.cc index d354c40d3ed..71455793516 100644 --- a/storage/perfschema/table_tiws_by_index_usage.cc +++ b/storage/perfschema/table_tiws_by_index_usage.cc @@ -290,15 +290,16 @@ int table_tiws_by_index_usage::rnd_next(void) table_share= &table_share_array[m_pos.m_index_1]; if (table_share->m_lock.is_populated()) { - if (m_pos.m_index_2 < table_share->m_key_count) + uint safe_key_count= sanitize_index_count(table_share->m_key_count); + if (m_pos.m_index_2 < safe_key_count) { make_row(table_share, m_pos.m_index_2); m_next_pos.set_after(&m_pos); return 0; } - if (m_pos.m_index_2 <= MAX_KEY) + if (m_pos.m_index_2 <= MAX_INDEXES) { - m_pos.m_index_2= MAX_KEY; + m_pos.m_index_2= MAX_INDEXES; make_row(table_share, m_pos.m_index_2); m_next_pos.set_after(&m_pos); return 0; @@ -319,12 +320,13 @@ table_tiws_by_index_usage::rnd_pos(const void *pos) table_share= &table_share_array[m_pos.m_index_1]; if (table_share->m_lock.is_populated()) { - if (m_pos.m_index_2 < table_share->m_key_count) + uint safe_key_count= sanitize_index_count(table_share->m_key_count); + if (m_pos.m_index_2 < safe_key_count) { make_row(table_share, m_pos.m_index_2); return 0; } - if (m_pos.m_index_2 == MAX_KEY) + if (m_pos.m_index_2 == MAX_INDEXES) { make_row(table_share, m_pos.m_index_2); return 0; diff --git a/storage/perfschema/unittest/CMakeLists.txt b/storage/perfschema/unittest/CMakeLists.txt index 6be5b0f9a50..d98b13622d7 100644 --- a/storage/perfschema/unittest/CMakeLists.txt +++ b/storage/perfschema/unittest/CMakeLists.txt @@ -1,5 +1,4 @@ -# Copyright (c) 2009, 2010 Sun Microsystems, Inc. -# Use is subject to license terms. +# Copyright (c) 2009, 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 @@ -11,18 +10,18 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/mysql ${CMAKE_SOURCE_DIR}/regex ${CMAKE_SOURCE_DIR}/sql - ${CMAKE_SOURCE_DIR}/extra/yassl/include + ${SSL_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/unittest/mytap ${CMAKE_SOURCE_DIR}/storage/perfschema) -ADD_DEFINITIONS(-DMYSQL_SERVER) +ADD_DEFINITIONS(-DMYSQL_SERVER ${SSL_DEFINES}) MY_ADD_TESTS(pfs_instr_class pfs_instr_class-oom pfs_instr pfs_instr-oom pfs_account-oom pfs_host-oom pfs_timer pfs_user-oom pfs EXT "cc" LINK_LIBRARIES perfschema mysys) diff --git a/storage/perfschema/unittest/pfs-t.cc b/storage/perfschema/unittest/pfs-t.cc index c673582ba53..9211443bcca 100644 --- a/storage/perfschema/unittest/pfs-t.cc +++ b/storage/perfschema/unittest/pfs-t.cc @@ -111,6 +111,7 @@ void test_bootstrap() param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; param.m_digest_sizing= 0; + param.m_session_connect_attrs_sizing= 0; boot= initialize_performance_schema(& param); ok(boot != NULL, "boot"); @@ -168,6 +169,7 @@ PSI * load_perfschema() param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; param.m_digest_sizing= 0; + param.m_session_connect_attrs_sizing= 0; /* test_bootstrap() covered this, assuming it just works */ boot= initialize_performance_schema(& param); @@ -759,21 +761,21 @@ void test_init_disabled() /* disabled S-A + disabled T-1: no instrumentation */ socket_class_A->m_enabled= false; - socket_A1= psi->init_socket(socket_key_A, NULL); + socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 == NULL, "socket_A1 not instrumented"); /* enabled S-A + disabled T-1: instrumentation (for later) */ socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(socket_key_A, NULL); + socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 != NULL, "socket_A1 instrumented"); /* broken key + disabled T-1: no instrumentation */ socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(0, NULL); + socket_A1= psi->init_socket(0, NULL, NULL, 0); ok(socket_A1 == NULL, "socket key 0 not instrumented"); - socket_A1= psi->init_socket(99, NULL); + socket_A1= psi->init_socket(99, NULL, NULL, 0); ok(socket_A1 == NULL, "broken socket key not instrumented"); /* Pretend thread T-1 is enabled */ @@ -892,16 +894,16 @@ void test_init_disabled() /* enabled S-A + enabled T-1: instrumentation */ socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(socket_key_A, NULL); + socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 != NULL, "instrumented"); psi->destroy_socket(socket_A1); /* broken key + enabled T-1: no instrumentation */ socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(0, NULL); + socket_A1= psi->init_socket(0, NULL, NULL, 0); ok(socket_A1 == NULL, "not instrumented"); - socket_A1= psi->init_socket(99, NULL); + socket_A1= psi->init_socket(99, NULL, NULL, 0); ok(socket_A1 == NULL, "not instrumented"); /* Pretend the running thread is not instrumented */ @@ -996,21 +998,21 @@ void test_init_disabled() /* disabled S-A + unknown thread: no instrumentation */ socket_class_A->m_enabled= false; - socket_A1= psi->init_socket(socket_key_A, NULL); + socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 == NULL, "socket_A1 not instrumented"); /* enabled S-A + unknown thread: instrumentation (for later) */ socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(socket_key_A, NULL); + socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 != NULL, "socket_A1 instrumented"); /* broken key + unknown thread: no instrumentation */ socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(0, NULL); + socket_A1= psi->init_socket(0, NULL, NULL, 0); ok(socket_A1 == NULL, "socket key 0 not instrumented"); - socket_A1= psi->init_socket(99, NULL); + socket_A1= psi->init_socket(99, NULL, NULL, 0); ok(socket_A1 == NULL, "broken socket key not instrumented"); shutdown_performance_schema(); @@ -1126,7 +1128,7 @@ void test_locker_disabled() ok(file_A1 != NULL, "instrumented"); socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(socket_key_A, NULL); + socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 != NULL, "instrumented"); /* Socket lockers require a thread owner */ @@ -1294,10 +1296,10 @@ void test_locker_disabled() cond_locker= psi->start_cond_wait(&cond_state, cond_A1, mutex_A1, PSI_COND_WAIT, __FILE__, __LINE__); ok(cond_locker != NULL, "locker"); psi->end_cond_wait(cond_locker, 0); - file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_OPEN, "xxx", NULL); + file_locker= psi->get_thread_file_name_locker(&file_state, file_key_A, PSI_FILE_STREAM_OPEN, "xxx", NULL); ok(file_locker != NULL, "locker"); psi->start_file_open_wait(file_locker, __FILE__, __LINE__); - psi->end_file_open_wait(file_locker); + psi->end_file_open_wait(file_locker, NULL); file_locker= psi->get_thread_file_stream_locker(&file_state, file_A1, PSI_FILE_READ); ok(file_locker != NULL, "locker"); psi->start_file_wait(file_locker, 10, __FILE__, __LINE__); @@ -1314,7 +1316,7 @@ void test_locker_disabled() /* ---------------------------------------------- */ socket_class_A->m_enabled= true; - socket_A1= psi->init_socket(socket_key_A, NULL); + socket_A1= psi->init_socket(socket_key_A, NULL, NULL, 0); ok(socket_A1 != NULL, "instrumented"); /* Socket thread owner has not been set */ socket_locker= psi->start_socket_wait(&socket_state, socket_A1, PSI_SOCKET_SEND, 12, "foo.cc", 12); @@ -1485,6 +1487,8 @@ void test_event_name_index() memset(& param, 0xFF, sizeof(param)); param.m_enabled= true; + /* NOTE: Need to add 3 to each index: table io, table lock, idle */ + /* Per mutex info waits should be at [0..9] */ param.m_mutex_class_sizing= 10; /* Per rwlock info waits should be at [10..29] */ @@ -1509,6 +1513,7 @@ void test_event_name_index() param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; param.m_digest_sizing= 0; + param.m_session_connect_attrs_sizing= 0; param.m_mutex_sizing= 0; param.m_rwlock_sizing= 0; @@ -1540,10 +1545,10 @@ void test_event_name_index() psi->register_mutex("X", dummy_mutexes, 2); mutex_class= find_mutex_class(dummy_mutex_key_1); ok(mutex_class != NULL, "mutex class 1"); - ok(mutex_class->m_event_name_index == 0, "index 0"); + ok(mutex_class->m_event_name_index == 3, "index 3"); mutex_class= find_mutex_class(dummy_mutex_key_2); ok(mutex_class != NULL, "mutex class 2"); - ok(mutex_class->m_event_name_index == 1, "index 1"); + ok(mutex_class->m_event_name_index == 4, "index 4"); PFS_rwlock_class *rwlock_class; PSI_rwlock_key dummy_rwlock_key_1; @@ -1557,10 +1562,10 @@ void test_event_name_index() psi->register_rwlock("X", dummy_rwlocks, 2); rwlock_class= find_rwlock_class(dummy_rwlock_key_1); ok(rwlock_class != NULL, "rwlock class 1"); - ok(rwlock_class->m_event_name_index == 10, "index 10"); + ok(rwlock_class->m_event_name_index == 13, "index 13"); rwlock_class= find_rwlock_class(dummy_rwlock_key_2); ok(rwlock_class != NULL, "rwlock class 2"); - ok(rwlock_class->m_event_name_index == 11, "index 11"); + ok(rwlock_class->m_event_name_index == 14, "index 14"); PFS_cond_class *cond_class; PSI_cond_key dummy_cond_key_1; @@ -1574,10 +1579,10 @@ void test_event_name_index() psi->register_cond("X", dummy_conds, 2); cond_class= find_cond_class(dummy_cond_key_1); ok(cond_class != NULL, "cond class 1"); - ok(cond_class->m_event_name_index == 30, "index 30"); + ok(cond_class->m_event_name_index == 33, "index 33"); cond_class= find_cond_class(dummy_cond_key_2); ok(cond_class != NULL, "cond class 2"); - ok(cond_class->m_event_name_index == 31, "index 31"); + ok(cond_class->m_event_name_index == 34, "index 34"); PFS_file_class *file_class; PSI_file_key dummy_file_key_1; @@ -1591,10 +1596,10 @@ void test_event_name_index() psi->register_file("X", dummy_files, 2); file_class= find_file_class(dummy_file_key_1); ok(file_class != NULL, "file class 1"); - ok(file_class->m_event_name_index == 70, "index 70"); + ok(file_class->m_event_name_index == 73, "index 73"); file_class= find_file_class(dummy_file_key_2); ok(file_class != NULL, "file class 2"); - ok(file_class->m_event_name_index == 71, "index 71"); + ok(file_class->m_event_name_index == 74, "index 74"); PFS_socket_class *socket_class; PSI_socket_key dummy_socket_key_1; @@ -1608,13 +1613,13 @@ void test_event_name_index() psi->register_socket("X", dummy_sockets, 2); socket_class= find_socket_class(dummy_socket_key_1); ok(socket_class != NULL, "socket class 1"); - ok(socket_class->m_event_name_index == 150, "index 150"); + ok(socket_class->m_event_name_index == 153, "index 153"); socket_class= find_socket_class(dummy_socket_key_2); ok(socket_class != NULL, "socket class 2"); - ok(socket_class->m_event_name_index == 151, "index 151"); + ok(socket_class->m_event_name_index == 154, "index 154"); - ok(global_table_io_class.m_event_name_index == 310, "index 310"); - ok(global_table_lock_class.m_event_name_index == 311, "index 311"); + ok(global_table_io_class.m_event_name_index == 0, "index 0"); + ok(global_table_lock_class.m_event_name_index == 1, "index 1"); ok(wait_class_max= 313, "313 event names"); // 3 global classes } diff --git a/storage/perfschema/unittest/pfs_account-oom-t.cc b/storage/perfschema/unittest/pfs_account-oom-t.cc index 214ac1c5995..8fa6f340cbf 100644 --- a/storage/perfschema/unittest/pfs_account-oom-t.cc +++ b/storage/perfschema/unittest/pfs_account-oom-t.cc @@ -59,6 +59,7 @@ void test_oom() param.m_statement_class_sizing= 50; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; /* Setup */ diff --git a/storage/perfschema/unittest/pfs_connect_attr-t.cc b/storage/perfschema/unittest/pfs_connect_attr-t.cc new file mode 100644 index 00000000000..7bee1d063a1 --- /dev/null +++ b/storage/perfschema/unittest/pfs_connect_attr-t.cc @@ -0,0 +1,345 @@ +/* Copyright (c) 2008, 2011, 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 + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ + +#include <my_global.h> +#include <my_pthread.h> +#include <pfs_server.h> +#include <pfs_instr_class.h> +#include <pfs_instr.h> +#include <pfs_global.h> +#include <tap.h> + + +#include <string.h> +#include <memory.h> + +/* test helpers, to inspect data */ +bool read_nth_attr(const char *connect_attrs, uint connect_attrs_length, + const CHARSET_INFO *connect_attrs_cs, + uint ordinal, + char *attr_name, uint max_attr_name, + uint *attr_name_length, + char *attr_value, uint max_attr_value, + uint *attr_value_length); + +void test_blob_parser() +{ + char name[100], value[4096]; + unsigned char packet[10000], *ptr; + uint name_len, value_len, idx, packet_length; + bool result; + const CHARSET_INFO *cs= &my_charset_utf8_bin; + + diag("test_blob_parser"); + + result= read_nth_attr("", 0, cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "zero length blob"); + + + result= read_nth_attr("\x1", 1, cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "invalid key length"); + + + result= read_nth_attr("\x2k1\x1", 4, cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "invalid value length"); + + + result= read_nth_attr("\x2k1\x2v1", 6, cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "one pair return"); + ok(name_len == 2, "one pair attr name length"); + ok(!strncmp(name, "k1", name_len), "one pair attr name"); + ok(value_len == 2, "one pair value length"); + ok(!strncmp(value, "v1", value_len), "one pair value"); + + result= read_nth_attr("\x2k1\x2v1", 6, cs, 1, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "no second arg"); + + result= read_nth_attr("\x2k1\x2v1\x2k2\x2v2", 12, cs, 1, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "two pairs return"); + ok(name_len == 2, "two pairs attr name length"); + ok(!strncmp(name, "k2", name_len), "two pairs attr name"); + ok(value_len == 2, "two pairs value length"); + ok(!strncmp(value, "v2", value_len), "two pairs value"); + + result= read_nth_attr("\x2k1\xff\x2k2\x2v2", 12, cs, 1, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "two pairs first value bad return"); + + result= read_nth_attr("\x2k1\x2v1\x2k2\x2v2", 10, cs, 1, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "two pairs wrong global length"); + + result= read_nth_attr("\x21z123456789z123456789z123456789z12\x2v1", 37, cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "attr name overflow"); + ok(name_len == 32, "attr name overflow length"); + ok(!strncmp(name, "z123456789z123456789z123456789z1", name_len), + "attr name overflow name"); + ok(value_len == 2, "attr name overflow value length"); + ok(!strncmp(value, "v1", value_len), "attr name overflow value"); + + packet[0]= 2; + packet[1]= 'k'; + packet[2]= '1'; + ptr= net_store_length(packet + 3, 1025); + for (idx= 0; idx < 1025; idx++) + *ptr++= '0' + (idx % 10); + packet_length= (uint) (ptr - packet); + result= read_nth_attr((char *) packet, packet_length, cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "attr value overflow"); + ok(name_len == 2, "attr value overflow length"); + ok(!strncmp(name, "k1", name_len), "attr value overflow name"); + ok(value_len == 1024, "attr value overflow value length"); + for (idx= 0; idx < 1024; idx++) + { + if (value[idx] != (char) ('0' + (idx % 10))) + break; + } + ok (idx == 1024, "attr value overflow value"); + + result= read_nth_attr("\x21z123456789z123456789z123456789z12\x2v1\x2k2\x2v2", + 43, cs, 1, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "prev attr name overflow"); + ok(name_len == 2, "prev attr name overflow length"); + ok(!strncmp(name, "k2", name_len), + "prev attr name overflow name"); + ok(value_len == 2, "prev attr name overflow value length"); + ok(!strncmp(value, "v2", value_len), "prev attr name overflow value"); + + + packet[1]= 'k'; + packet[2]= '1'; + packet[3]= 2; + packet[4]= 'v'; + packet[5]= '1'; + + for(idx= 251; idx < 256; idx++) + { + packet[0]= idx; + result= read_nth_attr((char *) packet, 6, cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "invalid string length %d", idx); + } + + memset(packet, 0, sizeof(packet)); + for (idx=0; idx < 1660 /* *6 = 9960 */; idx++) + memcpy(packet + idx * 6, "\x2k1\x2v1", 6); + result= read_nth_attr((char *) packet, 8192, cs, 1364, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "last valid attribute %d", 1364); + result= read_nth_attr((char *) packet, 8192, cs, 1365, + name, 32, &name_len, value, 1024, &value_len); + ok(result == false, "first attribute that's cut %d", 1365); +} + +void test_multibyte_lengths() +{ + char name[100], value[4096]; + uint name_len, value_len; + bool result; + const CHARSET_INFO *cs= &my_charset_utf8_bin; + + unsigned char var_len_packet[] = { + 252, 2, 0, 'k', '1', + 253, 2, 0, 0, 'v', '1', + 254, 2, 0, 0, 0, 0, 0, 0, 0, 'k', '2', + 254, 2, 0, 0, 0, 0, 0, 0, 0, 'v', '2' + }; + + result= read_nth_attr((char *) var_len_packet, sizeof(var_len_packet), cs, 0, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "multibyte lengths return"); + ok(name_len == 2, "multibyte lengths name length"); + ok(!strncmp(name, "k1", name_len), "multibyte lengths attr name"); + ok(value_len == 2, "multibyte lengths value length"); + ok(!strncmp(value, "v1", value_len), "multibyte lengths value"); + + result= read_nth_attr((char *) var_len_packet, sizeof(var_len_packet), cs, 1, + name, 32, &name_len, value, 1024, &value_len); + ok(result == true, "multibyte lengths second attr return"); + ok(name_len == 2, "multibyte lengths second attr name length"); + ok(!strncmp(name, "k2", name_len), "multibyte lengths second attr attr name"); + ok(value_len == 2, "multibyte lengths value length"); + ok(!strncmp(value, "v2", value_len), "multibyte lengths second attr value"); +} + + +void test_utf8_parser() +{ + /* utf8 max byte length per character is 6 */ + char name[33 * 6], value[1024 * 6], packet[1500 * 6], *ptr; + uint name_len, value_len; + bool result; + const CHARSET_INFO *cs= &my_charset_utf8_bin; + + /* note : this is encoded in utf-8 */ + const char *attr1= "Георги"; + const char *val1= "Кодинов"; + const char *attr2= "Пловдив"; + const char *val2= "България"; + + ptr= packet; + *ptr++= strlen(attr1); + memcpy(ptr, attr1, strlen(attr1)); + ptr+= strlen(attr1); + *ptr++= strlen(val1); + memcpy(ptr, val1, strlen(val1)); + ptr+= strlen(val1); + + *ptr++= strlen(attr2); + memcpy(ptr, attr2, strlen(attr2)); + ptr+= strlen(attr2); + *ptr++= strlen(val2); + memcpy(ptr, val2, strlen(val2)); + ptr+= strlen(val2); + + diag("test_utf8_parser attr pair #1"); + + result= read_nth_attr((char *) packet, ptr - packet, cs, 0, + name, sizeof(name), &name_len, + value, sizeof(value), &value_len); + ok(result == true, "return"); + ok(name_len == strlen(attr1), "name length"); + ok(!strncmp(name, attr1, name_len), "attr name"); + ok(value_len == strlen(val1), "value length"); + ok(!strncmp(value, val1, value_len), "value"); + + diag("test_utf8_parser attr pair #2"); + result= read_nth_attr((char *) packet, ptr - packet, cs, 1, + name, sizeof(name), &name_len, + value, sizeof(value), &value_len); + ok(result == true, "return"); + ok(name_len == strlen(attr2), "name length"); + ok(!strncmp(name, attr2, name_len), "attr name"); + ok(value_len == strlen(val2), "value length"); + ok(!strncmp(value, val2, value_len), "value"); +} + + +void test_utf8_parser_bad_encoding() +{ + /* utf8 max byte length per character is 3*/ + char name[33 * 3], value[1024 * 3], packet[1500 * 3], *ptr; + uint name_len, value_len; + bool result; + const CHARSET_INFO *cs= &my_charset_utf8_bin; + + /* note : this is encoded in utf-8 */ + const char *attr= "Георги"; + const char *val= "Кодинов"; + + ptr= packet; + *ptr++= strlen(attr); + memcpy(ptr, attr, strlen(attr)); + ptr[0]= 0xFA; // invalid UTF-8 char + ptr+= strlen(attr); + *ptr++= strlen(val); + memcpy(ptr, val, strlen(val)); + ptr+= strlen(val); + + diag("test_utf8_parser_bad_encoding"); + + result= read_nth_attr((char *) packet, ptr - packet, cs, 0, + name, sizeof(name), &name_len, + value, sizeof(value), &value_len); + ok(result == false, "return"); +} + +const CHARSET_INFO *cs_cp1251; + +void test_cp1251_parser() +{ + /* utf8 max byte length per character is 3*/ + char name[33 * 3], value[1024 * 3], packet[1500 * 3], *ptr; + uint name_len, value_len; + bool result; + + /* note : this is Георги in windows-1251 */ + const char *attr1= "\xc3\xe5\xee\xf0\xe3\xe8"; + /* note : this is Кодинов in windows-1251 */ + const char *val1= "\xca\xee\xe4\xe8\xed\xee\xe2"; + /* note : this is Пловдив in windows-1251 */ + const char *attr2= "\xcf\xeb\xee\xe2\xe4\xe8\xe2"; + /* note : this is България in windows-1251 */ + const char *val2= "\xc1\xfa\xeb\xe3\xe0\xf0\xe8\xff"; + + ptr= packet; + *ptr++= strlen(attr1); + memcpy(ptr, attr1, strlen(attr1)); + ptr+= strlen(attr1); + *ptr++= strlen(val1); + memcpy(ptr, val1, strlen(val1)); + ptr+= strlen(val1); + + *ptr++= strlen(attr2); + memcpy(ptr, attr2, strlen(attr2)); + ptr+= strlen(attr2); + *ptr++= strlen(val2); + memcpy(ptr, val2, strlen(val2)); + ptr+= strlen(val2); + + diag("test_cp1251_parser attr pair #1"); + + result= read_nth_attr((char *) packet, ptr - packet, cs_cp1251, 0, + name, sizeof(name), &name_len, + value, sizeof(value), &value_len); + ok(result == true, "return"); + /* need to compare to the UTF-8 equivalents */ + ok(name_len == strlen("Георги"), "name length"); + ok(!strncmp(name, "Георги", name_len), "attr name"); + ok(value_len == strlen("Кодинов"), "value length"); + ok(!strncmp(value, "Кодинов", value_len), "value"); + + diag("test_cp1251_parser attr pair #2"); + result= read_nth_attr((char *) packet, ptr - packet, cs_cp1251, 1, + name, sizeof(name), &name_len, + value, sizeof(value), &value_len); + ok(result == true, "return"); + /* need to compare to the UTF-8 equivalents */ + ok(name_len == strlen("Пловдив"), "name length"); + ok(!strncmp(name, "Пловдив", name_len), "attr name"); + ok(value_len == strlen("България"), "value length"); + ok(!strncmp(value, "България", value_len), "value"); +} + + +void do_all_tests() +{ + test_blob_parser(); + test_multibyte_lengths(); + test_utf8_parser(); + test_utf8_parser_bad_encoding(); + test_cp1251_parser(); +} + +int main(int, char **) +{ + MY_INIT("pfs_connect_attr-t"); + + cs_cp1251= get_charset_by_csname("cp1251", MY_CS_PRIMARY, MYF(0)); + if (!cs_cp1251) + diag("skipping the cp1251 tests : missing character set"); + plan(59 + (cs_cp1251 ? 10 : 0)); + do_all_tests(); + return 0; +} diff --git a/storage/perfschema/unittest/pfs_host-oom-t.cc b/storage/perfschema/unittest/pfs_host-oom-t.cc index 455de9bf9ca..3d3dfd6d05e 100644 --- a/storage/perfschema/unittest/pfs_host-oom-t.cc +++ b/storage/perfschema/unittest/pfs_host-oom-t.cc @@ -59,6 +59,7 @@ void test_oom() param.m_statement_class_sizing= 50; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; /* Setup */ diff --git a/storage/perfschema/unittest/pfs_instr-oom-t.cc b/storage/perfschema/unittest/pfs_instr-oom-t.cc index 0bc329ccddc..18c0029776d 100644 --- a/storage/perfschema/unittest/pfs_instr-oom-t.cc +++ b/storage/perfschema/unittest/pfs_instr-oom-t.cc @@ -63,6 +63,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -98,6 +99,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -133,6 +135,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -168,6 +171,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -201,6 +205,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -236,6 +241,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -271,6 +277,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -308,6 +315,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 2; init_event_name_sizing(& param); @@ -341,6 +349,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 2; init_event_name_sizing(& param); @@ -383,8 +392,9 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; - stub_alloc_fails_after_count= 2; + stub_alloc_fails_after_count= 1; init_event_name_sizing(& param); rc= init_instruments(& param); ok(rc == 1, "oom (per thread waits)"); @@ -417,6 +427,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 3; init_event_name_sizing(& param); @@ -451,6 +462,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 2; init_event_name_sizing(& param); @@ -485,6 +497,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 10; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 2; init_event_name_sizing(& param); @@ -519,6 +532,7 @@ void test_oom() param.m_statement_class_sizing= 50; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 2; init_event_name_sizing(& param); @@ -553,6 +567,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 1; init_event_name_sizing(& param); @@ -587,6 +602,7 @@ void test_oom() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 3; init_event_name_sizing(& param); @@ -624,6 +640,7 @@ void test_oom() param.m_statement_class_sizing= 20; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_session_connect_attrs_sizing= 0; stub_alloc_fails_after_count= 3; init_event_name_sizing(& param); diff --git a/storage/perfschema/unittest/pfs_instr-t.cc b/storage/perfschema/unittest/pfs_instr-t.cc index fd71a722a50..fab22b203d3 100644 --- a/storage/perfschema/unittest/pfs_instr-t.cc +++ b/storage/perfschema/unittest/pfs_instr-t.cc @@ -60,6 +60,8 @@ void test_no_instruments() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_digest_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -117,6 +119,8 @@ void test_no_instances() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_digest_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -153,19 +157,19 @@ void test_no_instances() PFS_thread fake_thread; fake_thread.m_filename_hash_pins= NULL; - file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5); + file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true); ok(file == NULL, "no file"); ok(file_lost == 1, "lost 1"); - file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5); + file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true); ok(file == NULL, "no file"); ok(file_lost == 2, "lost 2"); init_file_hash(); - file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5); + file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true); ok(file == NULL, "no file"); ok(file_lost == 3, "lost 3"); - file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5); + file= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true); ok(file == NULL, "no file"); ok(file_lost == 4, "lost 4"); @@ -173,7 +177,7 @@ void test_no_instances() int size= sizeof(long_file_name); memset(long_file_name, 'X', size); - file= find_or_create_file(& fake_thread, & dummy_file_class, long_file_name, size); + file= find_or_create_file(& fake_thread, & dummy_file_class, long_file_name, size, true); ok(file == NULL, "no file"); ok(file_lost == 5, "lost 5"); @@ -184,10 +188,10 @@ void test_no_instances() ok(table == NULL, "no table"); ok(table_lost == 2, "lost 2"); - socket= create_socket(& dummy_socket_class, NULL); + socket= create_socket(& dummy_socket_class, NULL, NULL, 0); ok(socket == NULL, "no socket"); ok(socket_lost == 1, "lost 1"); - socket= create_socket(& dummy_socket_class, NULL); + socket= create_socket(& dummy_socket_class, NULL, NULL, 0); ok(socket == NULL, "no socket"); ok(socket_lost == 2, "lost 2"); @@ -255,6 +259,8 @@ void test_with_instances() param.m_statement_class_sizing= 0; param.m_events_statements_history_sizing= 0; param.m_events_statements_history_long_sizing= 0; + param.m_digest_sizing= 0; + param.m_session_connect_attrs_sizing= 0; init_event_name_sizing(& param); rc= init_instruments(& param); @@ -325,50 +331,50 @@ void test_with_instances() PFS_thread fake_thread; fake_thread.m_filename_hash_pins= NULL; - file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5); + file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true); ok(file_1 == NULL, "no file"); ok(file_lost == 1, "lost 1"); - file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5); + file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy", 5, true); ok(file_1 == NULL, "no file"); ok(file_lost == 2, "lost 2"); init_file_hash(); file_lost= 0; - file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7); + file_1= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7, true); ok(file_1 != NULL, "file"); ok(file_1->m_file_stat.m_open_count == 1, "open count 1"); ok(file_lost == 0, "not lost"); - file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7); + file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_A", 7, true); ok(file_1 == file_2, "same file"); ok(file_1->m_file_stat.m_open_count == 2, "open count 2"); ok(file_lost == 0, "not lost"); release_file(file_2); ok(file_1->m_file_stat.m_open_count == 1, "open count 1"); - file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_B", 7); + file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_B", 7, true); ok(file_2 != NULL, "file"); ok(file_lost == 0, "not lost"); - file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_C", 7); + file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_C", 7, true); ok(file_2 == NULL, "no file"); ok(file_lost == 1, "lost"); release_file(file_1); /* the file still exists, not destroyed */ ok(file_1->m_file_stat.m_open_count == 0, "open count 0"); - file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_D", 7); + file_2= find_or_create_file(& fake_thread, & dummy_file_class, "dummy_D", 7, true); ok(file_2 == NULL, "no file"); ok(file_lost == 2, "lost"); - socket_1= create_socket(& dummy_socket_class, NULL); + socket_1= create_socket(& dummy_socket_class, NULL, NULL, 0); ok(socket_1 != NULL, "socket"); ok(socket_lost == 0, "not lost"); - socket_2= create_socket(& dummy_socket_class, NULL); + socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0); ok(socket_2 != NULL, "socket"); ok(socket_lost == 0, "not lost"); - socket_2= create_socket(& dummy_socket_class, NULL); + socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0); ok(socket_2 == NULL, "no socket"); ok(socket_lost == 1, "lost 1"); destroy_socket(socket_1); - socket_2= create_socket(& dummy_socket_class, NULL); + socket_2= create_socket(& dummy_socket_class, NULL, NULL, 0); ok(socket_2 != NULL, "socket"); ok(socket_lost == 1, "no new loss"); diff --git a/storage/perfschema/unittest/pfs_instr_class-t.cc b/storage/perfschema/unittest/pfs_instr_class-t.cc index 0ec224cbae3..706c5724a80 100644 --- a/storage/perfschema/unittest/pfs_instr_class-t.cc +++ b/storage/perfschema/unittest/pfs_instr_class-t.cc @@ -475,6 +475,7 @@ void test_table_registration() #endif } +#ifdef LATER void set_wait_stat(PFS_instr_class *klass) { PFS_single_stat *stat; @@ -501,6 +502,7 @@ bool is_empty_stat(PFS_instr_class *klass) return false; return true; } +#endif void test_instruments_reset() { |